From fijal at codespeak.net Fri May 1 00:07:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:07:52 +0200 (CEST) Subject: [pypy-svn] r64893 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090430220752.9FDA5168522@codespeak.net> Author: fijal Date: Fri May 1 00:07:51 2009 New Revision: 64893 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Log: respect the DEBUG flag. I think this is the first JIT that can be made not print anything at all :) 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 May 1 00:07:51 2009 @@ -88,6 +88,8 @@ # ____________________________________________________________ def compile_fresh_loop(metainterp, old_loops, greenkey, start): + from pypy.jit.metainterp.pyjitpl import DEBUG + history = metainterp.history loop = create_empty_loop(metainterp) loop.greenkey = greenkey @@ -101,7 +103,7 @@ old_loop = metainterp_sd.optimize_loop(metainterp_sd.options, old_loops, loop, metainterp.cpu) if old_loop is not None: - if we_are_translated(): + if we_are_translated() and DEBUG > 0: debug_print("reusing old loop") return old_loop history.source_link = loop @@ -119,7 +121,9 @@ loop._ignore_during_counting = True log.info("compiled new " + type) else: - debug_print("compiled new " + type) + from pypy.jit.metainterp.pyjitpl import DEBUG + if DEBUG > 0: + debug_print("compiled new " + type) # ____________________________________________________________ From fijal at codespeak.net Fri May 1 00:13:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:13:38 +0200 (CEST) Subject: [pypy-svn] r64894 - pypy/build/bot2/pypybuildbot Message-ID: <20090430221338.DD244169E54@codespeak.net> Author: fijal Date: Fri May 1 00:13:31 2009 New Revision: 64894 Modified: pypy/build/bot2/pypybuildbot/builds.py pypy/build/bot2/pypybuildbot/master.py Log: Add a jit lib-python build. (yay!) Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri May 1 00:13:31 2009 @@ -62,24 +62,6 @@ self.command = (self.command + translationArgs + [self.translationTarget] + targetArgs) -class TranslateJIT(ShellCmd): - name = "translate_jit" - description = ["translating"] - descriptionDone = ["translation"] - - command = ["python", "../../translator/goal/translate.py", "--jit", "--batch"] - translationTarget = "targetpypyjit" - - def __init__(self, translationArgs, targetArgs, - workdir="build/pypy/jit/tl", - *a, **kw): - kw['translationArgs'] = translationArgs - kw['targetArgs'] = targetArgs - kw['timeout'] = 3600 - ShellCmd.__init__(self, workdir, *a, **kw) - self.command = (self.command + translationArgs + - [self.translationTarget] + targetArgs) - # ________________________________________________________________ def not_first_time(props): @@ -211,12 +193,18 @@ description="copy build", command=["scp", "pypy-c", "fijal at codespeak.net:builds/pypy-c-scratchbox"], workdir = workdir)) -class PyPyJITTranslatedTestFactory(factory.BuildFactory): +class PyPyJITTranslatedLibPythonTestFactory(factory.BuildFactory): def __init__(self, *a, **kw): platform = kw.pop('platform', 'linux') factory.BuildFactory.__init__(self, *a, **kw) setup_steps(platform, self) - self.addStep(TranslateJIT([], [])) + self.addStep(Translate(['--jit'], ['--withoutmod-thread'])) + self.addStep(ShellCmd( + description="lib-python test", + command=["python", "pypy/test_all.py", + "--pypy=pypy/translator/goal/pypy-c", + "--resultlog=cpython.log", "lib-python"], + logfiles={'pytestLog': 'cpython.log'})) Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Fri May 1 00:13:31 2009 @@ -34,7 +34,7 @@ pypyTranslatedAppLevelTestFactory = pypybuilds.PyPyTranslatedAppLevelTestFactory() pypyStacklessTranslatedAppLevelTestFactory = pypybuilds.PyPyStacklessTranslatedAppLevelTestFactory() -pypyJITTranslatedTestFactory = pypybuilds.PyPyJITTranslatedTestFactory() +pypyJITTranslatedTestFactory = pypybuilds.PyPyJITTranslatedLibPythonTestFactory() LINUX32 = "own-linux-x86-32" CPYLINUX32 = "pypy-c-lib-python-linux-x86-32" @@ -56,7 +56,7 @@ hour=0, minute=45, branch="release/1.1.x", ), Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, - STACKLESSAPPLVLLINUX32], + STACKLESSAPPLVLLINUX32, JITLINUX32], hour=4, minute=45), ], 'status': [status], @@ -115,7 +115,7 @@ "category": 'other' }, {"name" : JITLINUX32, - "slavenames": ["wyvern"], + "slavenames": ["bigdogvm1"], 'builddir' : JITLINUX32, 'factory' : pypyJITTranslatedTestFactory, 'category' : 'other', From fijal at codespeak.net Fri May 1 00:14:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:14:48 +0200 (CEST) Subject: [pypy-svn] r64895 - pypy/build/bot2/pypybuildbot Message-ID: <20090430221448.35A0B169E54@codespeak.net> Author: fijal Date: Fri May 1 00:14:47 2009 New Revision: 64895 Modified: pypy/build/bot2/pypybuildbot/master.py Log: put it under a different scheduler as we need to build it from branch Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Fri May 1 00:14:47 2009 @@ -56,8 +56,10 @@ hour=0, minute=45, branch="release/1.1.x", ), Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, - STACKLESSAPPLVLLINUX32, JITLINUX32], + STACKLESSAPPLVLLINUX32], hour=4, minute=45), + Nightly("nightly-jit", [JITLINUX32], + hour=1, minute=45, branch="branch/pyjitpl5"), ], 'status': [status], From fijal at codespeak.net Fri May 1 00:16:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:16:29 +0200 (CEST) Subject: [pypy-svn] r64896 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090430221629.65154169E54@codespeak.net> Author: fijal Date: Fri May 1 00:16:28 2009 New Revision: 64896 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Log: Kill outdated, commented out code Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Fri May 1 00:16:28 2009 @@ -55,105 +55,3 @@ #if func.__name__ == 'll_update': # return False return super(PyPyJitPolicy, self).look_inside_function(func) - -# def seebinary(self, opname): -# name2 = name1 = opname[:3].lower() -# if name1 in ('and', 'or'): -# name1 += '_' -# descr_impl = getattr( -# pypy.objspace.descroperation.DescrOperation, name1) -# obj_impl = getattr(pypy.objspace.std.intobject, name2 + '__Int_Int') -# self.seepath( -# getattr(pypy.interpreter.pyframe.PyFrame, 'BINARY_'+ opname), -# descr_impl, -# obj_impl) -# self.seepath(descr_impl, -# pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) -# descr_impl = getattr(pypy.objspace.descroperation.DescrOperation, -# 'inplace_' + name2) -# op_impl = getattr(pypy.interpreter.pyframe.PyFrame, 'INPLACE_'+ opname) -# self.seepath(op_impl, descr_impl, obj_impl) -# self.seepath(descr_impl, -# pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) - -# def seeunary(self, opname, name=None): -# if name is None: -# name = opname.lower() -# descr_impl = getattr( -# pypy.objspace.descroperation.DescrOperation, name) -# self.seepath( -# getattr(pypy.interpreter.pyframe.PyFrame, 'UNARY_' + opname), -# descr_impl, -# getattr(pypy.objspace.std.intobject, name + '__Int')) -# self.seepath(descr_impl, -# pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) - -# def seecmp(self, name): -# descr_impl = getattr(pypy.objspace.descroperation.DescrOperation, name) -# self.seepath( -# pypy.interpreter.pyframe.PyFrame.COMPARE_OP, -# descr_impl, -# getattr(pypy.objspace.std.intobject, name +'__Int_Int'), -# pypy.objspace.std.Space.newbool) -# self.seepath( -# descr_impl, -# pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) - -# def fill_seen_graphs(self): -# import pypy -# def fc(o): -# return [i[1] for i in find_calls_from(self.translator, o)] -# return - -# # -------------------- -# for binop in 'MODULO ADD SUBTRACT MULTIPLY AND OR XOR'.split(): -# self.seebinary(binop) -# for cmpname in 'lt le eq ne ge gt'.split(): -# self.seecmp(cmpname) -# self.seepath(pypy.interpreter.pyframe.PyFrame.UNARY_NOT, -# pypy.objspace.std.Space.not_) -# self.seeunary('INVERT') -# self.seeunary('POSITIVE', 'pos') -# self.seeunary('NEGATIVE', 'neg') - -# self.seepath(pypy.objspace.descroperation._invoke_binop, -# pypy.objspace.descroperation._check_notimplemented) -# self.seepath(pypy.objspace.std.intobject.add__Int_Int, -# pypy.objspace.std.inttype.wrapint, -# pypy.objspace.std.intobject.W_IntObject.__init__) -# self.seepath(pypy.objspace.descroperation.DescrOperation.add, -# pypy.objspace.std.Space.type, -# pypy.objspace.std.Space.gettypeobject) -# self.seepath(pypy.objspace.descroperation.DescrOperation.add, -# pypy.objspace.std.Space.is_w) -# self.seegraph(pypy.interpreter.pyframe.PyFrame.execute_frame, False) -# self.seegraph(pypy.objspace.std.multimethod.FailedToImplement.__init__, -# True) -# # -------------------- -# self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, -# pypy.objspace.std.boolobject.nonzero__Bool) -# self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, -# pypy.objspace.std.boolobject.nonzero__Bool) -# self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, -# pypy.objspace.std.intobject.nonzero__Int) -# self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, -# pypy.objspace.std.intobject.nonzero__Int) -# self.seepath(pypy.interpreter.pyframe.PyFrame.FOR_ITER, -# pypy.objspace.descroperation.DescrOperation.next, -# pypy.objspace.std.rangeobject.next__RangeIter, -# pypy.objspace.std.rangeobject.W_RangeListObject.getitem) -# # -# #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) - - - -#forbidden_modules = {'pypy.interpreter.gateway': True, - #'pypy.interpreter.baseobjspace': True, -# 'pypy.interpreter.typedef': True, -# 'pypy.interpreter.eval': True, -# 'pypy.interpreter.function': True, -# 'pypy.interpreter.pytraceback': True, -# } From fijal at codespeak.net Fri May 1 00:17:12 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:17:12 +0200 (CEST) Subject: [pypy-svn] r64897 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090430221712.45024169E54@codespeak.net> Author: fijal Date: Fri May 1 00:17:11 2009 New Revision: 64897 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Log: skip subclasses Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Fri May 1 00:17:11 2009 @@ -54,4 +54,10 @@ # return False #if func.__name__ == 'll_update': # return False + + # weakref support + if (mod == 'pypy.objspace.std.typeobject' and + func.__name__ == 'get_subclasses'): + return False + return super(PyPyJitPolicy, self).look_inside_function(func) From fijal at codespeak.net Fri May 1 00:20:44 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:20:44 +0200 (CEST) Subject: [pypy-svn] r64898 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090430222044.A7F89169E54@codespeak.net> Author: fijal Date: Fri May 1 00:20:43 2009 New Revision: 64898 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Log: oops, wrong order Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Fri May 1 00:20:43 2009 @@ -19,6 +19,12 @@ return True if '_mth_mm_' in func.__name__: # e.g. str_mth_mm_join_xxx return True + + # weakref support + if (mod == 'pypy.objspace.std.typeobject' and + func.__name__ == 'get_subclasses'): + return False + if mod.startswith('pypy.objspace.'): # we don't support floats if 'float' in mod or 'complex' in mod: @@ -54,10 +60,5 @@ # return False #if func.__name__ == 'll_update': # return False - - # weakref support - if (mod == 'pypy.objspace.std.typeobject' and - func.__name__ == 'get_subclasses'): - return False return super(PyPyJitPolicy, self).look_inside_function(func) From fijal at codespeak.net Fri May 1 00:23:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 00:23:09 +0200 (CEST) Subject: [pypy-svn] r64899 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090430222309.2493D169E54@codespeak.net> Author: fijal Date: Fri May 1 00:23:09 2009 New Revision: 64899 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Log: improve Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/policy.py Fri May 1 00:23:09 2009 @@ -21,9 +21,10 @@ return True # weakref support - if (mod == 'pypy.objspace.std.typeobject' and - func.__name__ == 'get_subclasses'): - return False + if mod == 'pypy.objspace.std.typeobject': + if func.__name__ in ['get_subclasses', 'add_subclass', + 'remove_subclass']: + return False if mod.startswith('pypy.objspace.'): # we don't support floats From benjamin at codespeak.net Fri May 1 00:35:54 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 00:35:54 +0200 (CEST) Subject: [pypy-svn] r64900 - in pypy/trunk/pypy: rpython/memory/gctransform tool Message-ID: <20090430223554.D40F5169E78@codespeak.net> Author: benjamin Date: Fri May 1 00:35:50 2009 New Revision: 64900 Modified: pypy/trunk/pypy/rpython/memory/gctransform/statistics.py pypy/trunk/pypy/rpython/memory/gctransform/transform.py pypy/trunk/pypy/tool/import_graph.py Log: use builtin set instead of the sets module Modified: pypy/trunk/pypy/rpython/memory/gctransform/statistics.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctransform/statistics.py (original) +++ pypy/trunk/pypy/rpython/memory/gctransform/statistics.py Fri May 1 00:35:50 2009 @@ -13,19 +13,18 @@ return isinstance(arg.concretetype, lltype.Ptr) and not arg.concretetype._needsgc() def relevant_gcvars_block(block, filter=filter_for_ptr): - import sets result = [] def filter_ptr(args): return [arg for arg in args if filter(arg)] def live_vars_before(index): if index == 0: - return sets.Set(filter_ptr(block.inputargs)) + return set(filter_ptr(block.inputargs)) op = block.operations[index - 1] result = live_vars_before(index - 1).union(filter_ptr(op.args + [op.result])) return result def live_vars_after(index): if index == len(block.operations) - 1: - result = sets.Set() + result = set() for exit in block.exits: result = result.union(filter_ptr(exit.args)) return result Modified: pypy/trunk/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/trunk/pypy/rpython/memory/gctransform/transform.py Fri May 1 00:35:50 2009 @@ -18,7 +18,8 @@ from pypy.rpython.rtyper import LowLevelOpList from pypy.rpython.rbuiltin import gen_cast from pypy.rlib.rarithmetic import ovfcheck -import sets, os, sys +import sys +import os from pypy.rpython.lltypesystem.lloperation import llop from pypy.translator.simplify import join_blocks, cleanup_graph @@ -194,15 +195,15 @@ if len(block.exits) != 0: # i.e not the return block assert block.exitswitch is not c_last_exception - deadinallexits = sets.Set(self.livevars) + deadinallexits = set(self.livevars) for link in block.exits: - deadinallexits.difference_update(sets.Set(link.args)) + deadinallexits.difference_update(set(link.args)) for var in deadinallexits: self.pop_alive(var, llops) for link in block.exits: - livecounts = dict.fromkeys(sets.Set(self.livevars) - deadinallexits, 1) + livecounts = dict.fromkeys(set(self.livevars) - deadinallexits, 1) for v, v2 in zip(link.args, link.target.inputargs): if is_borrowed(v2): continue Modified: pypy/trunk/pypy/tool/import_graph.py ============================================================================== --- pypy/trunk/pypy/tool/import_graph.py (original) +++ pypy/trunk/pypy/tool/import_graph.py Fri May 1 00:35:50 2009 @@ -4,7 +4,6 @@ import math import random -import sets exclude_files = ["__init__.py", "autopath.py", "conftest.py"] @@ -89,7 +88,7 @@ self.remove_double_refs() self.incoming = {} for mod in self.imports: - self.incoming[mod] = sets.Set() + self.incoming[mod] = set() for mod, refs in self.imports.iteritems(): for ref in refs: if ref[0] in self.incoming: @@ -118,7 +117,7 @@ # remove several references to the same module for mod, refs in self.imports.iteritems(): i = 0 - seen_refs = sets.Set() + seen_refs = set() while i < len(refs): if refs[i] not in seen_refs: seen_refs.add(refs[i]) @@ -139,7 +138,7 @@ def create_clusters(self): self.topgraph_properties.append("compound=true;") self.clustered = True - hierarchy = [sets.Set() for i in range(6)] + hierarchy = [set() for i in range(6)] for mod in self.imports: for i, d in enumerate(mod.split(".")): hierarchy[i].add(d) @@ -151,7 +150,7 @@ if i == len(mod.split(".")) - 1: continue if cluster not in self.clusters: - self.clusters[cluster] = sets.Set() + self.clusters[cluster] = set() self.clusters[cluster].add(mod) self.mod_to_cluster[mod] = cluster @@ -162,7 +161,7 @@ if len(incoming) > 10: tangled.append(mod) for mod in tangled: - remove = sets.Set() + remove = set() incoming = self.incoming[mod] while len(remove) < len(incoming) * 0.80: remove.add(random.choice(list(incoming))) @@ -196,7 +195,7 @@ try: nodes = self.clusters[self.mod_to_cluster[mod]] except KeyError: - nodes = sets.Set() + nodes = set() for ref in refs: if ref[0] not in nodes: f.write('\t"%s" -> "%s";\n' % (mod[5:], ref[0][5:])) From fijal at codespeak.net Fri May 1 01:15:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 01:15:36 +0200 (CEST) Subject: [pypy-svn] r64901 - pypy/build/bot2/pypybuildbot Message-ID: <20090430231536.7FF8A168552@codespeak.net> Author: fijal Date: Fri May 1 01:15:29 2009 New Revision: 64901 Modified: pypy/build/bot2/pypybuildbot/master.py Log: rename Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Fri May 1 01:15:29 2009 @@ -44,7 +44,7 @@ APPLVLLINUX32 = "pypy-c-app-level-linux-x86-32" STACKLESSAPPLVLLINUX32 = "pypy-c-stackless-app-level-linux-x86-32" CPYFREEBSD64 = 'pypy-c-lib-python-freebsd-7-x86-64' -JITLINUX32 = "jit-linux-x86-32" +JITLINUX32 = "pypy-c-jit-lib-python-linux-x86-32" BuildmasterConfig = { 'slavePortnum': slavePortnum, From fijal at codespeak.net Fri May 1 01:23:41 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 01:23:41 +0200 (CEST) Subject: [pypy-svn] r64902 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090430232341.E292E169EA3@codespeak.net> Author: fijal Date: Fri May 1 01:23:41 2009 New Revision: 64902 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO Log: update Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO Fri May 1 01:23:41 2009 @@ -1,11 +1,5 @@ * find a test for r64742 (JitException capture) -* fix HashCollisionException, it appears in the wild - -* do something about _weakref module, it's usually needed by everyone - -* look at some remaining crashes - * support floats * fix bugs in virtualizables, but think first From benjamin at codespeak.net Fri May 1 01:31:52 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 01:31:52 +0200 (CEST) Subject: [pypy-svn] r64903 - in pypy/branch/pyjitpl5/pypy: rpython/memory/gctransform tool Message-ID: <20090430233152.92EA6169DFF@codespeak.net> Author: benjamin Date: Fri May 1 01:31:51 2009 New Revision: 64903 Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/statistics.py pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/transform.py pypy/branch/pyjitpl5/pypy/tool/import_graph.py Log: merge r64900 Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/statistics.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/statistics.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/statistics.py Fri May 1 01:31:51 2009 @@ -13,19 +13,18 @@ return isinstance(arg.concretetype, lltype.Ptr) and not arg.concretetype._needsgc() def relevant_gcvars_block(block, filter=filter_for_ptr): - import sets result = [] def filter_ptr(args): return [arg for arg in args if filter(arg)] def live_vars_before(index): if index == 0: - return sets.Set(filter_ptr(block.inputargs)) + return set(filter_ptr(block.inputargs)) op = block.operations[index - 1] result = live_vars_before(index - 1).union(filter_ptr(op.args + [op.result])) return result def live_vars_after(index): if index == len(block.operations) - 1: - result = sets.Set() + result = set() for exit in block.exits: result = result.union(filter_ptr(exit.args)) return result Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/transform.py Fri May 1 01:31:51 2009 @@ -18,7 +18,8 @@ from pypy.rpython.rtyper import LowLevelOpList from pypy.rpython.rbuiltin import gen_cast from pypy.rlib.rarithmetic import ovfcheck -import sets, os, sys +import sys +import os from pypy.rpython.lltypesystem.lloperation import llop from pypy.translator.simplify import join_blocks, cleanup_graph @@ -194,15 +195,15 @@ if len(block.exits) != 0: # i.e not the return block assert block.exitswitch is not c_last_exception - deadinallexits = sets.Set(self.livevars) + deadinallexits = set(self.livevars) for link in block.exits: - deadinallexits.difference_update(sets.Set(link.args)) + deadinallexits.difference_update(set(link.args)) for var in deadinallexits: self.pop_alive(var, llops) for link in block.exits: - livecounts = dict.fromkeys(sets.Set(self.livevars) - deadinallexits, 1) + livecounts = dict.fromkeys(set(self.livevars) - deadinallexits, 1) for v, v2 in zip(link.args, link.target.inputargs): if is_borrowed(v2): continue Modified: pypy/branch/pyjitpl5/pypy/tool/import_graph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/tool/import_graph.py (original) +++ pypy/branch/pyjitpl5/pypy/tool/import_graph.py Fri May 1 01:31:51 2009 @@ -4,7 +4,6 @@ import math import random -import sets exclude_files = ["__init__.py", "autopath.py", "conftest.py"] @@ -89,7 +88,7 @@ self.remove_double_refs() self.incoming = {} for mod in self.imports: - self.incoming[mod] = sets.Set() + self.incoming[mod] = set() for mod, refs in self.imports.iteritems(): for ref in refs: if ref[0] in self.incoming: @@ -118,7 +117,7 @@ # remove several references to the same module for mod, refs in self.imports.iteritems(): i = 0 - seen_refs = sets.Set() + seen_refs = set() while i < len(refs): if refs[i] not in seen_refs: seen_refs.add(refs[i]) @@ -139,7 +138,7 @@ def create_clusters(self): self.topgraph_properties.append("compound=true;") self.clustered = True - hierarchy = [sets.Set() for i in range(6)] + hierarchy = [set() for i in range(6)] for mod in self.imports: for i, d in enumerate(mod.split(".")): hierarchy[i].add(d) @@ -151,7 +150,7 @@ if i == len(mod.split(".")) - 1: continue if cluster not in self.clusters: - self.clusters[cluster] = sets.Set() + self.clusters[cluster] = set() self.clusters[cluster].add(mod) self.mod_to_cluster[mod] = cluster @@ -162,7 +161,7 @@ if len(incoming) > 10: tangled.append(mod) for mod in tangled: - remove = sets.Set() + remove = set() incoming = self.incoming[mod] while len(remove) < len(incoming) * 0.80: remove.add(random.choice(list(incoming))) @@ -196,7 +195,7 @@ try: nodes = self.clusters[self.mod_to_cluster[mod]] except KeyError: - nodes = sets.Set() + nodes = set() for ref in refs: if ref[0] not in nodes: f.write('\t"%s" -> "%s";\n' % (mod[5:], ref[0][5:])) From fijal at codespeak.net Fri May 1 02:49:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 02:49:43 +0200 (CEST) Subject: [pypy-svn] r64904 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090501004943.CA7FE168575@codespeak.net> Author: fijal Date: Fri May 1 02:49:36 2009 New Revision: 64904 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: add a rudimentary profiler support 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 May 1 02:49:36 2009 @@ -588,6 +588,7 @@ raise NotImplementedError class History(RunningMatcher): + extratext = '' def record(self, opnum, argboxes, resbox, descr=None): op = ResOperation(opnum, argboxes, resbox, descr) @@ -697,6 +698,7 @@ _about_ = check_descr def compute_result_annotation(self, s_x): + return from pypy.annotation import model as annmodel if not annmodel.s_None.contains(s_x): assert isinstance(s_x, annmodel.SomeInstance) Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Fri May 1 02:49:36 2009 @@ -0,0 +1,80 @@ + +""" A small helper module for profiling JIT +""" + +import time + +TRACING = 0 +RUNNING = 1 +BLACKHOLE = 2 +END_TRACING = 4 +END_RUNNING = 5 +END_BLACKHOLE = 6 + +class EmptyProfiler(object): + initialized = False + + def start(self): + pass + + def finish(self): + pass + + def start_normal(self, greenkey=None): + pass + + def end_normal(self): + pass + + def start_tracing(self, greenkey=None): + pass + + def end_tracing(self): + pass + + def start_running(self, greenkey=None): + pass + + def end_running(self): + pass + + def start_blackhole(self, greenkey=None): + pass + + def end_blackhole(self): + pass + +class Profiler(object): + initialized = False + + def start(self): + self.t0 = time.clock() + self.events = [] + + def finish(self): + self.tk = time.clock() + self.print_stats() + + def start_tracing(self, greenkey=None): + self.events.append((time.clock(), TRACING)) + + def end_tracing(self): + self.events.append((time.clock(), END_TRACING)) + + def start_running(self, greenkey=None): + self.events.append((time.clock(), RUNNING)) + + def end_running(self): + self.events.append((time.clock(), END_RUNNING)) + + def start_blackhole(self, greenkey=None): + self.events.append((time.clock(), BLACKHOLE)) + + def end_blackhole(self): + self.events.append((time.clock(), END_BLACKHOLE)) + + def print_stats(self): + print "Total: %f" % (self.tk - self.t0) + #for t, ev in self.events: + # if ev == END_TRACING + 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 May 1 02:49:36 2009 @@ -18,6 +18,7 @@ from pypy.jit.metainterp import typesystem from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import specialize +from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler # ____________________________________________________________ @@ -829,7 +830,7 @@ num_green_args = 0 def __init__(self, portal_graph, graphs, cpu, stats, options, - optimizer=None): + optimizer=None, profile=False): self.portal_graph = portal_graph self.cpu = cpu self.stats = stats @@ -861,6 +862,11 @@ else: self.ts = typesystem.llhelper + if profile: + self.profiler = Profiler() + else: + self.profiler = EmptyProfiler() + def _freeze_(self): return True @@ -1014,6 +1020,8 @@ while True: self.framestack[-1].run_one_step() finally: + if isinstance(self.history, history.BlackHole): + self.staticdata.profiler.end_blackhole() if not we_are_translated(): history.log.event('LEAVE' + self.history.extratext) elif DEBUG: @@ -1266,6 +1274,7 @@ self.history.operations.append(suboperations[i]) self.extra_rebuild_operations = extra if not must_compile: + self.staticdata.profiler.start_blackhole() self.history = history.BlackHole(self.cpu) # the BlackHole is invalid because it doesn't start with # guard_failure.key.guard_op.suboperations, but that's fine Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py Fri May 1 02:49:36 2009 @@ -0,0 +1,39 @@ + +from pypy.jit.metainterp.warmspot import ll_meta_interp +from pypy.rlib.jit import JitDriver +from pypy.jit.metainterp.test.test_basic import LLJitMixin +from pypy.jit.metainterp import pyjitpl +from pypy.jit.metainterp.jitprof import * + +class ProfilerMixin(LLJitMixin): + def meta_interp(self, *args, **kwds): + kwds = kwds.copy() + kwds['profile'] = True + return LLJitMixin.meta_interp(self, *args, **kwds) + +class TestProfile(ProfilerMixin): + + def test_simple_loop(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y', '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 += x + y -= 1 + return res * 2 + res = self.meta_interp(f, [6, 7]) + assert res == 84 + profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler + assert len(profiler.events) == 6 + expected = [ + TRACING, + END_TRACING, + RUNNING, + END_RUNNING, + BLACKHOLE, + END_BLACKHOLE + ] + assert [i[1] for i in profiler.events] == expected + 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 May 1 02:49:36 2009 @@ -141,7 +141,7 @@ def build_meta_interp(self, CPUClass=None, view="auto", translate_support_code=False, optimizer=None, - **kwds): + profile=False, **kwds): assert CPUClass is not None opt = pyjitpl.Options(**kwds) self.stats = history.Stats() @@ -170,7 +170,8 @@ self.jitdriver = block.operations[pos].args[1].value self.metainterp_sd = MetaInterpStaticData(graph, graphs, cpu, self.stats, opt, - optimizer=optimizer) + optimizer=optimizer, + profile=profile) def make_enter_function(self): WarmEnterState = make_state_class(self) @@ -555,6 +556,10 @@ # not too bad. def maybe_compile_and_run(self, *args): + metainterp_sd = warmrunnerdesc.metainterp_sd + if not metainterp_sd.profiler.initialized: + metainterp_sd.profiler.start() + metainterp_sd.profiler.initialized = True # get the greenargs and look for the cell corresponding to the hash greenargs = args[:num_green_args] argshash = self.getkeyhash(*greenargs) @@ -568,9 +573,10 @@ self.cells[argshash] = Counter(n) return #interp.debug_trace("jit_compile", *greenargs) - metainterp_sd = warmrunnerdesc.metainterp_sd metainterp = MetaInterp(metainterp_sd) + metainterp_sd.profiler.start_tracing() loop = metainterp.compile_and_run_once(*args) + metainterp_sd.profiler.end_tracing() else: # machine code was already compiled for these greenargs # (or we have a hash collision) @@ -588,7 +594,9 @@ # ---------- execute assembler ---------- while True: # until interrupted by an exception metainterp_sd = warmrunnerdesc.metainterp_sd + metainterp_sd.profiler.start_running() fail_op = metainterp_sd.cpu.execute_operations(loop) + metainterp_sd.profiler.end_running() loop = fail_op.descr.handle_fail_op(metainterp_sd, fail_op) maybe_compile_and_run._dont_inline_ = True @@ -614,7 +622,10 @@ return None metainterp_sd = warmrunnerdesc.metainterp_sd metainterp = MetaInterp(metainterp_sd) - return metainterp.compile_and_run_once(*args) + warmrunnerdesc.metainterp_sd.profiler.start_tracing() + res = metainterp.compile_and_run_once(*args) + warmrunnerdesc.metainterp_sd.profiler.end_tracing() + return res handle_hash_collision._dont_inline_ = True def getkeyhash(self, *greenargs): From fijal at codespeak.net Fri May 1 02:54:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 02:54:04 +0200 (CEST) Subject: [pypy-svn] r64905 - pypy/branch/pyjitpl5 Message-ID: <20090501005404.BE8B21683E7@codespeak.net> Author: fijal Date: Fri May 1 02:54:03 2009 New Revision: 64905 Modified: pypy/branch/pyjitpl5/ (props changed) Log: Copy svn:externals from trunk From fijal at codespeak.net Fri May 1 03:30:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 03:30:18 +0200 (CEST) Subject: [pypy-svn] r64906 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090501013018.21D44169E45@codespeak.net> Author: fijal Date: Fri May 1 03:30:12 2009 New Revision: 64906 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: progress on profiler Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Fri May 1 03:30:12 2009 @@ -7,9 +7,10 @@ TRACING = 0 RUNNING = 1 BLACKHOLE = 2 -END_TRACING = 4 -END_RUNNING = 5 -END_BLACKHOLE = 6 +LAST_START = 2 +END_TRACING = 3 +END_RUNNING = 4 +END_BLACKHOLE = 5 class EmptyProfiler(object): initialized = False @@ -46,32 +47,50 @@ class Profiler(object): initialized = False + timer = time.clock def start(self): - self.t0 = time.clock() + self.t0 = self.timer() self.events = [] def finish(self): - self.tk = time.clock() + self.tk = self.timer() + self.summarize() self.print_stats() def start_tracing(self, greenkey=None): - self.events.append((time.clock(), TRACING)) + self.events.append((self.timer(), TRACING)) def end_tracing(self): - self.events.append((time.clock(), END_TRACING)) + self.events.append((self.timer(), END_TRACING)) def start_running(self, greenkey=None): - self.events.append((time.clock(), RUNNING)) + self.events.append((self.timer(), RUNNING)) def end_running(self): - self.events.append((time.clock(), END_RUNNING)) + self.events.append((self.timer(), END_RUNNING)) def start_blackhole(self, greenkey=None): - self.events.append((time.clock(), BLACKHOLE)) + self.events.append((self.timer(), BLACKHOLE)) def end_blackhole(self): - self.events.append((time.clock(), END_BLACKHOLE)) + self.events.append((self.timer(), END_BLACKHOLE)) + + def summarize(self): + current = [] + t = 0 + times = [0, 0, 0] + for t0, ev in self.events: + if ev <= LAST_START: + if current: + times[current[-1]] += t0 - t + current.append(ev) + else: + times[current.pop()] += t0 - t + t = t0 + self.trace_time = times[TRACING] + self.run_time = times[RUNNING] + self.blackhole_time = times[BLACKHOLE] def print_stats(self): print "Total: %f" % (self.tk - self.t0) 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 May 1 03:30:12 2009 @@ -862,8 +862,8 @@ else: self.ts = typesystem.llhelper - if profile: - self.profiler = Profiler() + if profile is not None: + self.profiler = profile() else: self.profiler = EmptyProfiler() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py Fri May 1 03:30:12 2009 @@ -5,10 +5,21 @@ from pypy.jit.metainterp import pyjitpl from pypy.jit.metainterp.jitprof import * +class FakeProfiler(Profiler): + def __init__(self): + self.counter = 0 + + def timer(self): + self.counter += 1 + return self.counter - 1 + + def print_stats(self): + pass + class ProfilerMixin(LLJitMixin): def meta_interp(self, *args, **kwds): kwds = kwds.copy() - kwds['profile'] = True + kwds['profile'] = FakeProfiler return LLJitMixin.meta_interp(self, *args, **kwds) class TestProfile(ProfilerMixin): @@ -36,4 +47,6 @@ END_BLACKHOLE ] assert [i[1] for i in profiler.events] == expected - + assert profiler.trace_time == 1 + assert profiler.run_time == 1 + assert profiler.blackhole_time == 1 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 May 1 03:30:12 2009 @@ -54,6 +54,7 @@ warmrunnerdesc.state.set_param_hash_bits(hash_bits) warmrunnerdesc.finish() res = interp.eval_graph(graph, args) + warmrunnerdesc.metainterp_sd.profiler.finish() print '~~~ return value:', res while repeat > 1: print '~' * 79 From fijal at codespeak.net Fri May 1 03:53:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 03:53:42 +0200 (CEST) Subject: [pypy-svn] r64907 - pypy/branch/pyjitpl5/pypy Message-ID: <20090501015342.BF5CA169E54@codespeak.net> Author: fijal Date: Fri May 1 03:53:42 2009 New Revision: 64907 Added: pypy/branch/pyjitpl5/pypy/conftest.py - copied unchanged from r64906, pypy/trunk/pypy/conftest.py Log: Replace conftest with one from trunk. damn. From fijal at codespeak.net Fri May 1 04:13:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 04:13:57 +0200 (CEST) Subject: [pypy-svn] r64908 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090501021357.9D4B1168544@codespeak.net> Author: fijal Date: Fri May 1 04:13:52 2009 New Revision: 64908 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: kill code that is not called anywhere outdated and "a bit ad hoc" 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 Fri May 1 04:13:52 2009 @@ -72,23 +72,6 @@ # # Public interface -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.backend.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 From fijal at codespeak.net Fri May 1 04:16:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 04:16:17 +0200 (CEST) Subject: [pypy-svn] r64909 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501021617.E7BEF16853B@codespeak.net> Author: fijal Date: Fri May 1 04:16:17 2009 New Revision: 64909 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: oops Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Fri May 1 04:16:17 2009 @@ -94,6 +94,7 @@ def print_stats(self): print "Total: %f" % (self.tk - self.t0) - #for t, ev in self.events: - # if ev == END_TRACING + print "Tracing: %f" % self.trace_time + print "Running: %f" % self.run_time + print "Blackhole: %f" % self.blackhole_time 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 May 1 04:16:17 2009 @@ -830,7 +830,7 @@ num_green_args = 0 def __init__(self, portal_graph, graphs, cpu, stats, options, - optimizer=None, profile=False): + optimizer=None, profile=None): self.portal_graph = portal_graph self.cpu = cpu self.stats = stats From fijal at codespeak.net Fri May 1 04:22:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 04:22:27 +0200 (CEST) Subject: [pypy-svn] r64910 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501022227.9B688168574@codespeak.net> Author: fijal Date: Fri May 1 04:22:19 2009 New Revision: 64910 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: grrrr 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 May 1 04:22:19 2009 @@ -142,7 +142,7 @@ def build_meta_interp(self, CPUClass=None, view="auto", translate_support_code=False, optimizer=None, - profile=False, **kwds): + profile=None, **kwds): assert CPUClass is not None opt = pyjitpl.Options(**kwds) self.stats = history.Stats() From fijal at codespeak.net Fri May 1 04:33:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 04:33:20 +0200 (CEST) Subject: [pypy-svn] r64911 - pypy/extradoc/talk/euroscipy2009 Message-ID: <20090501023320.632F2168574@codespeak.net> Author: fijal Date: Fri May 1 04:33:10 2009 New Revision: 64911 Added: pypy/extradoc/talk/euroscipy2009/ pypy/extradoc/talk/euroscipy2009/abstract.txt (contents, props changed) Log: Add an abstract for euroscipy Added: pypy/extradoc/talk/euroscipy2009/abstract.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/euroscipy2009/abstract.txt Fri May 1 04:33:10 2009 @@ -0,0 +1,23 @@ +==================== +PyPy's JIT and Numpy +==================== + +Common problem when developing scientific application is that CPython's +interpreter is too slow. This can mitigated by usage of FORTRAN, C or Cython +in performance-critical parts of the code, but it would be much nicer +to just run python faster. + +JIT was one of the main objectives of PyPy project for quite a while now. +As of `March 2009`_ we're able to speed up simple examples in Python +for about 20-30x over the speed of CPython. Since PyPy's JIT is much more +flexible than for example Psyco, we expect even greater speedups in the +future, as well as support for floats and 64bit architecture, which Psyco +will not achieve in forseeable future. + +In this talk we would like to talk about PyPy's JIT, design principles and +it's future, without going into too many architectural details. + +We would also like to present how JIT can make the life easier of simple +postprocessing of data generated by EULAG model. XXX extend. + +.. _`March 2009`: http://morepypy.blogspot.com/2009/03/good-news-everyone.html From fijal at codespeak.net Fri May 1 04:34:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 04:34:51 +0200 (CEST) Subject: [pypy-svn] r64912 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090501023451.6619F1684E4@codespeak.net> Author: fijal Date: Fri May 1 04:34:46 2009 New Revision: 64912 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: also check when compiled 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 May 1 04:34:46 2009 @@ -677,11 +677,18 @@ if len(oldlocs) != len(newlocs): # virtualizable mess return - if not we_are_translated(): - assert str(oldlocs) == str(newlocs) + for i in range(len(oldlocs)): + oldloc = oldlocs[i] + newloc = newlocs[i] + if isinstance(newloc, MODRM): + assert isinstance(oldloc, MODRM) + assert newloc.position == oldloc.position + else: + assert newloc is oldloc # newlocs should be sorted in acending order, excluding the regs - locs = [loc.position for loc in newlocs if isinstance(loc, MODRM)] - assert locs == sorted(locs) + if not we_are_translated(): + locs = [loc.position for loc in newlocs if isinstance(loc, MODRM)] + assert locs == sorted(locs) # if newdepth != olddepth: mc2 = self.mcstack.next_mc() From benjamin at codespeak.net Fri May 1 04:56:27 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 04:56:27 +0200 (CEST) Subject: [pypy-svn] r64913 - pypy/extradoc/talk/euroscipy2009 Message-ID: <20090501025627.30BF5169E45@codespeak.net> Author: benjamin Date: Fri May 1 04:56:17 2009 New Revision: 64913 Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt Log: edits Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt ============================================================================== --- pypy/extradoc/talk/euroscipy2009/abstract.txt (original) +++ pypy/extradoc/talk/euroscipy2009/abstract.txt Fri May 1 04:56:17 2009 @@ -2,22 +2,22 @@ PyPy's JIT and Numpy ==================== -Common problem when developing scientific application is that CPython's -interpreter is too slow. This can mitigated by usage of FORTRAN, C or Cython -in performance-critical parts of the code, but it would be much nicer -to just run python faster. +A common problem when developing scientific applications is that CPython is +too slow. This can mitigated by usage of FORTRAN, C, or Cython in +performance-critical parts of the code, but it would be much nicer if +python ran faster. -JIT was one of the main objectives of PyPy project for quite a while now. -As of `March 2009`_ we're able to speed up simple examples in Python -for about 20-30x over the speed of CPython. Since PyPy's JIT is much more -flexible than for example Psyco, we expect even greater speedups in the -future, as well as support for floats and 64bit architecture, which Psyco -will not achieve in forseeable future. +Creating a JIT has been one of the main objectives of the PyPy project for +quite a while now. As of `March 2009`_, we're able to speed up simple +examples in Python t about 20-30x over the speed of CPython. Since PyPy's +JIT is much more flexible than others, Psyco for example, we expect even +greater speedups in the future, as well as support for floats and 64bit +architectures, which Psyco will not achieve in forseeable future. -In this talk we would like to talk about PyPy's JIT, design principles and -it's future, without going into too many architectural details. +In this talk, we will talk about the design principles and future of PyPy's +JIT. We won't go into too many architectural details. -We would also like to present how JIT can make the life easier of simple +We will also present how JIT can make the life easier for simple postprocessing of data generated by EULAG model. XXX extend. .. _`March 2009`: http://morepypy.blogspot.com/2009/03/good-news-everyone.html From benjamin at codespeak.net Fri May 1 05:01:16 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 05:01:16 +0200 (CEST) Subject: [pypy-svn] r64914 - pypy/extradoc/talk/euroscipy2009 Message-ID: <20090501030116.83279169E3E@codespeak.net> Author: benjamin Date: Fri May 1 05:01:06 2009 New Revision: 64914 Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt Log: more style things Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt ============================================================================== --- pypy/extradoc/talk/euroscipy2009/abstract.txt (original) +++ pypy/extradoc/talk/euroscipy2009/abstract.txt Fri May 1 05:01:06 2009 @@ -10,12 +10,12 @@ Creating a JIT has been one of the main objectives of the PyPy project for quite a while now. As of `March 2009`_, we're able to speed up simple examples in Python t about 20-30x over the speed of CPython. Since PyPy's -JIT is much more flexible than others, Psyco for example, we expect even -greater speedups in the future, as well as support for floats and 64bit -architectures, which Psyco will not achieve in forseeable future. +JIT is much more flexible than Pysco we expect even greater speedups in the +future, as well as support for floats and 64bit architectures, which Psyco +will not achieve in forseeable future. -In this talk, we will talk about the design principles and future of PyPy's -JIT. We won't go into too many architectural details. +In this talk, we will discuss about the design principles and future of +PyPy's JIT. We won't go into too many architectural details. We will also present how JIT can make the life easier for simple postprocessing of data generated by EULAG model. XXX extend. From benjamin at codespeak.net Fri May 1 05:03:01 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 05:03:01 +0200 (CEST) Subject: [pypy-svn] r64915 - pypy/extradoc/talk/euroscipy2009 Message-ID: <20090501030301.AB095169E45@codespeak.net> Author: benjamin Date: Fri May 1 05:02:50 2009 New Revision: 64915 Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt Log: better as one sentence Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt ============================================================================== --- pypy/extradoc/talk/euroscipy2009/abstract.txt (original) +++ pypy/extradoc/talk/euroscipy2009/abstract.txt Fri May 1 05:02:50 2009 @@ -14,8 +14,8 @@ future, as well as support for floats and 64bit architectures, which Psyco will not achieve in forseeable future. -In this talk, we will discuss about the design principles and future of -PyPy's JIT. We won't go into too many architectural details. +In this talk, we will discuss the design principles and future of PyPy's +JIT but won't go into too many architectural details. We will also present how JIT can make the life easier for simple postprocessing of data generated by EULAG model. XXX extend. From benjamin at codespeak.net Fri May 1 05:04:45 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 05:04:45 +0200 (CEST) Subject: [pypy-svn] r64916 - pypy/extradoc/talk/euroscipy2009 Message-ID: <20090501030445.A7E45169E6C@codespeak.net> Author: benjamin Date: Fri May 1 05:04:36 2009 New Revision: 64916 Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt Log: stray letter Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt ============================================================================== --- pypy/extradoc/talk/euroscipy2009/abstract.txt (original) +++ pypy/extradoc/talk/euroscipy2009/abstract.txt Fri May 1 05:04:36 2009 @@ -9,8 +9,8 @@ Creating a JIT has been one of the main objectives of the PyPy project for quite a while now. As of `March 2009`_, we're able to speed up simple -examples in Python t about 20-30x over the speed of CPython. Since PyPy's -JIT is much more flexible than Pysco we expect even greater speedups in the +examples in Python about 20-30x over the speed of CPython. Since PyPy's JIT +is much more flexible than Pysco we expect even greater speedups in the future, as well as support for floats and 64bit architectures, which Psyco will not achieve in forseeable future. From benjamin at codespeak.net Fri May 1 05:09:29 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 1 May 2009 05:09:29 +0200 (CEST) Subject: [pypy-svn] r64917 - pypy/extradoc/talk/euroscipy2009 Message-ID: <20090501030929.34B5D168494@codespeak.net> Author: benjamin Date: Fri May 1 05:09:19 2009 New Revision: 64917 Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt Log: passing the test suite Modified: pypy/extradoc/talk/euroscipy2009/abstract.txt ============================================================================== --- pypy/extradoc/talk/euroscipy2009/abstract.txt (original) +++ pypy/extradoc/talk/euroscipy2009/abstract.txt Fri May 1 05:09:19 2009 @@ -9,10 +9,11 @@ Creating a JIT has been one of the main objectives of the PyPy project for quite a while now. As of `March 2009`_, we're able to speed up simple -examples in Python about 20-30x over the speed of CPython. Since PyPy's JIT -is much more flexible than Pysco we expect even greater speedups in the -future, as well as support for floats and 64bit architectures, which Psyco -will not achieve in forseeable future. +examples in Python about 20-30x over the speed of CPython. The JIT also +runs CPython's test suite without crashing. Since PyPy's JIT is much more +flexible than Pysco, we expect even greater speedups in the future, as well +as support for floats and 64bit architectures, which Psyco will not achieve +in forseeable future. In this talk, we will discuss the design principles and future of PyPy's JIT but won't go into too many architectural details. From fijal at codespeak.net Fri May 1 05:39:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 05:39:49 +0200 (CEST) Subject: [pypy-svn] r64918 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501033949.DFD88168536@codespeak.net> Author: fijal Date: Fri May 1 05:39:43 2009 New Revision: 64918 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: incredibly messy hack to finish profiling. Enable profile by default for translated version. 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 May 1 05:39:43 2009 @@ -20,6 +20,7 @@ from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp from pypy.jit.metainterp.policy import JitPolicy from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper +from pypy.jit.metainterp.jitprof import Profiler # ____________________________________________________________ # Bootstrapping @@ -33,6 +34,7 @@ translate_support_code=True, listops=True, optimizer=Optimizer, + profile=Profiler, **kwds) warmrunnerdesc.finish() translator.warmrunnerdesc = warmrunnerdesc # for later debugging @@ -122,6 +124,7 @@ self.metainterp_sd.generate_bytecode(policy, self.ts) self.make_enter_function() self.rewrite_can_enter_jit() + self.rewrite_entry_point() self.metainterp_sd.num_green_args = self.num_green_args self.metainterp_sd.state = self.state @@ -438,6 +441,24 @@ origblock.recloseblock(Link([v_result], origportalgraph.returnblock)) checkgraph(origportalgraph) + def rewrite_entry_point(self): + def finish_profiler(): + self.metainterp_sd.profiler.finish() + + if self.cpu.translate_support_code: + entry_point = self.translator.graphs[0] + TP = lltype.Ptr(lltype.FuncType([], lltype.Void)) + profiler_ptr = self.helper_func(TP, finish_profiler) + for block in entry_point.iterblocks(): + for link in block.exits: + if link.target is entry_point.returnblock: + v = Variable() + v.concretetype = lltype.Void + newop = SpaceOperation('direct_call', + [Constant(profiler_ptr, TP)], + v) + block.operations.append(newop) + checkgraph(entry_point) def decode_hp_hint_args(op): # Returns (list-of-green-vars, list-of-red-vars) without Voids. From fijal at codespeak.net Fri May 1 06:47:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 06:47:20 +0200 (CEST) Subject: [pypy-svn] r64919 - pypy/build/bot2/pypybuildbot Message-ID: <20090501044720.A774B1683DD@codespeak.net> Author: fijal Date: Fri May 1 06:47:10 2009 New Revision: 64919 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: I don't completely understand why this is not needed on a normal build, but it seems it's needed there :-( Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri May 1 06:47:10 2009 @@ -204,7 +204,8 @@ self.addStep(ShellCmd( description="lib-python test", - command=["python", "pypy/test_all.py", - "--pypy=pypy/translator/goal/pypy-c", - "--resultlog=cpython.log", "lib-python"], + command=["python", "test_all.py", + "--pypy=translator/goal/pypy-c", + "--resultlog=../cpython.log", "../lib-python"], + workdir="pypy", logfiles={'pytestLog': 'cpython.log'})) From antocuni at codespeak.net Fri May 1 09:51:42 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 09:51:42 +0200 (CEST) Subject: [pypy-svn] r64920 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501075142.35B0B16854B@codespeak.net> Author: antocuni Date: Fri May 1 09:51:41 2009 New Revision: 64920 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: fix ootype translation, broken in r64918 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 May 1 09:51:41 2009 @@ -447,7 +447,7 @@ if self.cpu.translate_support_code: entry_point = self.translator.graphs[0] - TP = lltype.Ptr(lltype.FuncType([], lltype.Void)) + _, TP = self.metainterp_sd.ts.get_FuncType([], lltype.Void) profiler_ptr = self.helper_func(TP, finish_profiler) for block in entry_point.iterblocks(): for link in block.exits: From antocuni at codespeak.net Fri May 1 10:07:25 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 10:07:25 +0200 (CEST) Subject: [pypy-svn] r64921 - pypy/branch/pyjitpl5/pypy/rpython Message-ID: <20090501080725.876C816803C@codespeak.net> Author: antocuni Date: Fri May 1 10:07:17 2009 New Revision: 64921 Modified: pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py Log: merge r54317 from oo-jit/ svn merge svn+ssh://codespeak.net/svn/pypy/branch/oo-jit/pypy/ -r54316:54317 ------------------------------------------------------------------------ r54317 | antocuni | 2008-05-02 14:01:57 +0200 (Fri, 02 May 2008) | 4 lines Changed paths: M /pypy/branch/oo-jit/pypy/rpython/annlowlevel.py forgot to checkin this in in r54301; make cast_object_to_ptr and cast_base_ptr_to_instance ootype-friendly ------------------------------------------------------------------------ Modified: pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py Fri May 1 10:07:17 2009 @@ -462,28 +462,51 @@ return cast_object_to_ptr(base_ptr_lltype(), instance) cast_instance_to_base_ptr._annspecialcase_ = 'specialize:argtype(0)' +def cast_instance_to_base_obj(instance): + return cast_object_to_ptr(base_obj_ootype(), instance) +cast_instance_to_base_obj._annspecialcase_ = 'specialize:argtype(0)' + def base_ptr_lltype(): from pypy.rpython.lltypesystem.rclass import OBJECTPTR return OBJECTPTR +def base_obj_ootype(): + from pypy.rpython.ootypesystem.rclass import OBJECT + return OBJECT + class CastObjectToPtrEntry(extregistry.ExtRegistryEntry): _about_ = cast_object_to_ptr def compute_result_annotation(self, s_PTR, s_object): assert s_PTR.is_constant() - assert isinstance(s_PTR.const, lltype.Ptr) - return annmodel.SomePtr(s_PTR.const) + if isinstance(s_PTR.const, lltype.Ptr): + return annmodel.SomePtr(s_PTR.const) + elif isinstance(s_PTR.const, ootype.Instance): + return annmodel.SomeOOInstance(s_PTR.const) + else: + assert False def specialize_call(self, hop): from pypy.rpython import rpbc PTR = hop.r_result.lowleveltype + if isinstance(PTR, lltype.Ptr): + T = lltype.Ptr + opname = 'cast_pointer' + null = lltype.nullptr(PTR.TO) + elif isinstance(PTR, ootype.Instance): + T = ootype.Instance + opname = 'ooupcast' + null = ootype.null(PTR) + else: + assert False + if isinstance(hop.args_r[1], rpbc.NoneFrozenPBCRepr): - return hop.inputconst(PTR, lltype.nullptr(PTR.TO)) + return hop.inputconst(PTR, null) v_arg = hop.inputarg(hop.args_r[1], arg=1) - assert isinstance(v_arg.concretetype, lltype.Ptr) + assert isinstance(v_arg.concretetype, T) hop.exception_cannot_occur() - return hop.genop('cast_pointer', [v_arg], - resulttype = PTR) + return hop.genop(opname, [v_arg], resulttype = PTR) + # ____________________________________________________________ @@ -513,6 +536,7 @@ # ____________________________________________________________ + def placeholder_sigarg(s): if s == "self": def expand(s_self, *args_s): From antocuni at codespeak.net Fri May 1 10:29:37 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 10:29:37 +0200 (CEST) Subject: [pypy-svn] r64922 - in pypy/branch/pyjitpl5/pypy: annotation jit/backend/minimal jit/backend/minimal/test Message-ID: <20090501082937.57120169E12@codespeak.net> Author: antocuni Date: Fri May 1 10:29:29 2009 New Revision: 64922 Modified: pypy/branch/pyjitpl5/pypy/annotation/builtin.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Log: test_bridge_from_guard_exception passes for ootype: - make do_call ootype friendly - implement guard_exception for ootype Modified: pypy/branch/pyjitpl5/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/builtin.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/builtin.py Fri May 1 10:29:29 2009 @@ -510,7 +510,7 @@ BUILTIN_ANALYZERS[lltype.Ptr] = constPtr # ootype -from pypy.annotation.model import SomeOOInstance, SomeOOClass +from pypy.annotation.model import SomeOOInstance, SomeOOClass, SomeOOStaticMeth from pypy.rpython.ootypesystem import ootype def new(I): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Fri May 1 10:29:29 2009 @@ -183,16 +183,7 @@ if self.current_exc_inst: raise GuardFailed elif opnum == rop.GUARD_EXCEPTION: - assert not self.is_oo - adr = argboxes[0].getaddr(self) - expected_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - ll_assert(bool(expected_class), - "execute_guard: expected_class==NULL") - exc = self.current_exc_inst - if exc and rclass.ll_isinstance(exc, expected_class): - return BoxPtr(self.get_exc_value()) - else: - raise GuardFailed + return self._execute_guard_exception(argboxes) else: ll_assert(False, "execute_guard: unknown guard op") @@ -308,12 +299,11 @@ assert isinstance(calldescr, CallDescr) assert calldescr.call is not None self.clear_exception() - addr_self = args[0].getaddr(self) + func = self._get_func(args[0]) try: - box = calldescr.call(self, addr_self, args[1:]) + box = calldescr.call(self, func, args[1:]) except Exception, e: - from pypy.rpython.annlowlevel import cast_instance_to_base_ptr - self.current_exc_inst = cast_instance_to_base_ptr(e) + self.current_exc_inst = self._cast_instance_to_base(e) if DEBUG: print '\tcall raised!', self.current_exc_inst box = calldescr.errbox @@ -338,6 +328,9 @@ class LLtypeCPU(BaseCPU): is_oo = False + # ---------------- + # template methods + def _get_fake_inst(self): ll_inst = lltype.malloc(rclass.OBJECT) ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, @@ -364,6 +357,26 @@ i += len(STRUCT._names) + 1 return i + def _get_func(self, funcbox): + return funcbox.getaddr(self) + + def _cast_instance_to_base(self, e): + from pypy.rpython.annlowlevel import cast_instance_to_base_ptr + return cast_instance_to_base_ptr(e) + + def _execute_guard_exception(self, argboxes): + adr = argboxes[0].getaddr(self) + expected_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) + ll_assert(bool(expected_class), + "execute_guard: expected_class==NULL") + exc = self.current_exc_inst + if exc and rclass.ll_isinstance(exc, expected_class): + return BoxPtr(self.get_exc_value()) + else: + raise GuardFailed + + # ---------------- + @cached_method('_sizecache') def sizeof(self, TYPE): def alloc(): @@ -487,6 +500,9 @@ class OOtypeCPU(BaseCPU): is_oo = True + # ---------------- + # template methods + def _get_fake_inst(self): return ootype.new(ootype.ROOT) @@ -507,6 +523,27 @@ def _cast_error_inst(self, ll_inst): return ootype.cast_to_object(ll_inst) + def _get_func(self, funcbox): + return funcbox.getobj() + + def _cast_instance_to_base(self, e): + from pypy.rpython.annlowlevel import cast_instance_to_base_obj + return ootype.cast_to_object(cast_instance_to_base_obj(e)) + + def _execute_guard_exception(self, argboxes): + obj = argboxes[0].getobj() + expected_class = ootype.cast_from_object(ootype.Class, obj) + ll_assert(bool(expected_class), + "execute_guard: expected_class==NULL") + exc = ootype.cast_from_object(ootype.ROOT, self.current_exc_inst) + if exc: + exc_class = ootype.classof(exc) + if ootype.subclassof(expected_class, exc_class): + return BoxObj(self.get_exc_value()) + raise GuardFailed + + # ---------------- + @cached_method('_typedescrcache') def typedescrof(self, TYPE): def alloc(): @@ -518,6 +555,8 @@ def methdescrof(self, SELFTYPE, methname): return MethDescr(SELFTYPE, methname) + # ---------------- + def do_new_with_vtable(self, args, sizedescr): assert isinstance(sizedescr, SizeDescr) assert sizedescr.alloc is not None Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Fri May 1 10:29:29 2009 @@ -26,7 +26,6 @@ def skip(self): py.test.skip('in-progress') - test_bridge_from_guard_exception = skip test_bridge_from_guard_no_exception = skip test_loop = skip test_four_levels_checks = skip From antocuni at codespeak.net Fri May 1 10:33:22 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 10:33:22 +0200 (CEST) Subject: [pypy-svn] r64923 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test Message-ID: <20090501083322.614E6169E12@codespeak.net> Author: antocuni Date: Fri May 1 10:33:15 2009 New Revision: 64923 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Log: cool, these two tests pass out of the box, and test_four_levels_checks is skipped anyway Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Fri May 1 10:33:15 2009 @@ -26,9 +26,6 @@ def skip(self): py.test.skip('in-progress') - test_bridge_from_guard_no_exception = skip - test_loop = skip - test_four_levels_checks = skip test_exception_from_outside = skip test_exception_from_outside_2 = skip test_exception_two_cases = skip From antocuni at codespeak.net Fri May 1 10:41:00 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 10:41:00 +0200 (CEST) Subject: [pypy-svn] r64924 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test Message-ID: <20090501084100.04DA0168050@codespeak.net> Author: antocuni Date: Fri May 1 10:40:52 2009 New Revision: 64924 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Log: a lot of tests pass out of the box, due to previous checkins Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Fri May 1 10:40:52 2009 @@ -26,15 +26,6 @@ def skip(self): py.test.skip('in-progress') - test_exception_from_outside = skip - test_exception_from_outside_2 = skip - test_exception_two_cases = skip - test_exception_two_cases_2 = skip - test_exception_later = skip - test_exception_and_then_no_exception = skip - test_int_ovf = skip - test_int_mod_ovf_zer = skip - test_int_lshift_ovf = skip test_reraise_through_portal = skip test_bridge_from_interpreter_exc = skip test_bridge_from_interpreter_exc_2 = skip From antocuni at codespeak.net Fri May 1 10:48:13 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 10:48:13 +0200 (CEST) Subject: [pypy-svn] r64925 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501084813.D82F0169E1F@codespeak.net> Author: antocuni Date: Fri May 1 10:48:08 2009 New Revision: 64925 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: don't call broken code 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 May 1 10:48:08 2009 @@ -124,7 +124,7 @@ self.metainterp_sd.generate_bytecode(policy, self.ts) self.make_enter_function() self.rewrite_can_enter_jit() - self.rewrite_entry_point() + #self.rewrite_entry_point() XXX broken when the last block handles exceptions self.metainterp_sd.num_green_args = self.num_green_args self.metainterp_sd.state = self.state From antocuni at codespeak.net Fri May 1 10:49:33 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 10:49:33 +0200 (CEST) Subject: [pypy-svn] r64926 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test Message-ID: <20090501084933.21AC3169E1F@codespeak.net> Author: antocuni Date: Fri May 1 10:49:32 2009 New Revision: 64926 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Log: one more passing test Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Fri May 1 10:49:32 2009 @@ -26,7 +26,6 @@ def skip(self): py.test.skip('in-progress') - test_reraise_through_portal = skip test_bridge_from_interpreter_exc = skip test_bridge_from_interpreter_exc_2 = skip test_raise = skip From arigo at codespeak.net Fri May 1 11:05:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 11:05:13 +0200 (CEST) Subject: [pypy-svn] r64927 - pypy/build/bot2/pypybuildbot Message-ID: <20090501090513.F2E62169E9E@codespeak.net> Author: arigo Date: Fri May 1 11:05:04 2009 New Revision: 64927 Modified: pypy/build/bot2/pypybuildbot/summary.py Log: Hide the line "builds aborted without getting a revision:" if nothing follows. Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 11:05:04 2009 @@ -437,6 +437,8 @@ self.sections.append(section) def add_no_revision_builds(self, status, no_revision_builds): + if not no_revision_builds: + return section = html.div(html.p("builds aborted without getting" " a revision:")) From antocuni at codespeak.net Fri May 1 11:10:32 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 11:10:32 +0200 (CEST) Subject: [pypy-svn] r64928 - in pypy/branch/pyjitpl5/pypy/rpython/ootypesystem: . test Message-ID: <20090501091032.3D5C9169E90@codespeak.net> Author: antocuni Date: Fri May 1 11:10:25 2009 New Revision: 64928 Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Log: implement '==' and '!=' for ootype classes Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py Fri May 1 11:10:25 2009 @@ -113,6 +113,19 @@ v = rpair.rtype_eq(hop) return hop.genop("bool_not", [v], resulttype=ootype.Bool) + +class __extend__(pairtype(OOClassRepr, OOClassRepr)): + def rtype_is_((r_obj1, r_obj2), hop): + vlist = hop.inputargs(r_obj1, r_obj2) + return hop.genop('oois', vlist, resulttype=ootype.Bool) + + rtype_eq = rtype_is_ + + def rtype_ne(rpair, hop): + v = rpair.rtype_eq(hop) + return hop.genop("bool_not", [v], resulttype=ootype.Bool) + + class OOBoundMethRepr(Repr): def __init__(self, ootype, name): self.lowleveltype = ootype Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Fri May 1 11:10:25 2009 @@ -403,3 +403,21 @@ g = gengraph(f) rettype = g.getreturnvar().concretetype assert rettype._hints['immutable'] + + +def test_compare_classes(): + A = ootype.Instance("A", ootype.ROOT) + B = ootype.Instance("B", ootype.ROOT) + + cls1 = ootype.runtimeClass(A) + def fn(n): + if n: + cls2 = ootype.runtimeClass(A) + else: + cls2 = ootype.runtimeClass(B) + + assert (cls1 == cls2) == (not (cls1 != cls2)) + return cls1 == cls2 + + res = interpret(fn, [1], type_system='ootype') + assert res From antocuni at codespeak.net Fri May 1 11:13:15 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 11:13:15 +0200 (CEST) Subject: [pypy-svn] r64929 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test Message-ID: <20090501091315.32C52169E90@codespeak.net> Author: antocuni Date: Fri May 1 11:13:12 2009 New Revision: 64929 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Log: cool, test_zrpy_exception fully passes on ootype Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_exception.py Fri May 1 11:13:12 2009 @@ -22,17 +22,7 @@ class TestOOtype(OOTranslatedJitMixin, test_zrpy_exception.TestLLExceptions): - - def skip(self): - py.test.skip('in-progress') - - test_bridge_from_interpreter_exc = skip - test_bridge_from_interpreter_exc_2 = skip - test_raise = skip - test_raise_through = skip - test_raise_through_wrong_exc = skip - test_raise_through_wrong_exc_2 = skip - + pass class TestLLtype(LLTranslatedJitMixin, test_zrpy_exception.TestLLExceptions): From pedronis at codespeak.net Fri May 1 11:53:36 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 11:53:36 +0200 (CEST) Subject: [pypy-svn] r64930 - in pypy/build/bot2: codespeak-html pypybuildbot pypybuildbot/test Message-ID: <20090501095336.58986169EB0@codespeak.net> Author: pedronis Date: Fri May 1 11:53:32 2009 New Revision: 64930 Added: pypy/build/bot2/codespeak-html/sucess.png (contents, props changed) Modified: pypy/build/bot2/pypybuildbot/summary.py pypy/build/bot2/pypybuildbot/test/test_summary.py Log: display when the last run was fine Added: pypy/build/bot2/codespeak-html/sucess.png ============================================================================== Binary file. No diff available. Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 11:53:32 2009 @@ -306,7 +306,7 @@ anchors.append(' (%s..%s)' % (mintxt, maxtxt)) return anchors - def start_cat_branch(self, cat_branch): + def _start_cat_branch(self, cat_branch, fine=False): category, branch = cat_branch branch = trunk_name(branch) category = category_name(category) @@ -321,8 +321,11 @@ href="/summary?category=%s&branch=%s" % cat_branch, class_="failSummary branch") - - self.sections.append(html.h2(cat_anchor," ",branch_anchor)) + if fine: + extra = html.img(alt=":-)", src="sucess.png") + else: + extra = "" + self.sections.append(html.h2(cat_anchor," ",branch_anchor, " ", extra)) def _builder_anchor(self, builder): if self.fixed_builder: @@ -359,7 +362,7 @@ rightalign = ' '*(revsize-len(revtxt)) return [rev_anchor, rightalign] - def add_section(self, outcome_sets): + def add_section(self, cat_branch, outcome_sets): if not outcome_sets: return labels = sorted(self._label(outcome_set) @@ -368,10 +371,11 @@ for outcome_set in outcome_sets) revs = [outcome_set.revision for outcome_set in outcome_sets] + _, last = by_label[-1] + self._start_cat_branch(cat_branch, fine = not last.failed) + lines = [] - revsize = len(str(max(revs))) - align = 2*len(labels)-1+revsize def bars(): return ' |'*len(lines) @@ -704,8 +708,7 @@ outcome_sets = [] for label, by_build in runs.items(): outcome_sets.append(GatherOutcomeSet(by_build)) - page.start_cat_branch(cat_branch) - page.add_section(outcome_sets) + page.add_section(cat_branch, outcome_sets) page.add_no_revision_builds(status, no_revision_builds) t1 = time.time() Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Fri May 1 11:53:32 2009 @@ -449,7 +449,7 @@ def test_two_builds(self): builder = status_builder.BuilderStatus('builder0') add_builds(builder, [(60000, "F TEST1\n. b"), - (60001, "F TEST1\n. b")]) + (60001, ". TEST1\n. b")]) s = summary.Summary() res = witness_cat_branch(s) @@ -472,7 +472,8 @@ assert revs == [60000, 60001] - assert 'TEST1' in out + assert 'TEST1' in out + assert ':-)' in out def test_two_builds_samerev(self): builder = status_builder.BuilderStatus('builder0') From jandem at codespeak.net Fri May 1 12:04:43 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Fri, 1 May 2009 12:04:43 +0200 (CEST) Subject: [pypy-svn] r64931 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090501100443.B9B441680C1@codespeak.net> Author: jandem Date: Fri May 1 12:04:43 2009 New Revision: 64931 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: Fix String.prototype tests and make it easier to set 'length' for builtins Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri May 1 12:04:43 2009 @@ -82,6 +82,7 @@ return create_object(ctx, 'Number', Value = W_FloatNumber(0.0)) class W_StringObject(W_NativeObject): + length = 1 def Call(self, ctx, args=[], this=None): if len(args) >= 1: return W_String(args[0].ToString(ctx)) @@ -363,6 +364,7 @@ return W_ValueValueOf class W_FromCharCode(W_NewBuiltin): + length = 1 def Call(self, ctx, args=[], this=None): temp = [] for arg in args: @@ -371,6 +373,7 @@ return W_String(''.join(temp)) class W_CharAt(W_NewBuiltin): + length = 1 def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) if len(args)>=1: @@ -401,6 +404,7 @@ return W_String(string) class W_IndexOf(W_NewBuiltin): + length = 1 def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) if len(args) < 1: @@ -416,6 +420,7 @@ return W_IntNumber(string.find(substr, pos)) class W_Substring(W_NewBuiltin): + length = 2 def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) size = len(string) @@ -434,6 +439,7 @@ return W_String(string[start:end]) class W_Split(W_NewBuiltin): + length = 2 def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) @@ -459,11 +465,13 @@ return w_array class W_ToLowerCase(W_NewBuiltin): + length = 0 def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) return W_String(string.lower()) class W_ToUpperCase(W_NewBuiltin): + length = 0 def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) return W_String(string.upper()) @@ -488,6 +496,7 @@ return W_String(common_join(ctx, this, sep=',')) class W_ArrayJoin(W_NewBuiltin): + length = 1 def Call(self, ctx, args=[], this=None): if len(args) >= 1 and not args[0] is w_Undefined: sep = args[0].ToString(ctx) @@ -635,52 +644,36 @@ w_StrPrototype = create_object(ctx, 'Object', Value=W_String('')) w_StrPrototype.Class = 'String' - - w_CharAt = W_CharAt(ctx) - w_CharAt.Put(ctx, 'length', W_IntNumber(1), flags=allon) - - # 15.5.4.14 - w_Split = W_Split(ctx) - w_Split.Put(ctx, 'length', W_IntNumber(2), flags=allon) - - # 15.5.4.7 - w_IndexOf = W_IndexOf(ctx) - w_IndexOf.Put(ctx, 'length', W_IntNumber(1), flags=allon) + w_StrPrototype.Put(ctx, 'length', W_IntNumber(0)) put_values(ctx, w_StrPrototype, { - 'constructor': w_FncPrototype, + 'constructor': w_String, '__proto__': w_StrPrototype, 'toString': W_StringValueToString(ctx), 'valueOf': get_value_of('String')(ctx), - 'charAt': w_CharAt, + 'charAt': W_CharAt(ctx), 'charCodeAt': W_CharCodeAt(ctx), 'concat': W_Concat(ctx), - 'indexOf': w_IndexOf, + 'indexOf': W_IndexOf(ctx), 'substring': W_Substring(ctx), - 'split': w_Split, + 'split': W_Split(ctx), 'toLowerCase': W_ToLowerCase(ctx), 'toUpperCase': W_ToUpperCase(ctx) }) - # 15.5.3.2 - w_FromCharCode = W_FromCharCode(ctx) - w_FromCharCode.Put(ctx, 'length', W_IntNumber(1), flags=allon) - - w_String.Put(ctx, 'prototype', w_StrPrototype) - w_String.Put(ctx, 'fromCharCode', w_FromCharCode) + w_String.Put(ctx, 'prototype', w_StrPrototype, flags=allon) + w_String.Put(ctx, 'fromCharCode', W_FromCharCode(ctx)) w_Global.Put(ctx, 'String', w_String) w_Array = W_ArrayObject('Array', w_FncPrototype) w_ArrPrototype = W_Array(Prototype=w_ObjPrototype) - w_arr_join = W_ArrayJoin(ctx) - w_arr_join.Put(ctx, 'length', W_IntNumber(1), flags=allon) put_values(ctx, w_ArrPrototype, { 'constructor': w_FncPrototype, '__proto__': w_ArrPrototype, 'toString': W_ArrayToString(ctx), - 'join': w_arr_join, + 'join': W_ArrayJoin(ctx), 'reverse': W_ArrayReverse(ctx), }) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri May 1 12:04:43 2009 @@ -108,6 +108,7 @@ class W_PrimitiveObject(W_Root): + length = -1 def __init__(self, ctx=None, Prototype=None, Class='Object', Value=w_Undefined, callfunc=None): self.propdict = {} @@ -122,6 +123,9 @@ else: self.Scope = None self.Value = Value + + if self.length != -1: + self.Put(ctx, 'length', W_IntNumber(self.length), flags = DE|DD|RO) def Call(self, ctx, args=[], this=None): if self.callfunc is None: # XXX Not sure if I should raise it here From arigo at codespeak.net Fri May 1 12:14:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 12:14:56 +0200 (CEST) Subject: [pypy-svn] r64932 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501101456.7D9671684BD@codespeak.net> Author: arigo Date: Fri May 1 12:14:55 2009 New Revision: 64932 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: Revert the (accidental?) disabling of check_descr(). Add a comment "don't do that". 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 May 1 12:14:55 2009 @@ -588,7 +588,6 @@ raise NotImplementedError class History(RunningMatcher): - extratext = '' def record(self, opnum, argboxes, resbox, descr=None): op = ResOperation(opnum, argboxes, resbox, descr) @@ -698,7 +697,8 @@ _about_ = check_descr def compute_result_annotation(self, s_x): - return + # Failures here mean that 'descr' is not correctly an AbstractDescr. + # Please don't check in disabling of this test! from pypy.annotation import model as annmodel if not annmodel.s_None.contains(s_x): assert isinstance(s_x, annmodel.SomeInstance) From pedronis at codespeak.net Fri May 1 12:38:54 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 12:38:54 +0200 (CEST) Subject: [pypy-svn] r64933 - in pypy/build/bot2: codespeak-html pypybuildbot pypybuildbot/test Message-ID: <20090501103854.A6E4D168547@codespeak.net> Author: pedronis Date: Fri May 1 12:38:51 2009 New Revision: 64933 Added: pypy/build/bot2/codespeak-html/success.png - copied unchanged from r64930, pypy/build/bot2/codespeak-html/sucess.png Removed: pypy/build/bot2/codespeak-html/sucess.png Modified: pypy/build/bot2/codespeak-html/buildbot.css pypy/build/bot2/pypybuildbot/summary.py pypy/build/bot2/pypybuildbot/test/test_summary.py Log: more success display Modified: pypy/build/bot2/codespeak-html/buildbot.css ============================================================================== --- pypy/build/bot2/codespeak-html/buildbot.css (original) +++ pypy/build/bot2/codespeak-html/buildbot.css Fri May 1 12:38:51 2009 @@ -78,6 +78,11 @@ } /* failure summary */ +.failSummary.success { + color: #408000; + font-weight: bold; +} + .failSummary.failed { color: #E00000; font-weight: bold; Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 12:38:51 2009 @@ -322,7 +322,7 @@ cat_branch, class_="failSummary branch") if fine: - extra = html.img(alt=":-)", src="sucess.png") + extra = html.img(alt=":-)", src="success.png") else: extra = "" self.sections.append(html.h2(cat_anchor," ",branch_anchor, " ", extra)) @@ -388,7 +388,18 @@ line.append('\n') lines.append(line) lines.append([bars(), "\n"]) - + + success = [] + for label, outcome_set in by_label: + if not outcome_set.failed: + success.append([" ", + html.span("+", + class_="failSummary success")]) + else: + success.append(" ") + success.append(" success\n") + lines.append(success) + failed = set() exploded = set() for label, outcome_set in by_label: Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Fri May 1 12:38:51 2009 @@ -474,6 +474,7 @@ assert 'TEST1' in out assert ':-)' in out + assert '\n + success' in out def test_two_builds_samerev(self): builder = status_builder.BuilderStatus('builder0') From pedronis at codespeak.net Fri May 1 12:44:34 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 12:44:34 +0200 (CEST) Subject: [pypy-svn] r64934 - pypy/build/bot2/codespeak-html Message-ID: <20090501104434.90D3A168547@codespeak.net> Author: pedronis Date: Fri May 1 12:44:33 2009 New Revision: 64934 Modified: pypy/build/bot2/codespeak-html/buildbot.css Log: avoid picking up buildbot own css values Modified: pypy/build/bot2/codespeak-html/buildbot.css ============================================================================== --- pypy/build/bot2/codespeak-html/buildbot.css (original) +++ pypy/build/bot2/codespeak-html/buildbot.css Fri May 1 12:44:33 2009 @@ -80,6 +80,7 @@ /* failure summary */ .failSummary.success { color: #408000; + background-color: #ffffff; font-weight: bold; } From david at codespeak.net Fri May 1 13:06:19 2009 From: david at codespeak.net (david at codespeak.net) Date: Fri, 1 May 2009 13:06:19 +0200 (CEST) Subject: [pypy-svn] r64935 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090501110619.A9426168511@codespeak.net> Author: david Date: Fri May 1 13:06:18 2009 New Revision: 64935 Added: pypy/branch/io-lang/pypy/lang/io/list.py pypy/branch/io-lang/pypy/lang/io/test/test_list.py Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/objspace.py Log: Basic List implementation, List proto, cloning, append and item access Added: pypy/branch/io-lang/pypy/lang/io/list.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/list.py Fri May 1 13:06:18 2009 @@ -0,0 +1,15 @@ +from pypy.lang.io.register import register_method +from pypy.lang.io.model import W_Number + at register_method('List', 'append') +def list_append(space, w_target, w_message, w_context): + assert w_message.arguments, 'requires at least one argument' + w_items = [x.eval(space, w_target, w_context) for x in w_message.arguments] + w_target.append(w_items) + return w_target + + at register_method('List', 'at') +def list_at(space, w_target, w_message, w_context): + assert len(w_message.arguments) > 0 + w_item = w_message.arguments[0].eval(space, w_target, w_context) + assert isinstance(w_item, W_Number) + return w_target[w_item.value] \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Fri May 1 13:06:18 2009 @@ -44,8 +44,28 @@ return cloned class W_List(W_Object): - pass - + def __init__(self, space, protos = [], items = []): + W_Object.__init__(self, space, protos) + self.items = items + + def append(self, w_items): + self.items += w_items + + def __getitem__(self, index): + try: + return self.items[index] + except IndexError: + return self.space.w_nil + + + def clone(self): + return W_List(self.space, [self], list(self.items)) + + def clone_and_init(self, space, items): + l = self.clone() + l.items += items + return l + class W_ImmutableSequence(W_Object): def __init__(self, space, string): self.value = string @@ -79,6 +99,7 @@ w_result = self.literal_value else: w_method = w_receiver.lookup(self.name) + assert w_method is not None, 'Method "%s" not found in "%s"' % (self.name, w_receiver.__class__) w_result = w_method.apply(space, w_receiver, self, w_context) if self.next: #TODO: optimize @@ -94,8 +115,6 @@ self.activateable = activateable def apply(self, space, w_receiver, w_message, w_context): - # TODO: move the call logic to a call method to use with blocks also - # TODO: store if the block is activateable (a method) or not # TODO: create and populate call object if self.activateable: return self.call(space, w_receiver, w_message, w_context) Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Fri May 1 13:06:18 2009 @@ -36,5 +36,9 @@ def w_object_clone(space, w_target, w_message, w_context): assert w_message.name == 'clone' return w_target.clone() -# def w_object_get_slot(w_target, w_message, w_context): -# pass \ No newline at end of file + + at register_method('Object', 'list') +def w_object_list(space, w_target, w_message, w_context): + w_items = [x.eval(space, w_target, w_context) for x in w_message.arguments] + return space.w_list.clone_and_init(space, w_items) + \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/objspace.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/objspace.py (original) +++ pypy/branch/io-lang/pypy/lang/io/objspace.py Fri May 1 13:06:18 2009 @@ -1,10 +1,11 @@ from pypy.rlib.objectmodel import instantiate -from pypy.lang.io.model import W_Number, W_Object, W_CFunction, W_Block, W_Message +from pypy.lang.io.model import W_Number, W_Object, W_CFunction, W_Block, W_Message, W_List from pypy.lang.io.register import cfunction_definitions import pypy.lang.io.number import pypy.lang.io.object import pypy.lang.io.block +import pypy.lang.io.list class ObjSpace(object): """docstring for ObjSpace""" @@ -18,12 +19,16 @@ self.w_false = W_Object(self, [self.w_object]) self.w_nil = W_Object(self, [self.w_object]) self.w_block = W_Block(self, [], W_Message(self, 'nil', []), False, [self.w_object]) + self.w_list = W_List(self, [self.w_object]) + self.w_core.protos.append(self.w_object) self.w_protos.protos.append(self.w_core) self.w_protos.slots['Core'] = self.w_core + self.init_w_list() + self.init_w_block() self.init_w_lobby() @@ -32,13 +37,13 @@ self.init_w_core() - # self.init_singletons() - # - # def init_singletons(self): - # #true, false, nil, Message, Call, Normal, Break, Continue, Return def init_w_block(self): for key, function in cfunction_definitions['Block'].items(): self.w_block.slots[key] = W_CFunction(self, function) + + def init_w_list(self): + for key, function in cfunction_definitions['List'].items(): + self.w_list.slots[key] = W_CFunction(self, function) def init_w_core(self): self.w_core.slots['Locals'] = self.w_locals @@ -47,6 +52,7 @@ self.w_core.slots['true'] = self.w_true self.w_core.slots['false'] = self.w_false self.w_core.slots['nil'] = self.w_nil + self.w_core.slots['List'] = self.w_list def init_w_number(self): self.w_number = instantiate(W_Number) Added: pypy/branch/io-lang/pypy/lang/io/test/test_list.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_list.py Fri May 1 13:06:18 2009 @@ -0,0 +1,49 @@ +from pypy.lang.io.parserhack import parse, interpret +from pypy.lang.io.model import W_List, W_Number +import py.test + + +def test_parse_empty_list(): + inp = "a := list()\na" + res,space = interpret(inp) + assert isinstance(res, W_List) + assert res.items == [] + +def test_parse_list(): + inp = "a := list(1,2,3)\na" + res,space = interpret(inp) + assert isinstance(res, W_List) + assert res.items == [W_Number(space, 1), W_Number(space, 2), W_Number(space, 3)] + +def test_list_proto(): + inp = "a := list(1,2,3)\na" + res,space = interpret(inp) + assert isinstance(res, W_List) + assert res.protos == [space.w_list] + assert space.w_list.protos == [space.w_object] + +def test_list_append(): + inp = "a := list(); a append(1)" + res,space = interpret(inp) + assert res.items == [W_Number(space, 1)] + +def test_list_at(): + inp = "a := list(1,2,3); a at(2)" + res,space = interpret(inp) + assert res.value == 3 + +def test_list_at_out_of_range_is_nil(): + inp = "a := list(1,2,3); a at(1234)" + res,space = interpret(inp) + assert res == space.w_nil + +def test_list_at_requires_arg(): + inp = "a := list(1,2,3); a at()" + # Unspecified exception until error handling are introduced + assert py.test.raises(Exception, 'interpret(inp)') + +def test_list_at_requires_numeric_arg(): + inp = 'a := list(1,2,3); a at("2")' + # Unspecified exception until error handling are introduced + assert py.test.raises(Exception, 'interpret(inp)') + \ No newline at end of file From pedronis at codespeak.net Fri May 1 13:15:23 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 13:15:23 +0200 (CEST) Subject: [pypy-svn] r64936 - pypy/build/bot2/pypybuildbot Message-ID: <20090501111523.D79A316856F@codespeak.net> Author: pedronis Date: Fri May 1 13:15:22 2009 New Revision: 64936 Modified: pypy/build/bot2/pypybuildbot/summary.py Log: make this optional for the other kind of vertical space police Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 13:15:22 2009 @@ -252,6 +252,7 @@ class SummaryPage(object): + SUCCESS_LINE = True def __init__(self, status): self.sections = [] @@ -389,16 +390,17 @@ lines.append(line) lines.append([bars(), "\n"]) - success = [] - for label, outcome_set in by_label: - if not outcome_set.failed: - success.append([" ", - html.span("+", - class_="failSummary success")]) - else: - success.append(" ") - success.append(" success\n") - lines.append(success) + if self.SUCCESS_LINE: + success = [] + for label, outcome_set in by_label: + if not outcome_set.failed: + success.append([" ", + html.span("+", + class_="failSummary success")]) + else: + success.append(" ") + success.append(" success\n") + lines.append(success) failed = set() exploded = set() From pedronis at codespeak.net Fri May 1 13:27:08 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 13:27:08 +0200 (CEST) Subject: [pypy-svn] r64937 - in pypy/build/bot2/pypybuildbot: . test Message-ID: <20090501112708.71C9F168578@codespeak.net> Author: pedronis Date: Fri May 1 13:27:07 2009 New Revision: 64937 Modified: pypy/build/bot2/pypybuildbot/summary.py pypy/build/bot2/pypybuildbot/test/test_summary.py Log: always fill in the success meta-line Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 13:27:07 2009 @@ -393,12 +393,14 @@ if self.SUCCESS_LINE: success = [] for label, outcome_set in by_label: - if not outcome_set.failed: - success.append([" ", - html.span("+", - class_="failSummary success")]) - else: - success.append(" ") + symbol = "+" + clazz = "success" + if outcome_set.failed: + symbol = "-" + clazz = "failed" + success.append([" ", + html.span(symbol, + class_="failSummary "+clazz)]) success.append(" success\n") lines.append(success) Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Fri May 1 13:27:07 2009 @@ -474,7 +474,7 @@ assert 'TEST1' in out assert ':-)' in out - assert '\n + success' in out + assert '\n - + success' in out def test_two_builds_samerev(self): builder = status_builder.BuilderStatus('builder0') From arigo at codespeak.net Fri May 1 13:58:24 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 13:58:24 +0200 (CEST) Subject: [pypy-svn] r64938 - pypy/trunk/pypy/doc Message-ID: <20090501115824.DD39E169DFF@codespeak.net> Author: arigo Date: Fri May 1 13:58:22 2009 New Revision: 64938 Modified: pypy/trunk/pypy/doc/getting-started-python.txt Log: Add a warning. Modified: pypy/trunk/pypy/doc/getting-started-python.txt ============================================================================== --- pypy/trunk/pypy/doc/getting-started-python.txt (original) +++ pypy/trunk/pypy/doc/getting-started-python.txt Fri May 1 13:58:22 2009 @@ -284,8 +284,9 @@ Now you are ready to start running Python code. Most Python modules should work if they don't involve CPython extension -modules. Here is an example of determining PyPy's performance -in pystones:: +modules. **This is slow, and most C modules are not present by +default even if they are standard!** Here is an example of +determining PyPy's performance in pystones:: >>>> from test import pystone >>>> pystone.main(10) From jandem at codespeak.net Fri May 1 14:08:14 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Fri, 1 May 2009 14:08:14 +0200 (CEST) Subject: [pypy-svn] r64939 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090501120814.B3EC6169DFF@codespeak.net> Author: jandem Date: Fri May 1 14:08:13 2009 New Revision: 64939 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Implement String.prototype.lastIndexOf Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri May 1 14:08:13 2009 @@ -419,6 +419,26 @@ pos = min(max(pos, 0), size) return W_IntNumber(string.find(substr, pos)) +class W_LastIndexOf(W_NewBuiltin): + length = 1 + def Call(self, ctx, args=[], this=None): + string = this.ToString(ctx) + if len(args) < 1: + return W_IntNumber(-1) + substr = args[0].ToString(ctx) + if len(args) < 2: + pos = INFINITY + else: + val = args[1].ToNumber(ctx) + if isnan(val): + pos = INFINITY + else: + pos = args[1].ToInteger(ctx) + size = len(string) + pos = min(max(pos, 0), size) + subsize = len(substr) + return W_IntNumber(string.rfind(substr, 0, pos+subsize)) + class W_Substring(W_NewBuiltin): length = 2 def Call(self, ctx, args=[], this=None): @@ -655,6 +675,7 @@ 'charCodeAt': W_CharCodeAt(ctx), 'concat': W_Concat(ctx), 'indexOf': W_IndexOf(ctx), + 'lastIndexOf': W_LastIndexOf(ctx), 'substring': W_Substring(ctx), 'split': W_Split(ctx), 'toLowerCase': W_ToLowerCase(ctx), From arigo at codespeak.net Fri May 1 14:17:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 14:17:38 +0200 (CEST) Subject: [pypy-svn] r64940 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090501121738.DB6E2168064@codespeak.net> Author: arigo Date: Fri May 1 14:17:38 2009 New Revision: 64940 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: The most important change is a fix in the placement of profiler.start_tracing() and end_tracing(). Also counts for how long the backend compiled the operations. 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 May 1 14:17:38 2009 @@ -113,7 +113,9 @@ return loop def send_loop_to_backend(metainterp, loop, type): + metainterp.staticdata.profiler.start_backend() metainterp.cpu.compile_operations(loop) + metainterp.staticdata.profiler.end_backend() if not we_are_translated(): if type != "entry bridge": metainterp.staticdata.stats.compiled_count += 1 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Fri May 1 14:17:38 2009 @@ -5,41 +5,44 @@ import time TRACING = 0 -RUNNING = 1 -BLACKHOLE = 2 -LAST_START = 2 -END_TRACING = 3 -END_RUNNING = 4 -END_BLACKHOLE = 5 +BACKEND = 1 +RUNNING = 2 +BLACKHOLE = 3 +LAST_START = 3 + +END_TRACING = 4 +END_BACKEND = 5 +END_RUNNING = 6 +END_BLACKHOLE = 7 class EmptyProfiler(object): - initialized = False + initialized = True def start(self): pass def finish(self): pass - - def start_normal(self, greenkey=None): + + def start_tracing(self): pass - def end_normal(self): + def end_tracing(self): pass - def start_tracing(self, greenkey=None): + def start_backend(self): pass - def end_tracing(self): + def end_backend(self): pass - def start_running(self, greenkey=None): + def start_running(self): pass def end_running(self): pass - def start_blackhole(self, greenkey=None): + def start_blackhole(self): pass def end_blackhole(self): @@ -58,19 +61,25 @@ self.summarize() self.print_stats() - def start_tracing(self, greenkey=None): + def start_tracing(self): self.events.append((self.timer(), TRACING)) def end_tracing(self): self.events.append((self.timer(), END_TRACING)) - def start_running(self, greenkey=None): + def start_backend(self): + self.events.append((self.timer(), BACKEND)) + + def end_backend(self): + self.events.append((self.timer(), END_BACKEND)) + + def start_running(self): self.events.append((self.timer(), RUNNING)) def end_running(self): self.events.append((self.timer(), END_RUNNING)) - def start_blackhole(self, greenkey=None): + def start_blackhole(self): self.events.append((self.timer(), BLACKHOLE)) def end_blackhole(self): @@ -79,7 +88,7 @@ def summarize(self): current = [] t = 0 - times = [0, 0, 0] + times = [0, 0, 0, 0] for t0, ev in self.events: if ev <= LAST_START: if current: @@ -89,12 +98,13 @@ times[current.pop()] += t0 - t t = t0 self.trace_time = times[TRACING] + self.backend_time = times[BACKEND] self.run_time = times[RUNNING] self.blackhole_time = times[BLACKHOLE] def print_stats(self): - print "Total: %f" % (self.tk - self.t0) - print "Tracing: %f" % self.trace_time - print "Running: %f" % self.run_time - print "Blackhole: %f" % self.blackhole_time - + print "Tracing: %f" % self.trace_time + print "Backend: %f" % self.backend_time + print "Running asm: %f" % self.run_time + print "Blackhole: %f" % self.blackhole_time + print "TOTAL: %f" % (self.tk - self.t0) 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 May 1 14:17:38 2009 @@ -1022,6 +1022,8 @@ finally: if isinstance(self.history, history.BlackHole): self.staticdata.profiler.end_blackhole() + else: + self.staticdata.profiler.end_tracing() if not we_are_translated(): history.log.event('LEAVE' + self.history.extratext) elif DEBUG: @@ -1242,6 +1244,7 @@ *args[1:]) def initialize_state_from_start(self, *args): + self.staticdata.profiler.start_tracing() self.staticdata._recompute_class_sizes() self.create_empty_history() num_green_args = self.staticdata.num_green_args @@ -1273,7 +1276,9 @@ for i in range(extra): self.history.operations.append(suboperations[i]) self.extra_rebuild_operations = extra - if not must_compile: + if must_compile: + self.staticdata.profiler.start_tracing() + else: self.staticdata.profiler.start_blackhole() self.history = history.BlackHole(self.cpu) # the BlackHole is invalid because it doesn't start with Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py Fri May 1 14:17:38 2009 @@ -13,8 +13,8 @@ self.counter += 1 return self.counter - 1 - def print_stats(self): - pass +## def print_stats(self): +## pass class ProfilerMixin(LLJitMixin): def meta_interp(self, *args, **kwds): @@ -37,9 +37,11 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - assert len(profiler.events) == 6 + assert len(profiler.events) == 8 expected = [ TRACING, + BACKEND, + END_BACKEND, END_TRACING, RUNNING, END_RUNNING, @@ -47,6 +49,7 @@ END_BLACKHOLE ] assert [i[1] for i in profiler.events] == expected - assert profiler.trace_time == 1 + assert profiler.trace_time == 2 + assert profiler.backend_time == 1 assert profiler.run_time == 1 assert profiler.blackhole_time == 1 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 May 1 14:17:38 2009 @@ -578,10 +578,6 @@ # not too bad. def maybe_compile_and_run(self, *args): - metainterp_sd = warmrunnerdesc.metainterp_sd - if not metainterp_sd.profiler.initialized: - metainterp_sd.profiler.start() - metainterp_sd.profiler.initialized = True # get the greenargs and look for the cell corresponding to the hash greenargs = args[:num_green_args] argshash = self.getkeyhash(*greenargs) @@ -595,10 +591,12 @@ self.cells[argshash] = Counter(n) return #interp.debug_trace("jit_compile", *greenargs) + metainterp_sd = warmrunnerdesc.metainterp_sd + if not metainterp_sd.profiler.initialized: + metainterp_sd.profiler.start() + metainterp_sd.profiler.initialized = True metainterp = MetaInterp(metainterp_sd) - metainterp_sd.profiler.start_tracing() loop = metainterp.compile_and_run_once(*args) - metainterp_sd.profiler.end_tracing() else: # machine code was already compiled for these greenargs # (or we have a hash collision) @@ -644,10 +642,7 @@ return None metainterp_sd = warmrunnerdesc.metainterp_sd metainterp = MetaInterp(metainterp_sd) - warmrunnerdesc.metainterp_sd.profiler.start_tracing() - res = metainterp.compile_and_run_once(*args) - warmrunnerdesc.metainterp_sd.profiler.end_tracing() - return res + return metainterp.compile_and_run_once(*args) handle_hash_collision._dont_inline_ = True def getkeyhash(self, *greenargs): From jandem at codespeak.net Fri May 1 14:39:55 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Fri, 1 May 2009 14:39:55 +0200 (CEST) Subject: [pypy-svn] r64942 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090501123955.E4728169E30@codespeak.net> Author: jandem Date: Fri May 1 14:39:53 2009 New Revision: 64942 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: Fix ToInteger for 'undefined', and use it for String.IndexOf. 230 new tests pass. Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri May 1 14:39:53 2009 @@ -415,7 +415,7 @@ if len(args) < 2: pos = 0 else: - pos = args[1].ToInt32(ctx) + pos = args[1].ToInteger(ctx) pos = min(max(pos, 0), size) return W_IntNumber(string.find(substr, pos)) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri May 1 14:39:53 2009 @@ -78,6 +78,9 @@ def __str__(self): return "w_undefined" + def ToInteger(self, ctx): + return 0 + def ToNumber(self, ctx): return NAN From arigo at codespeak.net Fri May 1 14:56:33 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 14:56:33 +0200 (CEST) Subject: [pypy-svn] r64943 - in pypy/branch/pyjitpl5/pypy/translator: . test Message-ID: <20090501125633.47119169E1B@codespeak.net> Author: arigo Date: Fri May 1 14:56:21 2009 New Revision: 64943 Modified: pypy/branch/pyjitpl5/pypy/translator/test/test_unsimplify.py pypy/branch/pyjitpl5/pypy/translator/unsimplify.py Log: Add a helper, unsimplify.call_final_function(). Modified: pypy/branch/pyjitpl5/pypy/translator/test/test_unsimplify.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/test/test_unsimplify.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/test/test_unsimplify.py Fri May 1 14:56:21 2009 @@ -1,12 +1,15 @@ +import os from pypy.translator.translator import TranslationContext, graphof -from pypy.translator.unsimplify import split_block +from pypy.translator.unsimplify import split_block, call_final_function from pypy.rpython.llinterp import LLInterpreter from pypy.objspace.flow.model import checkgraph +from pypy.rlib.objectmodel import we_are_translated +from pypy.tool.udir import udir -def translate(func, argtypes): +def translate(func, argtypes, type_system="lltype"): t = TranslationContext() t.buildannotator().build_types(func, argtypes) - t.buildrtyper().specialize() + t.buildrtyper(type_system=type_system).specialize() return graphof(t, func), t def test_split_blocks_simple(): @@ -66,3 +69,21 @@ result = interp.eval_graph(graph, [2]) assert result == 2 +def test_call_final_function(): + tmpfile = str(udir.join('test_call_final_function')) + for type_system in ['lltype', 'ootype']: + def f(x): + return x * 6 + def goodbye_world(): + if we_are_translated(): + fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0) + os.close(fd) + graph, t = translate(f, [int], type_system) + call_final_function(t, goodbye_world) + # + if os.path.exists(tmpfile): + os.unlink(tmpfile) + interp = LLInterpreter(t.rtyper) + result = interp.eval_graph(graph, [7]) + assert result == 42 + assert os.path.isfile(tmpfile) Modified: pypy/branch/pyjitpl5/pypy/translator/unsimplify.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/unsimplify.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/unsimplify.py Fri May 1 14:56:21 2009 @@ -154,3 +154,27 @@ break if links_to_start_block: insert_empty_startblock(None, graph) + +def call_final_function(translator, final_func): + """When the program finishes normally, call 'final_func()'.""" + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.annlowlevel import MixLevelHelperAnnotator + + annhelper = MixLevelHelperAnnotator(translator.rtyper) + c_final_func = annhelper.constfunc(final_func, [], annmodel.s_None) + annhelper.finish() + + entry_point = translator.graphs[0] + v = copyvar(translator.annotator, entry_point.getreturnvar()) + extrablock = Block([v]) + v_none = varoftype(lltype.Void) + newop = SpaceOperation('direct_call', [c_final_func], v_none) + extrablock.operations = [newop] + extrablock.closeblock(Link([v], entry_point.returnblock)) + for block in entry_point.iterblocks(): + if block is not extrablock: + for link in block.exits: + if link.target is entry_point.returnblock: + link.target = extrablock + checkgraph(entry_point) From arigo at codespeak.net Fri May 1 15:01:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 15:01:58 +0200 (CEST) Subject: [pypy-svn] r64944 - in pypy/branch/pyjitpl5/pypy: jit/metainterp translator Message-ID: <20090501130158.F13A7168415@codespeak.net> Author: arigo Date: Fri May 1 15:01:48 2009 New Revision: 64944 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py pypy/branch/pyjitpl5/pypy/translator/unsimplify.py Log: Use call_final_function() in the jit. 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 May 1 15:01:48 2009 @@ -15,6 +15,7 @@ from pypy.rlib.debug import debug_print from pypy.rpython.lltypesystem.lloperation import llop from pypy.translator.simplify import get_funcobj, get_functype +from pypy.translator.unsimplify import call_final_function from pypy.jit.metainterp import support, history, pyjitpl from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp @@ -124,7 +125,7 @@ self.metainterp_sd.generate_bytecode(policy, self.ts) self.make_enter_function() self.rewrite_can_enter_jit() - #self.rewrite_entry_point() XXX broken when the last block handles exceptions + self.add_profiler_finish() self.metainterp_sd.num_green_args = self.num_green_args self.metainterp_sd.state = self.state @@ -441,24 +442,14 @@ origblock.recloseblock(Link([v_result], origportalgraph.returnblock)) checkgraph(origportalgraph) - def rewrite_entry_point(self): + def add_profiler_finish(self): def finish_profiler(): - self.metainterp_sd.profiler.finish() + if self.metainterp_sd.profiler.initialized: + self.metainterp_sd.profiler.finish() if self.cpu.translate_support_code: - entry_point = self.translator.graphs[0] - _, TP = self.metainterp_sd.ts.get_FuncType([], lltype.Void) - profiler_ptr = self.helper_func(TP, finish_profiler) - for block in entry_point.iterblocks(): - for link in block.exits: - if link.target is entry_point.returnblock: - v = Variable() - v.concretetype = lltype.Void - newop = SpaceOperation('direct_call', - [Constant(profiler_ptr, TP)], - v) - block.operations.append(newop) - checkgraph(entry_point) + call_final_function(self.translator, finish_profiler, + annhelper = self.annhelper) def decode_hp_hint_args(op): # Returns (list-of-green-vars, list-of-red-vars) without Voids. Modified: pypy/branch/pyjitpl5/pypy/translator/unsimplify.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/unsimplify.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/unsimplify.py Fri May 1 15:01:48 2009 @@ -155,15 +155,18 @@ if links_to_start_block: insert_empty_startblock(None, graph) -def call_final_function(translator, final_func): +def call_final_function(translator, final_func, annhelper=None): """When the program finishes normally, call 'final_func()'.""" from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype from pypy.rpython.annlowlevel import MixLevelHelperAnnotator - annhelper = MixLevelHelperAnnotator(translator.rtyper) + own_annhelper = (annhelper is None) + if own_annhelper: + annhelper = MixLevelHelperAnnotator(translator.rtyper) c_final_func = annhelper.constfunc(final_func, [], annmodel.s_None) - annhelper.finish() + if own_annhelper: + annhelper.finish() entry_point = translator.graphs[0] v = copyvar(translator.annotator, entry_point.getreturnvar()) From arigo at codespeak.net Fri May 1 17:05:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 17:05:44 +0200 (CEST) Subject: [pypy-svn] r64945 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090501150544.F19DC1684E4@codespeak.net> Author: arigo Date: Fri May 1 17:05:43 2009 New Revision: 64945 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py Log: Improve jitprof to not build list potentially very long list in memory. It can cause random tweaks to the runtimes. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Fri May 1 17:05:43 2009 @@ -8,12 +8,6 @@ BACKEND = 1 RUNNING = 2 BLACKHOLE = 3 -LAST_START = 3 - -END_TRACING = 4 -END_BACKEND = 5 -END_RUNNING = 6 -END_BLACKHOLE = 7 class EmptyProfiler(object): initialized = True @@ -50,61 +44,54 @@ class Profiler(object): initialized = False - timer = time.clock + timer = time.time def start(self): - self.t0 = self.timer() - self.events = [] + self.starttime = self.timer() + self.t1 = self.starttime + self.times = [0, 0, 0, 0] + self.current = [] def finish(self): self.tk = self.timer() - self.summarize() self.print_stats() - def start_tracing(self): - self.events.append((self.timer(), TRACING)) - - def end_tracing(self): - self.events.append((self.timer(), END_TRACING)) - - def start_backend(self): - self.events.append((self.timer(), BACKEND)) - - def end_backend(self): - self.events.append((self.timer(), END_BACKEND)) + def _start(self, event): + t0 = self.t1 + self.t1 = self.timer() + if self.current: + self.times[self.current[-1]] += self.t1 - t0 + self.current.append(event) + + def _end(self, event): + t0 = self.t1 + self.t1 = self.timer() + if not self.current: + raise BrokenProfilerData + ev1 = self.current.pop() + if ev1 != event: + raise BrokenProfilerData + self.times[ev1] += self.t1 - t0 + + def start_tracing(self): self._start(TRACING) + def end_tracing(self): self._end (TRACING) - def start_running(self): - self.events.append((self.timer(), RUNNING)) + def start_backend(self): self._start(BACKEND) + def end_backend(self): self._end (BACKEND) - def end_running(self): - self.events.append((self.timer(), END_RUNNING)) + def start_running(self): self._start(RUNNING) + def end_running(self): self._end (RUNNING) - def start_blackhole(self): - self.events.append((self.timer(), BLACKHOLE)) + def start_blackhole(self): self._start(BLACKHOLE) + def end_blackhole(self): self._end (BLACKHOLE) - def end_blackhole(self): - self.events.append((self.timer(), END_BLACKHOLE)) + def print_stats(self): + print "Tracing: %f" % self.times[TRACING] + print "Backend: %f" % self.times[BACKEND] + print "Running asm: %f" % self.times[RUNNING] + print "Blackhole: %f" % self.times[BLACKHOLE] + print "TOTAL: %f" % (self.tk - self.starttime) - def summarize(self): - current = [] - t = 0 - times = [0, 0, 0, 0] - for t0, ev in self.events: - if ev <= LAST_START: - if current: - times[current[-1]] += t0 - t - current.append(ev) - else: - times[current.pop()] += t0 - t - t = t0 - self.trace_time = times[TRACING] - self.backend_time = times[BACKEND] - self.run_time = times[RUNNING] - self.blackhole_time = times[BLACKHOLE] - def print_stats(self): - print "Tracing: %f" % self.trace_time - print "Backend: %f" % self.backend_time - print "Running asm: %f" % self.run_time - print "Blackhole: %f" % self.blackhole_time - print "TOTAL: %f" % (self.tk - self.t0) +class BrokenProfilerData(Exception): + pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_jitprof.py Fri May 1 17:05:43 2009 @@ -7,14 +7,20 @@ class FakeProfiler(Profiler): def __init__(self): - self.counter = 0 + self.counter = 123456 + self.events = [] def timer(self): self.counter += 1 return self.counter - 1 -## def print_stats(self): -## pass + def _start(self, event): + Profiler._start(self, event) + self.events.append(event) + + def _end(self, event): + Profiler._end(self, event) + self.events.append(~event) class ProfilerMixin(LLJitMixin): def meta_interp(self, *args, **kwds): @@ -37,19 +43,15 @@ res = self.meta_interp(f, [6, 7]) assert res == 84 profiler = pyjitpl._warmrunnerdesc.metainterp_sd.profiler - assert len(profiler.events) == 8 expected = [ TRACING, BACKEND, - END_BACKEND, - END_TRACING, + ~ BACKEND, + ~ TRACING, RUNNING, - END_RUNNING, + ~ RUNNING, BLACKHOLE, - END_BLACKHOLE + ~ BLACKHOLE ] - assert [i[1] for i in profiler.events] == expected - assert profiler.trace_time == 2 - assert profiler.backend_time == 1 - assert profiler.run_time == 1 - assert profiler.blackhole_time == 1 + assert profiler.events == expected + assert profiler.times == [2, 1, 1, 1] From arigo at codespeak.net Fri May 1 17:29:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 17:29:03 +0200 (CEST) Subject: [pypy-svn] r64946 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090501152903.CCC7C16856D@codespeak.net> Author: arigo Date: Fri May 1 17:29:02 2009 New Revision: 64946 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Log: Print also the number of times we called start_xxx(), to get an idea. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/jitprof.py Fri May 1 17:29:02 2009 @@ -50,6 +50,7 @@ self.starttime = self.timer() self.t1 = self.starttime self.times = [0, 0, 0, 0] + self.counters = [0, 0, 0, 0] self.current = [] def finish(self): @@ -61,6 +62,7 @@ self.t1 = self.timer() if self.current: self.times[self.current[-1]] += self.t1 - t0 + self.counters[event] += 1 self.current.append(event) def _end(self, event): @@ -86,11 +88,13 @@ def end_blackhole(self): self._end (BLACKHOLE) def print_stats(self): - print "Tracing: %f" % self.times[TRACING] - print "Backend: %f" % self.times[BACKEND] - print "Running asm: %f" % self.times[RUNNING] - print "Blackhole: %f" % self.times[BLACKHOLE] - print "TOTAL: %f" % (self.tk - self.starttime) + cnt = self.counters + tim = self.times + print "Tracing: \t%d\t%f" % (cnt[TRACING], tim[TRACING]) + print "Backend: \t%d\t%f" % (cnt[BACKEND], tim[BACKEND]) + print "Running asm:\t%d\t%f" % (cnt[RUNNING], tim[RUNNING]) + print "Blackhole: \t%d\t%f" % (cnt[BLACKHOLE], tim[BLACKHOLE]) + print "TOTAL: \t\t%f" % (self.tk - self.starttime) class BrokenProfilerData(Exception): From fijal at codespeak.net Fri May 1 17:46:50 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 17:46:50 +0200 (CEST) Subject: [pypy-svn] r64947 - pypy/branch/pyjitpl5/lib-python Message-ID: <20090501154650.8C1C4168574@codespeak.net> Author: fijal Date: Fri May 1 17:46:49 2009 New Revision: 64947 Added: pypy/branch/pyjitpl5/lib-python/conftest.py - copied unchanged from r64643, pypy/trunk/lib-python/conftest.py Log: Replace conftest with one from pypy-trunk From fijal at codespeak.net Fri May 1 17:49:13 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 17:49:13 +0200 (CEST) Subject: [pypy-svn] r64948 - pypy/build/bot2/pypybuildbot Message-ID: <20090501154913.B6E07169E17@codespeak.net> Author: fijal Date: Fri May 1 17:49:09 2009 New Revision: 64948 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Revert a checkin that tried to run tests from within pypy dir Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Fri May 1 17:49:09 2009 @@ -204,8 +204,7 @@ self.addStep(ShellCmd( description="lib-python test", - command=["python", "test_all.py", - "--pypy=translator/goal/pypy-c", - "--resultlog=../cpython.log", "../lib-python"], - workdir="pypy", + command=["python", "pypy/test_all.py", + "--pypy=pypy/translator/goal/pypy-c", + "--resultlog=cpython.log", "lib-python"], logfiles={'pytestLog': 'cpython.log'})) From antocuni at codespeak.net Fri May 1 19:03:47 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:03:47 +0200 (CEST) Subject: [pypy-svn] r64949 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal Message-ID: <20090501170347.6CDAE169EB9@codespeak.net> Author: antocuni Date: Fri May 1 19:03:45 2009 New Revision: 64949 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Log: oops, I forgot to check this in. This means that most of the previous check-ins "test x and y passes" are broken :-(. Sorry Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Fri May 1 19:03:45 2009 @@ -3,8 +3,8 @@ from pypy.rlib.debug import ll_assert, debug_print from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rstr, rclass from pypy.rpython.ootypesystem import ootype -from pypy.jit.metainterp.history import AbstractDescr, Box, BoxInt, BoxPtr -from pypy.jit.metainterp.history import BoxObj +from pypy.jit.metainterp.history import AbstractDescr, AbstractMethDescr +from pypy.jit.metainterp.history import Box, BoxInt, BoxPtr, BoxObj from pypy.jit.metainterp import executor from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model @@ -166,12 +166,7 @@ if value: raise GuardFailed elif opnum == rop.GUARD_CLASS: - assert not self.is_oo - value = argboxes[0].getptr(rclass.OBJECTPTR) - adr = argboxes[1].getaddr(self) - expected_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) - if value.typeptr != expected_class: - raise GuardFailed + self._execute_guard_class(argboxes) elif opnum == rop.GUARD_VALUE: value = argboxes[0].getint() expected_value = argboxes[1].getint() @@ -364,6 +359,13 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr return cast_instance_to_base_ptr(e) + def _execute_guard_class(self, argboxes): + value = argboxes[0].getptr(rclass.OBJECTPTR) + adr = argboxes[1].getaddr(self) + expected_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) + if value.typeptr != expected_class: + raise GuardFailed + def _execute_guard_exception(self, argboxes): adr = argboxes[0].getaddr(self) expected_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE) @@ -530,6 +532,13 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_obj return ootype.cast_to_object(cast_instance_to_base_obj(e)) + def _execute_guard_class(self, argboxes): + # XXX: what if we try to cast a List to ROOT? + value = ootype.cast_from_object(ootype.ROOT, argboxes[0].getobj()) + expected_class = ootype.cast_from_object(ootype.Class, argboxes[1].getobj()) + if ootype.classof(value) != expected_class: + raise GuardFailed + def _execute_guard_exception(self, argboxes): obj = argboxes[0].getobj() expected_class = ootype.cast_from_object(ootype.Class, obj) @@ -621,7 +630,6 @@ self.errbox = errbox - # ____________________________________________________________ @@ -670,7 +678,7 @@ if isinstance(TYPE, ootype.OOType): return ootype.cast_from_object(TYPE, box.getobj()) else: - return lltype.cast_to_primitive(TYPE, box.getint()) + return lltype.cast_primitive(TYPE, box.getint()) base_dict = { 'ootype': ootype, From antocuni at codespeak.net Fri May 1 19:15:26 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:15:26 +0200 (CEST) Subject: [pypy-svn] r64950 - in pypy/branch/pyjitpl5/pypy: annotation rpython/ootypesystem rpython/ootypesystem/test Message-ID: <20090501171526.9EADC169EC2@codespeak.net> Author: antocuni Date: Fri May 1 19:15:18 2009 New Revision: 64950 Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Log: implement call_args for oo low level bound methods Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/unaryop.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/unaryop.py Fri May 1 19:15:18 2009 @@ -779,6 +779,18 @@ METH = ootype.typeOf(meth) return lltype_to_annotation(METH.RESULT) + def call(m, args): + args_s, kwds_s = args.unpack() + if kwds_s: + raise Exception("keyword arguments to call to a low-level bound method") + info = 'argument to ll bound method call' + llargs = [annotation_to_lltype(s_arg,info)._defl() for s_arg in args_s] + inst = m.ootype._example() + meth = getattr(inst, m.name) + v = meth(*llargs) + return ll_to_annotation(v) + + class __extend__(SomeOOStaticMeth): def call(m, args): Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rootype.py Fri May 1 19:15:18 2009 @@ -145,6 +145,13 @@ return hop.genop("oosend", [cname]+vlist, resulttype = hop.r_result.lowleveltype) + def rtype_call_args(self, hop): + from pypy.rpython.rbuiltin import call_args_expand + hop, _ = call_args_expand(hop, takes_kwds=False) + hop.swap_fst_snd_args() + hop.r_s_popfirstarg() + return self.rtype_simple_call(hop) + class OOStaticMethRepr(Repr): def __init__(self, METHODTYPE): Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Fri May 1 19:15:18 2009 @@ -421,3 +421,21 @@ res = interpret(fn, [1], type_system='ootype') assert res + + +def test_boundmeth_callargs(): + A = Instance("A", ROOT, {'a': (Signed, 3)}) + M = Meth([Signed, Signed], Signed) + def m_(self, x, y): + return self.a + x + y + m = meth(M, _name="m", _callable=m_) + addMethods(A, {"m": m}) + + def fn(x, y): + a = ootype.new(A) + meth = a.m + args = (x, y) + return meth(*args) + + res = interpret(fn, [4, 5], type_system='ootype') + assert res == 3+4+5 From arigo at codespeak.net Fri May 1 19:18:50 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 May 2009 19:18:50 +0200 (CEST) Subject: [pypy-svn] r64951 - pypy/build/bot2/pypybuildbot Message-ID: <20090501171850.9C84A168509@codespeak.net> Author: arigo Date: Fri May 1 19:18:49 2009 New Revision: 64951 Modified: pypy/build/bot2/pypybuildbot/summary.py Log: Force "failure" to be computed and shown. This is a temporary fix to avoid hiding a real failure. Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 19:18:49 2009 @@ -132,8 +132,8 @@ ts = step.getTimes() if ts[0] is not None and ts[1] is not None: pytest_elapsed += ts[1]-ts[0] - elif (failure is None and - step.getResults()[0] in (FAILURE, EXCEPTION)): + if (failure is None and + step.getResults()[0] in (FAILURE, EXCEPTION)): failure = ' '.join(step.getText()) run_info = {'URL': run_url, 'elapsed': pytest_elapsed or None, @@ -148,12 +148,12 @@ outcome_set.populate_one(stepName+' aborted', '!', "") outcome_set.populate(resultLog) - if not someresult: + if not someresult or failure is not None: if failure: name = '"%s"' % failure # quote else: name = '' - outcome_set.populate_one(name, '!', "no logs from the test run") + outcome_set.populate_one(name, '!') return outcome_set From antocuni at codespeak.net Fri May 1 19:30:48 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:30:48 +0200 (CEST) Subject: [pypy-svn] r64952 - in pypy/branch/pyjitpl5/pypy: annotation rpython/ootypesystem/test Message-ID: <20090501173048.0701C169EC2@codespeak.net> Author: antocuni Date: Fri May 1 19:30:46 2009 New Revision: 64952 Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Log: bah, you cannot really call the method with the default value of the parameters, else it might triggers errors (like an AssertionError inside ootype._string.ll_stritem_nonneg). Instead, just trust the value of METH.RESULT Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/unaryop.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/unaryop.py Fri May 1 19:30:46 2009 @@ -786,9 +786,9 @@ info = 'argument to ll bound method call' llargs = [annotation_to_lltype(s_arg,info)._defl() for s_arg in args_s] inst = m.ootype._example() - meth = getattr(inst, m.name) - v = meth(*llargs) - return ll_to_annotation(v) + _, meth = ootype.typeOf(inst)._lookup(m.name) + METH = ootype.typeOf(meth) + return lltype_to_annotation(METH.RESULT) class __extend__(SomeOOStaticMeth): Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Fri May 1 19:30:46 2009 @@ -439,3 +439,13 @@ res = interpret(fn, [4, 5], type_system='ootype') assert res == 3+4+5 + +def test_boundmeth_callargs_stritem_nonneg(): + def fn(i): + s = ootype.oostring(42, -1) + meth = s.ll_stritem_nonneg + args = (i,) + return meth(*args) + + res = interpret(fn, [0], type_system='ootype') + assert res == '4' From antocuni at codespeak.net Fri May 1 19:36:57 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:36:57 +0200 (CEST) Subject: [pypy-svn] r64953 - pypy/branch/pyjitpl5/pypy/annotation Message-ID: <20090501173657.6A395169E9F@codespeak.net> Author: antocuni Date: Fri May 1 19:36:56 2009 New Revision: 64953 Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py Log: (arigo) kill two useless lines Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/unaryop.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/unaryop.py Fri May 1 19:36:56 2009 @@ -783,8 +783,6 @@ args_s, kwds_s = args.unpack() if kwds_s: raise Exception("keyword arguments to call to a low-level bound method") - info = 'argument to ll bound method call' - llargs = [annotation_to_lltype(s_arg,info)._defl() for s_arg in args_s] inst = m.ootype._example() _, meth = ootype.typeOf(inst)._lookup(m.name) METH = ootype.typeOf(meth) From antocuni at codespeak.net Fri May 1 19:38:41 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:38:41 +0200 (CEST) Subject: [pypy-svn] r64954 - pypy/branch/pyjitpl5/pypy/annotation Message-ID: <20090501173841.E089C169E9F@codespeak.net> Author: antocuni Date: Fri May 1 19:38:40 2009 New Revision: 64954 Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py Log: (arigo) kill one more unused line Modified: pypy/branch/pyjitpl5/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/unaryop.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/unaryop.py Fri May 1 19:38:40 2009 @@ -771,7 +771,6 @@ class __extend__(SomeOOBoundMeth): def simple_call(m, *args_s): - inst = m.ootype._example() _, meth = m.ootype._lookup(m.name) if isinstance(meth, ootype._overloaded_meth): return meth._resolver.annotate(args_s) From antocuni at codespeak.net Fri May 1 19:40:15 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:40:15 +0200 (CEST) Subject: [pypy-svn] r64955 - in pypy/branch/pyjitpl5/pypy/jit/backend/minimal: . test Message-ID: <20090501174015.15EB6169EB7@codespeak.net> Author: antocuni Date: Fri May 1 19:40:15 2009 New Revision: 64955 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Log: impressive, test_tiny1 passes with a minimal fix: we need to use our own copy of MethDescr because the llgraph one calls maybe_on_top_of_llinterp, and it's hard to convince the annotator to ignore it Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Fri May 1 19:40:15 2009 @@ -629,6 +629,26 @@ self.call = call self.errbox = errbox +class MethDescr(AbstractMethDescr): + callmeth = None + def __init__(self, SELFTYPE, methname): + from pypy.jit.backend.llgraph.runner import boxresult, make_getargs + _, meth = SELFTYPE._lookup(methname) + METH = ootype.typeOf(meth) + self.SELFTYPE = SELFTYPE + self.METH = METH + self.methname = methname + RESULT = METH.RESULT + getargs = make_getargs(METH.ARGS) + def callmeth(selfbox, argboxes): + selfobj = ootype.cast_from_object(SELFTYPE, selfbox.getobj()) + meth = getattr(selfobj, methname) + methargs = getargs(argboxes) + res = meth(*methargs) + if RESULT is not ootype.Void: + return boxresult(RESULT, res) + self.callmeth = callmeth + # ____________________________________________________________ @@ -692,6 +712,7 @@ 'rffi': rffi, 'BoxInt': BoxInt, 'BoxPtr': BoxPtr, + 'BoxObj': BoxObj, } class GuardFailed(Exception): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Fri May 1 19:40:15 2009 @@ -1,8 +1,19 @@ import py from pypy.jit.metainterp.test.test_tl import ToyLanguageTests -from pypy.jit.backend.minimal.test.test_zrpy_exception import LLTranslatedJitMixin +from pypy.jit.backend.minimal.test.test_zrpy_exception import LLTranslatedJitMixin, OOTranslatedJitMixin -class TestTL(LLTranslatedJitMixin, ToyLanguageTests): +class TestOOtype(OOTranslatedJitMixin, ToyLanguageTests): + + def skip(self): + py.test.skip('in-progress') + + test_tlr = skip + test_tl_base = skip + test_tl_2 = skip + test_tl_call = skip + + +class TestLLtype(LLTranslatedJitMixin, ToyLanguageTests): # for the individual tests see # ====> ../../../metainterp/test/test_tl.py pass From antocuni at codespeak.net Fri May 1 19:50:19 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 1 May 2009 19:50:19 +0200 (CEST) Subject: [pypy-svn] r64956 - in pypy/branch/pyjitpl5/pypy/jit/backend/minimal: . test Message-ID: <20090501175019.A5230169EB7@codespeak.net> Author: antocuni Date: Fri May 1 19:50:17 2009 New Revision: 64956 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Log: implement set_future_value_obj, and test_tlr passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Fri May 1 19:50:17 2009 @@ -144,6 +144,11 @@ assert len(self._future_values) == index self._future_values.append(BoxPtr(ptrvalue)) + def set_future_value_obj(self, index, objvalue): + del self._future_values[index:] + assert len(self._future_values) == index + self._future_values.append(BoxObj(objvalue)) + def get_latest_value_int(self, index): op, env = self.latest_fail return env[op.args[index]].getint() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Fri May 1 19:50:17 2009 @@ -7,7 +7,6 @@ def skip(self): py.test.skip('in-progress') - test_tlr = skip test_tl_base = skip test_tl_2 = skip test_tl_call = skip From fijal at codespeak.net Fri May 1 21:55:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 21:55:43 +0200 (CEST) Subject: [pypy-svn] r64957 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090501195543.CF49E169DB6@codespeak.net> Author: fijal Date: Fri May 1 21:55:31 2009 New Revision: 64957 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: I think this assert was here before. I'm not sure though, assert that op is actually the same as expected Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Fri May 1 21:55:31 2009 @@ -335,6 +335,8 @@ cpu.set_future_value_int(i, v.value) op = cpu.execute_operations(loop) assert op.args == endvars + if builder.should_fail_by is not None: + assert op is builder.should_fail_by for i, v in enumerate(endvars): value = cpu.get_latest_value_int(i) From fijal at codespeak.net Fri May 1 22:42:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 22:42:33 +0200 (CEST) Subject: [pypy-svn] r64958 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090501204233.8C63B169EEB@codespeak.net> Author: fijal Date: Fri May 1 22:42:31 2009 New Revision: 64958 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Some support for bridges in test_random. If the bridge failed, compile more assembler for it and run again Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Fri May 1 22:42:31 2009 @@ -5,7 +5,11 @@ from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstAddr from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute +from pypy.jit.metainterp.resoperation import opname +class DummyLoop(object): + def __init__(self, subops): + self.operations = subops class OperationBuilder: def __init__(self, cpu, loop, vars): @@ -40,15 +44,51 @@ v = self.do(rop.INT_IS_TRUE, [v]) return v - def print_loop_prebuilt(self, names, writevar, s): - pass + def process_operation(self, s, op, names, subops): + args = [] + for v in op.args: + if v in names: + args.append(names[v]) + elif isinstance(v, ConstAddr): + name = ''.join([v.value.ptr.name[i] + for i in range(len(v.value.ptr.name)-1)]) + args.append( + 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' + % name) + else: + args.append('ConstInt(%d)' % v.value) + if op.descr is None: + descrstr = '' + else: + descrstr = ', ' + op.descr._random_info + print >>s, ' ResOperation(rop.%s, [%s], %s%s),' % ( + opname[op.opnum], ', '.join(args), names[op.result], descrstr) + if getattr(op, 'suboperations', None) is not None: + subops.append(op) def print_loop(self): + def update_names(ops): + for op in ops: + v = op.result + if v not in names: + writevar(v, 'tmp') + if getattr(op, 'suboperations', None) is not None: + update_names(op.suboperations) + + def print_loop_prebuilt(ops): + for op in ops: + for arg in op.args: + if isinstance(arg, ConstPtr): + writevar(arg, 'const_ptr') + if getattr(op, 'suboperations', None) is not None: + print_loop_prebuilt(op.suboperations) + if demo_conftest.option.output: s = open(demo_conftest.option.output, "w") else: s = sys.stdout names = {None: 'None'} + subops = [] # def writevar(v, nameprefix, init=''): names[v] = '%s%d' % (nameprefix, len(names)) @@ -59,46 +99,29 @@ writevar(v, 'v') for v, S in self.ptrvars: writevar(v, 'p') - for op in self.loop.operations: - v = op.result - if v not in names: - writevar(v, 'tmp') - # - self.print_loop_prebuilt(names, writevar, s) + update_names(self.loop.operations) + print_loop_prebuilt(self.loop.operations) # print >>s, ' cpu = CPU(None, None)' print >>s, " loop = TreeLoop('test')" print >>s, ' loop.inputargs = [%s]' % ( ', '.join([names[v] for v in self.loop.inputargs])) - from pypy.jit.metainterp.resoperation import opname print >>s, ' loop.operations = [' for op in self.loop.operations: - args = [] - for v in op.args: - if v in names: - args.append(names[v]) - elif isinstance(v, ConstAddr): - name = ''.join([v.value.ptr.name[i] - for i in range(len(v.value.ptr.name)-1)]) - args.append( - 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' - % name) - else: - args.append('ConstInt(%d)' % v.value) - if op.descr is None: - descrstr = '' - else: - descrstr = ', ' + op.descr._random_info - print >>s, ' ResOperation(rop.%s, [%s], %s%s),' % ( - opname[op.opnum], ', '.join(args), names[op.result], descrstr) + self.process_operation(s, op, names, subops) print >>s, ' ]' - for i, op in enumerate(self.loop.operations): - if getattr(op, 'suboperations', None) is not None: - [op] = op.suboperations - assert op.opnum == rop.FAIL - print >>s, ' loop.operations[%d].suboperations = [' % i - print >>s, ' ResOperation(rop.FAIL, [%s], None)]' % ( - ', '.join([names[v] for v in op.args])) + while subops: + next = subops.pop(0) + for op in next.suboperations: + self.process_operation(s, op, names, subops) + # XXX think what to do about the one below + #if len(op.suboperations) > 1: + # continue # XXX + #[op] = op.suboperations + #assert op.opnum == rop.FAIL + #print >>s, ' loop.operations[%d].suboperations = [' % i + #print >>s, ' ResOperation(rop.FAIL, [%s], None)]' % ( + # ', '.join([names[v] for v in op.args])) print >>s, ' cpu.compile_operations(loop)' for i, v in enumerate(self.loop.inputargs): print >>s, ' cpu.set_future_value_int(%d, %d)' % (i, v.value) @@ -275,8 +298,8 @@ from pypy.jit.backend.llgraph.runner import LLtypeCPU return LLtypeCPU(None) elif demo_conftest.option.backend == 'minimal': - from pypy.jit.backend.minimal.runner import CPU - return CPU(None) + from pypy.jit.backend.minimal.runner import LLtypeCPU + return LLtypeCPU(None, None) elif demo_conftest.option.backend == 'x86': from pypy.jit.backend.x86.runner import CPU386 return CPU386(None, None) @@ -285,6 +308,16 @@ # ____________________________________________________________ +def generate_ops(builder, block_length, r): + for i in range(block_length): + try: + r.choice(builder.OPERATIONS).produce_into(builder, r) + except CannotProduceOperation: + pass + if builder.should_fail_by is not None: + break + + def check_random_function(BuilderClass, r): block_length = demo_conftest.option.block_length vars = [BoxInt(r.random_integer()) @@ -297,14 +330,7 @@ loop.operations = [] builder = BuilderClass(cpu, loop, vars) - - for i in range(block_length): - try: - r.choice(BuilderClass.OPERATIONS).produce_into(builder, r) - except CannotProduceOperation: - pass - if builder.should_fail_by is not None: - break + generate_ops(builder, block_length, r) endvars = [] used_later = {} @@ -316,39 +342,68 @@ endvars.append(v) r.shuffle(endvars) loop.operations.append(ResOperation(rop.FAIL, endvars, None)) - builder.print_loop() - - cpu.compile_operations(loop) - - if builder.should_fail_by is not None: - endvars = builder.should_fail_by.args - expected = {} - for v in endvars: - expected[v] = v.value - - for v, S, fields in builder.prebuilt_ptr_consts: - container = v.value._obj.container - for name, value in fields.items(): - setattr(container, name, value) - - for i, v in enumerate(valueboxes): - cpu.set_future_value_int(i, v.value) - op = cpu.execute_operations(loop) - assert op.args == endvars - if builder.should_fail_by is not None: - assert op is builder.should_fail_by - - for i, v in enumerate(endvars): - value = cpu.get_latest_value_int(i) - assert value == expected[v], ( - "Got %d, expected %d, in the variable %s" % (value, - expected[v], - builder.names[v]) - ) + should_fail_by = builder.should_fail_by + if should_fail_by is not None: + guard_op = loop.operations[builder.should_fail_by_num] + all_builders = [builder] + + while True: + builder.print_loop() + cpu.compile_operations(loop) + + if should_fail_by is not None: + endvars = should_fail_by.args + expected = {} + for v in endvars: + expected[v] = v.value + + for b in all_builders: + for v, S, fields in b.prebuilt_ptr_consts: + container = v.value._obj.container + for name, value in fields.items(): + setattr(container, name, value) + + for i, v in enumerate(valueboxes): + cpu.set_future_value_int(i, v.value) + op = cpu.execute_operations(loop) + assert op.args == endvars + if should_fail_by is not None: + assert op is should_fail_by + + for i, v in enumerate(endvars): + value = cpu.get_latest_value_int(i) + assert value == expected[v], ( + "Got %d, expected %d, in the variable %s" % (value, + expected[v], + builder.names[v]) + ) + if should_fail_by is None or guard_op is None: + break + # build a bridge and repeat + guard_op.suboperations = [] + subloop = DummyLoop(guard_op.suboperations) + if not op.args: + break + bridge_builder = BuilderClass(cpu, subloop, op.args[:]) + generate_ops(bridge_builder, block_length, r) + k = r.random() + subset = [] + num = int(k * len(bridge_builder.intvars)) + for i in range(num): + subset.append(r.choice(bridge_builder.intvars)) + r.shuffle(subset) + fail_op = ResOperation(rop.FAIL, subset, None) + guard_op.suboperations.append(fail_op) + all_builders.append(bridge_builder) + if bridge_builder.should_fail_by is None: + should_fail_by = fail_op + guard_op = None + else: + should_fail_by = bridge_builder.should_fail_by + guard_op = guard_op.suboperations[bridge_builder.should_fail_by_num] print ' # passed.' - print - + print def test_random_function(BuilderClass=OperationBuilder): r = Random() From fijal at codespeak.net Fri May 1 22:56:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 22:56:49 +0200 (CEST) Subject: [pypy-svn] r64959 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090501205649.DC1E416854B@codespeak.net> Author: fijal Date: Fri May 1 22:56:43 2009 New Revision: 64959 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Fix an obscure corner case. We don't guarantee that over transition to guard also stack positions which are not explicit in inputargs will be preserved 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 May 1 22:56:43 2009 @@ -79,9 +79,12 @@ if arg in regalloc.stack_bindings: self.stack_bindings[arg] = regalloc.stack_bindings[arg] else: - assert arg in self.reg_bindings + assert arg in regalloc.reg_bindings if arg in regalloc.dirty_stack: self.dirty_stack[arg] = regalloc.dirty_stack[arg] + if (arg in regalloc.stack_bindings and + arg in regalloc.reg_bindings): + self.dirty_stack[arg] = True allocated_regs = self.reg_bindings.values() self.free_regs = [v for v in REGS if v not in allocated_regs] self.current_stack_depth = regalloc.current_stack_depth From fijal at codespeak.net Fri May 1 23:15:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 23:15:23 +0200 (CEST) Subject: [pypy-svn] r64960 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090501211523.9E816168575@codespeak.net> Author: fijal Date: Fri May 1 23:15:22 2009 New Revision: 64960 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: fix a rare crash in lshift_ovf 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 May 1 23:15:22 2009 @@ -774,7 +774,7 @@ loc2 = self.make_sure_var_in_reg(op.args[1], [], ecx) loc1 = self.force_result_in_reg(op.result, op.args[0], op.args) tmpvar = TempBox() - tmploc = self.force_allocate_reg(tmpvar, []) + tmploc = self.force_allocate_reg(tmpvar, [op.args[1], op.result]) self.eventually_free_vars(op.args) self.position += 1 regalloc = self.regalloc_for_guard(guard_op) From pedronis at codespeak.net Fri May 1 23:42:28 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 23:42:28 +0200 (CEST) Subject: [pypy-svn] r64961 - pypy/build/bot2/pypybuildbot/test Message-ID: <20090501214228.18F7E169E7C@codespeak.net> Author: pedronis Date: Fri May 1 23:42:28 2009 New Revision: 64961 Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py Log: tests about the new code/cases Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Fri May 1 23:42:28 2009 @@ -336,6 +336,9 @@ def readlines(self): return [l+'\n' for l in self.cont.splitlines()] + def isFinished(self): + return True + def add_builds(builder, builds): n = getattr(builder, 'nextBuildNumber', 0) t = 1000 @@ -589,9 +592,12 @@ build.setProperty('got_revision', '70000', None) step = build.addStepWithName('pytest') step.logs.extend([FakeLog(step, 'pytestLog', "F TEST1")]) + step.setText(["pytest", "failed"]) + step.stepFinished(summary.FAILURE) step2 = build.addStepWithName('pytest2') step2.logs.extend([FakeLog(step, 'pytestLog', ". x\nF TEST2")]) step2.setText(["pytest2", "aborted"]) + step2.stepFinished(summary.EXCEPTION) build.buildFinished() builder.addBuildToCache(build) builder.nextBuildNumber = 1 @@ -602,9 +608,29 @@ assert 'TEST1' in out assert 'TEST2' in out - assert 'pytest aborted' not in out + assert 'pytest aborted' not in out + #assert 'pytest failed' not in out assert 'pytest2 aborted' in out + def test_subtle_failures(self): + builder = status_builder.BuilderStatus('builder1') + build = status_builder.BuildStatus(builder, 0) + build.setProperty('got_revision', '70000', None) + step = build.addStepWithName('pytest') + step.logs.extend([FakeLog(step, 'pytestLog', ". TEST1")]) + step.setText(["pytest", "failed slave lost"]) + step.stepFinished(summary.FAILURE) + build.buildFinished() + builder.addBuildToCache(build) + builder.nextBuildNumber = 1 + + s = summary.Summary() + req = FakeRequest([builder]) + out = s.body(req) + + assert 'pytest failed slave lost' in out + + def test_category_sorting_key(self): s = summary.Summary(['foo', 'bar']) From fijal at codespeak.net Fri May 1 23:47:37 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 May 2009 23:47:37 +0200 (CEST) Subject: [pypy-svn] r64962 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090501214737.ED77F16854B@codespeak.net> Author: fijal Date: Fri May 1 23:47:37 2009 New Revision: 64962 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: make test_random jump to some previously generated loop from time to time Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Fri May 1 23:47:37 2009 @@ -7,6 +7,8 @@ from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.resoperation import opname +allloops = [] + class DummyLoop(object): def __init__(self, subops): self.operations = subops @@ -346,6 +348,7 @@ if should_fail_by is not None: guard_op = loop.operations[builder.should_fail_by_num] all_builders = [builder] + dont_check_result = False while True: builder.print_loop() @@ -366,6 +369,9 @@ for i, v in enumerate(valueboxes): cpu.set_future_value_int(i, v.value) op = cpu.execute_operations(loop) + + if dont_check_result: + break assert op.args == endvars if should_fail_by is not None: assert op is should_fail_by @@ -392,6 +398,14 @@ for i in range(num): subset.append(r.choice(bridge_builder.intvars)) r.shuffle(subset) + if r.random() < 0.1 and allloops: + jump_target = r.choice(allloops) + args = op.args[:len(jump_target.inputargs)] + while len(args) < len(jump_target.inputargs): + args.append(args[-1]) + fail_op = ResOperation(rop.JUMP, args, None) + fail_op.jump_target = jump_target + dont_check_result = True fail_op = ResOperation(rop.FAIL, subset, None) guard_op.suboperations.append(fail_op) all_builders.append(bridge_builder) @@ -405,6 +419,8 @@ print ' # passed.' print + allloops.append(loop) + def test_random_function(BuilderClass=OperationBuilder): r = Random() if demo_conftest.option.repeat == -1: From pedronis at codespeak.net Fri May 1 23:51:16 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 1 May 2009 23:51:16 +0200 (CEST) Subject: [pypy-svn] r64963 - in pypy/build/bot2/pypybuildbot: . test Message-ID: <20090501215116.5ECE416856C@codespeak.net> Author: pedronis Date: Fri May 1 23:51:14 2009 New Revision: 64963 Modified: pypy/build/bot2/pypybuildbot/summary.py pypy/build/bot2/pypybuildbot/test/test_summary.py Log: try to avoid the extra 'pytest failed' lines Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Fri May 1 23:51:14 2009 @@ -123,31 +123,38 @@ rev = int(build.getProperty("got_revision")) pytest_logs = [] pytest_elapsed = 0 - failure = None + with_logs = set() for step in build.getSteps(): logs = dict((log.getName(), log) for log in step.getLogs()) if 'pytestLog' in logs: - aborted = 'aborted' in step.getText() - pytest_logs.append((step.getName(), logs['pytestLog'], aborted)) + with_logs.add(step) + pytest_logs.append((step.getName(), logs['pytestLog'])) ts = step.getTimes() if ts[0] is not None and ts[1] is not None: pytest_elapsed += ts[1]-ts[0] - if (failure is None and - step.getResults()[0] in (FAILURE, EXCEPTION)): - failure = ' '.join(step.getText()) run_info = {'URL': run_url, 'elapsed': pytest_elapsed or None, 'times': build.getTimes()} outcome_set = RevisionOutcomeSet(rev, key, run_info) someresult = False if pytest_logs: - for stepName, resultLog, aborted in pytest_logs: + for stepName, resultLog in pytest_logs: if resultLog.hasContents(): someresult = True - if aborted: - outcome_set.populate_one(stepName+' aborted', '!', "") outcome_set.populate(resultLog) + failedtests = not not outcome_set.failed + + failure = None + for step in build.getSteps(): + if step.getResults()[0] in (FAILURE, EXCEPTION): + text = ' '.join(step.getText()) + if step in with_logs: + if failedtests and text.endswith('failed'): + continue + failure = text + break + if not someresult or failure is not None: if failure: name = '"%s"' % failure # quote Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Fri May 1 23:51:14 2009 @@ -609,7 +609,7 @@ assert 'TEST1' in out assert 'TEST2' in out assert 'pytest aborted' not in out - #assert 'pytest failed' not in out + assert 'pytest failed' not in out assert 'pytest2 aborted' in out def test_subtle_failures(self): From fijal at codespeak.net Sat May 2 00:16:13 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 00:16:13 +0200 (CEST) Subject: [pypy-svn] r64964 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090501221613.52763169EBD@codespeak.net> Author: fijal Date: Sat May 2 00:16:13 2009 New Revision: 64964 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: actually *use* this jump. This test requires additional care since, for unclear reasons, it does not completely repeat the path taken by the previous run of the loop. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sat May 2 00:16:13 2009 @@ -7,8 +7,6 @@ from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.resoperation import opname -allloops = [] - class DummyLoop(object): def __init__(self, subops): self.operations = subops @@ -320,13 +318,13 @@ break -def check_random_function(BuilderClass, r): +def check_random_function(cpu, BuilderClass, r, vars=None): block_length = demo_conftest.option.block_length - vars = [BoxInt(r.random_integer()) - for i in range(demo_conftest.option.n_vars)] + if vars is None: + vars = [BoxInt(r.random_integer()) + for i in range(demo_conftest.option.n_vars)] valueboxes = [BoxInt(box.value) for box in vars] - cpu = get_cpu() loop = TreeLoop('test_random_function') loop.inputargs = vars[:] loop.operations = [] @@ -398,15 +396,16 @@ for i in range(num): subset.append(r.choice(bridge_builder.intvars)) r.shuffle(subset) - if r.random() < 0.1 and allloops: - jump_target = r.choice(allloops) - args = op.args[:len(jump_target.inputargs)] - while len(args) < len(jump_target.inputargs): - args.append(args[-1]) - fail_op = ResOperation(rop.JUMP, args, None) + if len(subset) == 0: + break + if r.random() < 0.1: + jump_target = check_random_function(cpu, BuilderClass, r, + [arg.clonebox() for arg in subset]) + fail_op = ResOperation(rop.JUMP, subset, None) fail_op.jump_target = jump_target dont_check_result = True - fail_op = ResOperation(rop.FAIL, subset, None) + else: + fail_op = ResOperation(rop.FAIL, subset, None) guard_op.suboperations.append(fail_op) all_builders.append(bridge_builder) if bridge_builder.should_fail_by is None: @@ -417,15 +416,15 @@ guard_op = guard_op.suboperations[bridge_builder.should_fail_by_num] print ' # passed.' - print - - allloops.append(loop) + print + return loop def test_random_function(BuilderClass=OperationBuilder): r = Random() + cpu = get_cpu() if demo_conftest.option.repeat == -1: while 1: - check_random_function(BuilderClass, r) + check_random_function(cpu, BuilderClass, r) else: for i in range(demo_conftest.option.repeat): - check_random_function(BuilderClass, r) + check_random_function(cpu, BuilderClass, r) From fijal at codespeak.net Sat May 2 00:22:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 00:22:19 +0200 (CEST) Subject: [pypy-svn] r64965 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090501222219.8E020169DFF@codespeak.net> Author: fijal Date: Sat May 2 00:22:18 2009 New Revision: 64965 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: A typo caught by test_random. good :-) 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 May 2 00:22:18 2009 @@ -534,7 +534,8 @@ if v in self.jump_reg_candidates and (selected_reg is None or self.jump_reg_candidates[v] is selected_reg): for var, reg in self.reg_bindings.items(): - if reg is self.jump_reg_candidates[v] and v not in forbidden_vars: + if (reg is self.jump_reg_candidates[v] and + var not in forbidden_vars): return var iter = self.reg_bindings.iterkeys() while 1: From fijal at codespeak.net Sat May 2 04:18:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 04:18:14 +0200 (CEST) Subject: [pypy-svn] r64966 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502021814.9EA24168533@codespeak.net> Author: fijal Date: Sat May 2 04:18:12 2009 New Revision: 64966 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: refactor test_random. Now loop is enclosed in a nice class. printing is disabled so far, I guess we should call the test with test_random(number) instead. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sat May 2 04:18:12 2009 @@ -7,6 +7,9 @@ from pypy.jit.metainterp.executor import execute from pypy.jit.metainterp.resoperation import opname +class PleaseRewriteMe(Exception): + pass + class DummyLoop(object): def __init__(self, subops): self.operations = subops @@ -67,6 +70,7 @@ subops.append(op) def print_loop(self): + raise PleaseRewriteMe() def update_names(ops): for op in ops: v = op.result @@ -204,7 +208,7 @@ op.suboperations = [ResOperation(rop.FAIL, subset, None)] if not passing: builder.should_fail_by = op.suboperations[0] - builder.should_fail_by_num = len(builder.loop.operations) - 1 + builder.guard_op = op class GuardValueOperation(GuardOperation): def gen_guard(self, builder, r): @@ -306,90 +310,96 @@ else: assert 0, "unknown backend %r" % demo_conftest.option.backend -# ____________________________________________________________ +# ____________________________________________________________ -def generate_ops(builder, block_length, r): - for i in range(block_length): - try: - r.choice(builder.OPERATIONS).produce_into(builder, r) - except CannotProduceOperation: - pass - if builder.should_fail_by is not None: - break - - -def check_random_function(cpu, BuilderClass, r, vars=None): - block_length = demo_conftest.option.block_length - if vars is None: - vars = [BoxInt(r.random_integer()) - for i in range(demo_conftest.option.n_vars)] - valueboxes = [BoxInt(box.value) for box in vars] - - loop = TreeLoop('test_random_function') - loop.inputargs = vars[:] - loop.operations = [] - - builder = BuilderClass(cpu, loop, vars) - generate_ops(builder, block_length, r) - - endvars = [] - used_later = {} - for op in loop.operations: - for v in op.args: - used_later[v] = True - for v in vars: - if v not in used_later: - endvars.append(v) - r.shuffle(endvars) - loop.operations.append(ResOperation(rop.FAIL, endvars, None)) - should_fail_by = builder.should_fail_by - if should_fail_by is not None: - guard_op = loop.operations[builder.should_fail_by_num] - all_builders = [builder] - dont_check_result = False - - while True: - builder.print_loop() +class RandomLoop(object): + def __init__(self, cpu, BuilderClass, r, startvars=None): + self.cpu = cpu + if startvars is None: + startvars = [BoxInt(r.random_integer()) + for i in range(demo_conftest.option.n_vars)] + self.startvars = startvars + self.prebuilt_ptr_consts = [] + self.r = r + self.build_random_loop(cpu, BuilderClass, r, startvars) + + def build_random_loop(self, cpu, BuilderClass, r, startvars): + + loop = TreeLoop('test_random_function') + loop.inputargs = startvars[:] + loop.operations = [] + + builder = BuilderClass(cpu, loop, startvars[:]) + self.generate_ops(builder, r, loop, startvars) + self.builder = builder cpu.compile_operations(loop) + self.loop = loop - if should_fail_by is not None: - endvars = should_fail_by.args - expected = {} + def generate_ops(self, builder, r, loop, startvars): + block_length = demo_conftest.option.block_length + + for i in range(block_length): + try: + r.choice(builder.OPERATIONS).produce_into(builder, r) + except CannotProduceOperation: + pass + if builder.should_fail_by is not None: + break + endvars = [] + used_later = {} + for op in loop.operations: + for v in op.args: + used_later[v] = True + for v in startvars: + if v not in used_later: + endvars.append(v) + r.shuffle(endvars) + loop.operations.append(ResOperation(rop.FAIL, endvars, None)) + if builder.should_fail_by: + self.should_fail_by = builder.should_fail_by + self.guard_op = builder.guard_op + else: + self.should_fail_by = loop.operations[-1] + self.guard_op = None + self.prebuilt_ptr_consts.extend(builder.prebuilt_ptr_consts) + endvars = self.should_fail_by.args + self.expected = {} for v in endvars: - expected[v] = v.value + self.expected[v] = v.value - for b in all_builders: - for v, S, fields in b.prebuilt_ptr_consts: - container = v.value._obj.container - for name, value in fields.items(): - setattr(container, name, value) + def clear_state(self): + for v, S, fields in self.prebuilt_ptr_consts: + container = v.value._obj.container + for name, value in fields.items(): + setattr(container, name, value) + + def run_loop(self): + cpu = self.builder.cpu + valueboxes = [BoxInt(box.value) for box in self.startvars] + self.clear_state() for i, v in enumerate(valueboxes): cpu.set_future_value_int(i, v.value) - op = cpu.execute_operations(loop) - - if dont_check_result: - break - assert op.args == endvars - if should_fail_by is not None: - assert op is should_fail_by - - for i, v in enumerate(endvars): + op = cpu.execute_operations(self.loop) + assert op is self.should_fail_by + for i, v in enumerate(op.args): value = cpu.get_latest_value_int(i) - assert value == expected[v], ( - "Got %d, expected %d, in the variable %s" % (value, - expected[v], - builder.names[v]) + assert value == self.expected[v], ( + "Got %d, expected %d" % (value, + self.expected[v]) ) - if should_fail_by is None or guard_op is None: - break - # build a bridge and repeat + + def build_bridge(self): + r = self.r + guard_op = self.guard_op guard_op.suboperations = [] - subloop = DummyLoop(guard_op.suboperations) + op = self.should_fail_by if not op.args: - break - bridge_builder = BuilderClass(cpu, subloop, op.args[:]) - generate_ops(bridge_builder, block_length, r) + return False + subloop = DummyLoop(guard_op.suboperations) + bridge_builder = self.builder.__class__(self.builder.cpu, subloop, + op.args[:]) + self.generate_ops(bridge_builder, r, subloop, op.args[:]) k = r.random() subset = [] num = int(k * len(bridge_builder.intvars)) @@ -397,27 +407,26 @@ subset.append(r.choice(bridge_builder.intvars)) r.shuffle(subset) if len(subset) == 0: - break + return False if r.random() < 0.1: - jump_target = check_random_function(cpu, BuilderClass, r, - [arg.clonebox() for arg in subset]) + jump_target = RandomLoop(self.builder.cpu, self.builder.__class__, + r) fail_op = ResOperation(rop.JUMP, subset, None) - fail_op.jump_target = jump_target - dont_check_result = True + fail_op.jump_target = jump_target.loop else: fail_op = ResOperation(rop.FAIL, subset, None) guard_op.suboperations.append(fail_op) - all_builders.append(bridge_builder) - if bridge_builder.should_fail_by is None: - should_fail_by = fail_op - guard_op = None - else: - should_fail_by = bridge_builder.should_fail_by - guard_op = guard_op.suboperations[bridge_builder.should_fail_by_num] + return True - print ' # passed.' - print - return loop +def check_random_function(cpu, BuilderClass, r): + loop = RandomLoop(cpu, BuilderClass, r) + while True: + loop.run_loop() + print ' # passed.' + print + if loop.guard_op is not None: + if not loop.build_bridge(): + break def test_random_function(BuilderClass=OperationBuilder): r = Random() From fijal at codespeak.net Sat May 2 04:53:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 04:53:34 +0200 (CEST) Subject: [pypy-svn] r64967 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502025334.64E35168533@codespeak.net> Author: fijal Date: Sat May 2 04:53:28 2009 New Revision: 64967 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: improve, disable jumps so far. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sat May 2 04:53:28 2009 @@ -319,6 +319,7 @@ startvars = [BoxInt(r.random_integer()) for i in range(demo_conftest.option.n_vars)] self.startvars = startvars + self.values = [var.value for var in startvars] self.prebuilt_ptr_consts = [] self.r = r self.build_random_loop(cpu, BuilderClass, r, startvars) @@ -375,11 +376,10 @@ def run_loop(self): cpu = self.builder.cpu - valueboxes = [BoxInt(box.value) for box in self.startvars] self.clear_state() - for i, v in enumerate(valueboxes): - cpu.set_future_value_int(i, v.value) + for i, v in enumerate(self.values): + cpu.set_future_value_int(i, v) op = cpu.execute_operations(self.loop) assert op is self.should_fail_by for i, v in enumerate(op.args): @@ -400,33 +400,44 @@ bridge_builder = self.builder.__class__(self.builder.cpu, subloop, op.args[:]) self.generate_ops(bridge_builder, r, subloop, op.args[:]) - k = r.random() - subset = [] - num = int(k * len(bridge_builder.intvars)) - for i in range(num): - subset.append(r.choice(bridge_builder.intvars)) - r.shuffle(subset) - if len(subset) == 0: - return False - if r.random() < 0.1: + if 0 and r.random() < 0.1: + k = r.random() + subset = [] + num = int(k * len(bridge_builder.intvars)) + for i in range(num): + subset.append(r.choice(bridge_builder.intvars)) + r.shuffle(subset) + if len(subset) == 0: + return False + args = [x.clonebox() for x in subset] jump_target = RandomLoop(self.builder.cpu, self.builder.__class__, - r) - fail_op = ResOperation(rop.JUMP, subset, None) - fail_op.jump_target = jump_target.loop - else: - fail_op = ResOperation(rop.FAIL, subset, None) - guard_op.suboperations.append(fail_op) + r, args) + jump_op = ResOperation(rop.JUMP, subset, None) + jump_op.jump_target = jump_target.loop + self.should_fail_by = jump_target.should_fail_by + self.expected = jump_target.expected + if self.guard_op is None: + guard_op.suboperations[-1] = jump_op + else: + self.guard_op.suboperations[-1] = jump_op + self.guard_op = jump_target.guard_op + self.prebuilt_ptr_consts += jump_target.prebuilt_ptr_consts + if r.random() < .05: + return False + self.builder.cpu.compile_operations(self.loop) return True def check_random_function(cpu, BuilderClass, r): loop = RandomLoop(cpu, BuilderClass, r) while True: loop.run_loop() - print ' # passed.' - print if loop.guard_op is not None: if not loop.build_bridge(): break + else: + break + print ' # passed.' + print def test_random_function(BuilderClass=OperationBuilder): r = Random() From fijal at codespeak.net Sat May 2 05:21:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 05:21:31 +0200 (CEST) Subject: [pypy-svn] r64968 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502032131.EF5BC168532@codespeak.net> Author: fijal Date: Sat May 2 05:21:28 2009 New Revision: 64968 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: generate at most one jump Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sat May 2 05:21:28 2009 @@ -313,6 +313,8 @@ # ____________________________________________________________ class RandomLoop(object): + dont_generate_more = False + def __init__(self, cpu, BuilderClass, r, startvars=None): self.cpu = cpu if startvars is None: @@ -390,6 +392,8 @@ ) def build_bridge(self): + if self.dont_generate_more: + return False r = self.r guard_op = self.guard_op guard_op.suboperations = [] @@ -400,7 +404,7 @@ bridge_builder = self.builder.__class__(self.builder.cpu, subloop, op.args[:]) self.generate_ops(bridge_builder, r, subloop, op.args[:]) - if 0 and r.random() < 0.1: + if r.random() < 0.1: k = r.random() subset = [] num = int(k * len(bridge_builder.intvars)) @@ -412,6 +416,7 @@ args = [x.clonebox() for x in subset] jump_target = RandomLoop(self.builder.cpu, self.builder.__class__, r, args) + self.cpu.compile_operations(jump_target.loop) jump_op = ResOperation(rop.JUMP, subset, None) jump_op.jump_target = jump_target.loop self.should_fail_by = jump_target.should_fail_by @@ -422,6 +427,7 @@ self.guard_op.suboperations[-1] = jump_op self.guard_op = jump_target.guard_op self.prebuilt_ptr_consts += jump_target.prebuilt_ptr_consts + self.dont_generate_more = True if r.random() < .05: return False self.builder.cpu.compile_operations(self.loop) From fijal at codespeak.net Sat May 2 05:43:45 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 05:43:45 +0200 (CEST) Subject: [pypy-svn] r64969 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090502034345.BBF76168498@codespeak.net> Author: fijal Date: Sat May 2 05:43:45 2009 New Revision: 64969 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Leave a clear marker what is broken 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 May 2 05:43:45 2009 @@ -1162,9 +1162,12 @@ free_reg = self.reg_bindings[v] self.Store(v, self.loc(v), self.stack_loc(v)) later_loads.insert(0, (v, self.stack_loc(v), self.loc(v))) + # XXX this is wrong, we can easily overwrite stuff that is on + # stack, we need to do this in a correct order to avoid that for v, from_l, to_l in reloaded: self.Load(v, from_l, free_reg) self.Store(v, free_reg, to_l) + # XXX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ BORKEN self.eventually_free_vars(op.args) for v, from_l, to_l in later_loads: self.Load(v, from_l, to_l) From arigo at codespeak.net Sat May 2 12:12:40 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 May 2009 12:12:40 +0200 (CEST) Subject: [pypy-svn] r64970 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090502101240.95638168516@codespeak.net> Author: arigo Date: Sat May 2 12:12:39 2009 New Revision: 64970 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Add my own comments to consider_jump(). In short I think that the logic in there needs to be rewritten from scratch. 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 May 2 12:12:39 2009 @@ -1115,6 +1115,7 @@ if arg in self.reg_bindings: if not isinstance(res, REG): self.Store(arg, self.loc(arg), loop.arglocs[i]) + # XXX ^^^^^^ this can overwrite random stuff elif res is self.reg_bindings[arg]: middle_busy_regs.append(res) else: @@ -1135,6 +1136,8 @@ 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 False # XXX (arigo) what is this case??? + # XXX it's not hit by any test... assert not isinstance(res, REG) self.Store(arg, self.loc(arg), res) else: @@ -1171,6 +1174,7 @@ self.eventually_free_vars(op.args) for v, from_l, to_l in later_loads: self.Load(v, from_l, to_l) + # XXX ^^^^^ broken: the stack locations in from_l are overwritten above self.PerformDiscard(op, []) def not_implemented_op(self, op, ignored): From arigo at codespeak.net Sat May 2 12:43:47 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 May 2009 12:43:47 +0200 (CEST) Subject: [pypy-svn] r64971 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090502104347.CD909168515@codespeak.net> Author: arigo Date: Sat May 2 12:43:47 2009 New Revision: 64971 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Fix test_random by "fixing" consider_jump(). Actually, this is a rewrite, making consider_jump() much simpler than the code that was there until r64970. At least it's bug-free (hopefully). We can then go on optimizing it again. 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 May 2 12:43:47 2009 @@ -319,6 +319,12 @@ regalloc_store = regalloc_load + def regalloc_push(self, loc): + self.mc.PUSH(loc) + + def regalloc_pop(self, loc): + self.mc.POP(loc) + def regalloc_perform(self, op, arglocs, resloc): genop_list[op.opnum](self, 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 Sat May 2 12:43:47 2009 @@ -1103,78 +1103,35 @@ consider_unicodegetitem = consider_strgetitem def consider_jump(self, op, ignored): - later_loads = [] - reloaded = [] - middle_busy_regs = [] + # This is a simplified version of the code that was there until r64970. + # At least it's bug-free (hopefully). We can then go on optimizing + # it again. + later_pops = [] # pops that will be performed in reverse order + extra_on_stack = 0 + loop = op.jump_target for i in range(len(op.args)): arg = op.args[i] - loop = op.jump_target + src = self.loc(arg) res = loop.arglocs[i] - if not (isinstance(arg, Const) or (arg in self.loop_consts - and self.loop_consts[arg] == i)): - if arg in self.reg_bindings: - if not isinstance(res, REG): - self.Store(arg, self.loc(arg), loop.arglocs[i]) - # XXX ^^^^^^ this can overwrite random stuff - elif res is self.reg_bindings[arg]: - middle_busy_regs.append(res) - else: - # register, but wrong - # we're going to need it (otherwise it'll be dead), so - # we spill it and reload - # if our register is free, easy - for v, reg in self.reg_bindings.items(): - if reg is res: - self.Store(arg, self.loc(arg), - self.stack_loc(arg)) - later_loads.append((arg, self.stack_loc(arg), - res)) - break - else: - self.Load(arg, self.loc(arg), res) - else: - 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 False # XXX (arigo) what is this case??? - # XXX it's not hit by any test... - assert not isinstance(res, REG) - self.Store(arg, self.loc(arg), res) - else: - assert arg not in self.dirty_stack - if isinstance(res, REG): - later_loads.append((arg, self.loc(arg), res)) - else: - arg0 = self.loc(arg) - assert isinstance(arg0, MODRM) - assert isinstance(res, MODRM) - if arg0.position != res.position: - reloaded.append((arg, self.loc(arg), res)) - elif isinstance(arg, Const): - later_loads.append((arg, self.loc(arg), res)) - if reloaded: - # XXX performance - free_reg = None - for reg in REGS: - if reg not in middle_busy_regs: - free_reg = reg - break - if free_reg is None: - # a very rare case - v = self.reg_bindings.keys()[0] - free_reg = self.reg_bindings[v] - self.Store(v, self.loc(v), self.stack_loc(v)) - later_loads.insert(0, (v, self.stack_loc(v), self.loc(v))) - # XXX this is wrong, we can easily overwrite stuff that is on - # stack, we need to do this in a correct order to avoid that - for v, from_l, to_l in reloaded: - self.Load(v, from_l, free_reg) - self.Store(v, free_reg, to_l) - # XXX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ BORKEN + if src is res: + continue # nothing needed to copy in this case + if (isinstance(src, MODRM) and + isinstance(res, MODRM) and + src.position == res.position): + continue # already at the correct stack position + # write the code that moves the correct value into 'res', in two + # steps: generate a pair PUSH (immediately) / POP (later) + if isinstance(src, MODRM): + src = stack_pos(src.position + extra_on_stack) + if isinstance(res, MODRM): + res = stack_pos(res.position + extra_on_stack) + self.assembler.regalloc_push(src) + later_pops.append(res) + extra_on_stack += 1 + # self.eventually_free_vars(op.args) - for v, from_l, to_l in later_loads: - self.Load(v, from_l, to_l) - # XXX ^^^^^ broken: the stack locations in from_l are overwritten above + for i in range(len(later_pops)-1, -1, -1): + self.assembler.regalloc_pop(later_pops[i]) self.PerformDiscard(op, []) def not_implemented_op(self, op, ignored): From arigo at codespeak.net Sat May 2 14:28:06 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 May 2009 14:28:06 +0200 (CEST) Subject: [pypy-svn] r64972 - pypy/branch/pyjitpl5/pypy/config Message-ID: <20090502122806.0D283168423@codespeak.net> Author: arigo Date: Sat May 2 14:28:05 2009 New Revision: 64972 Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py Log: The JIT is incompatible with threads at the moment. Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/config/translationoption.py (original) +++ pypy/branch/pyjitpl5/pypy/config/translationoption.py Sat May 2 14:28:05 2009 @@ -112,7 +112,8 @@ BoolOption("jit", "generate a JIT", default=False, cmdline="--jit", requires=[("translation.gc", "boehm"), - ("translation.list_comprehension_operations", True)]), + ("translation.list_comprehension_operations", True), + ("translation.thread", False)]), ChoiceOption("jit_backend", "choose the backend for the JIT", ["auto", "minimal", "x86"], default="auto", cmdline="--jit-backend"), From jandem at codespeak.net Sat May 2 14:51:08 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Sat, 2 May 2009 14:51:08 +0200 (CEST) Subject: [pypy-svn] r64973 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090502125108.03AC416856D@codespeak.net> Author: jandem Date: Sat May 2 14:51:08 2009 New Revision: 64973 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Function.constructor should have Don't Enumerate flag, fixes FunctionObject tests Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Sat May 2 14:51:08 2009 @@ -585,7 +585,7 @@ w_FncPrototype = w_Function.Call(ctx, this=w_Function) w_Function.Put(ctx, 'prototype', w_FncPrototype, flags = allon) - w_Function.Put(ctx, 'constructor', w_Function) + w_Function.Put(ctx, 'constructor', w_Function, flags=allon) toString = W_ToString(ctx) From jandem at codespeak.net Sat May 2 15:35:10 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Sat, 2 May 2009 15:35:10 +0200 (CEST) Subject: [pypy-svn] r64974 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090502133510.503D31684C8@codespeak.net> Author: jandem Date: Sat May 2 15:35:09 2009 New Revision: 64974 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Add missing constants to Math object and refactor eval, parseInt and parseFloat Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Sat May 2 15:35:09 2009 @@ -120,52 +120,58 @@ TEST = False -def evaljs(ctx, args, this): - if len(args) >= 1: - if isinstance(args[0], W_String): - src = args[0].strval +class W_Eval(W_NewBuiltin): + length = 1 + def Call(self, ctx, args=[], this=None): + if len(args) >= 1: + if isinstance(args[0], W_String): + src = args[0].strval + else: + return args[0] else: - return args[0] - else: - src = '' - try: - node = load_source(src, 'evalcode') - except ParseError, e: - raise ThrowException(W_String('SyntaxError: '+str(e))) - - bytecode = JsCode() - node.emit(bytecode) - return bytecode.run(ctx, retlast=True) + return w_Undefined + + try: + node = load_source(src, 'evalcode') + except ParseError, e: + raise ThrowException(W_String('SyntaxError: '+str(e))) -def parseIntjs(ctx, args, this): - if len(args) < 1: - return W_FloatNumber(NAN) - s = args[0].ToString(ctx).strip(" ") - if len(args) > 1: - radix = args[1].ToInt32(ctx) - else: - radix = 10 - if len(s) >= 2 and (s.startswith('0x') or s.startswith('0X')) : - radix = 16 - s = s[2:] - if s == '' or radix < 2 or radix > 36: - return W_FloatNumber(NAN) - try: - n = int(s, radix) - except ValueError: - return W_FloatNumber(NAN) - return W_IntNumber(n) + bytecode = JsCode() + node.emit(bytecode) + return bytecode.run(ctx, retlast=True) -def parseFloatjs(ctx, args, this): - if len(args) < 1: - return W_FloatNumber(NAN) - s = args[0].ToString(ctx).strip(" ") - try: - n = float(s) - except ValueError: - n = NAN - return W_FloatNumber(n) - +class W_ParseInt(W_NewBuiltin): + length = 1 + def Call(self, ctx, args=[], this=None): + if len(args) < 1: + return W_FloatNumber(NAN) + s = args[0].ToString(ctx).strip(" ") + if len(args) > 1: + radix = args[1].ToInt32(ctx) + else: + radix = 10 + if len(s) >= 2 and (s.startswith('0x') or s.startswith('0X')) : + radix = 16 + s = s[2:] + if s == '' or radix < 2 or radix > 36: + return W_FloatNumber(NAN) + try: + n = int(s, radix) + except ValueError: + return W_FloatNumber(NAN) + return W_IntNumber(n) + +class W_ParseFloat(W_NewBuiltin): + length = 1 + def Call(self, ctx, args=[], this=None): + if len(args) < 1: + return W_FloatNumber(NAN) + s = args[0].ToString(ctx).strip(" ") + try: + n = float(s) + except ValueError: + n = NAN + return W_FloatNumber(n) def printjs(ctx, args, this): writer(",".join([i.ToString(ctx) for i in args])) @@ -713,10 +719,15 @@ w_math.Put(ctx, 'floor', W_Builtin(floorjs, Class='function')) w_math.Put(ctx, 'pow', W_Builtin(powjs, Class='function')) w_math.Put(ctx, 'sqrt', W_Builtin(sqrtjs, Class='function')) - w_math.Put(ctx, 'E', W_FloatNumber(math.e)) - w_math.Put(ctx, 'PI', W_FloatNumber(math.pi)) - - w_Global.Put(ctx, 'version', W_Builtin(versionjs)) + w_math.Put(ctx, 'E', W_FloatNumber(math.e), flags=allon) + w_math.Put(ctx, 'LN2', W_FloatNumber(math.log(2)), flags=allon) + w_math.Put(ctx, 'LN10', W_FloatNumber(math.log(10)), flags=allon) + w_math.Put(ctx, 'LOG2E', W_FloatNumber(math.log(math.e, 2)), flags=allon) + w_math.Put(ctx, 'LOG10E', W_FloatNumber(math.log(math.e, 10)), flags=allon) + w_math.Put(ctx, 'PI', W_FloatNumber(math.pi), flags=allon) + w_math.Put(ctx, 'SQRT1_2', W_FloatNumber(math.sqrt(0.5)), flags=allon) + w_math.Put(ctx, 'SQRT2', W_FloatNumber(math.sqrt(2)), flags=allon) + w_Global.Put(ctx, 'version', W_Builtin(versionjs), flags=allon) #Date w_Date = W_DateFake(ctx, Class='Date') @@ -725,9 +736,9 @@ w_Global.Put(ctx, 'NaN', W_FloatNumber(NAN), flags = DE|DD) w_Global.Put(ctx, 'Infinity', W_FloatNumber(INFINITY), flags = DE|DD) w_Global.Put(ctx, 'undefined', w_Undefined, flags = DE|DD) - w_Global.Put(ctx, 'eval', W_Builtin(evaljs)) - w_Global.Put(ctx, 'parseInt', W_Builtin(parseIntjs)) - w_Global.Put(ctx, 'parseFloat', W_Builtin(parseFloatjs)) + w_Global.Put(ctx, 'eval', W_Eval(ctx)) + w_Global.Put(ctx, 'parseInt', W_ParseInt(ctx)) + w_Global.Put(ctx, 'parseFloat', W_ParseFloat(ctx)) w_Global.Put(ctx, 'isNaN', W_Builtin(isnanjs)) w_Global.Put(ctx, 'isFinite', W_Builtin(isfinitejs)) w_Global.Put(ctx, 'print', W_Builtin(printjs)) From antocuni at codespeak.net Sat May 2 17:22:50 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 2 May 2009 17:22:50 +0200 (CEST) Subject: [pypy-svn] r64975 - in pypy/branch/pyjitpl5/pypy: jit/backend/minimal jit/backend/minimal/test rpython/ootypesystem Message-ID: <20090502152250.6EF19169E83@codespeak.net> Author: antocuni Date: Sat May 2 17:22:48 2009 New Revision: 64975 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py Log: - we cannot rely on the same tricks as lltype to implement do_call; in particular, we cannot cast from a StaticMethod which contains some Void arguments to a StaticMethod without those. Thus, split the lltype and ootype version of calldescrof - implement arraydescrof for ootype - due to a bug in the cli backend, it doesn't compile if hash_bits it too big; as a temporary workaround, patch it Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Sat May 2 17:22:48 2009 @@ -211,36 +211,6 @@ sort_key = self._count_sort_key(T, name) return FieldDescr(dict2['getfield'], dict2['setfield'], sort_key) - @cached_method('_callcache') - def calldescrof(self, FUNC, ARGS, RESULT): - FUNC, cast_func = self._get_cast_func(ARGS, RESULT) - dict2 = base_dict.copy() - args = [] - for i, ARG in enumerate(ARGS): - args.append(make_reader(ARG, 'args[%d]' % i, dict2)) - dict = {'args': ', '.join(args), - 'result': make_writer(RESULT, 'res', dict2)} - dict2.update({'cast_func': cast_func, - 'length': len(ARGS), - 'll_assert': ll_assert, - }) - exec py.code.Source(""" - def call(cpu, function, args): - ll_assert(len(args) == length, 'call: wrong arg count') - function = cast_func(function) - res = function(%(args)s) - return %(result)s - """ % dict).compile() in dict2 - if RESULT is lltype.Void: - errbox = None - elif not self.is_oo and isinstance(RESULT, lltype.Ptr) and RESULT.TO._gckind == 'gc': - errbox = BoxPtr() - elif self.is_oo and isinstance(RESULT, ootype.OOType): - errbox = BoxObj() - else: - errbox = BoxInt() - return CallDescr(FUNC, dict2['call'], errbox) - # ---------- def do_getfield_gc(self, args, fielddescr): @@ -314,6 +284,7 @@ print '\tcall did not raise' return box + def set_overflow_error(self): self.current_exc_inst = self._ovf_error_inst @@ -342,12 +313,6 @@ FIELDTYPE = getattr(STRUCT, name) return PTR, FIELDTYPE, reveal_ptr - def _get_cast_func(self, ARGS, RESULT): - FUNC = lltype.Ptr(lltype.FuncType(ARGS, RESULT)) - def cast_func(function): - return rffi.cast(FUNC, function) - return FUNC, cast_func - def _count_sort_key(self, STRUCT, name): i = list(STRUCT._names).index(name) while True: @@ -391,6 +356,37 @@ return lltype.cast_opaque_ptr(llmemory.GCREF, p) return SizeDescr(alloc) + @cached_method('_callcache') + def calldescrof(self, FUNC, ARGS, RESULT): + dict2 = base_dict.copy() + args = [] + for i, ARG in enumerate(ARGS): + args.append(make_reader(ARG, 'args[%d]' % i, dict2)) + dict = {'args': ', '.join(args), + 'result': make_writer(RESULT, 'res', dict2)} + dict2.update({'rffi': rffi, + 'FUNC': lltype.Ptr(lltype.FuncType(ARGS, RESULT)), + 'length': len(ARGS), + 'll_assert': ll_assert, + }) + exec py.code.Source(""" + def call(cpu, function, args): + ll_assert(len(args) == length, 'call: wrong arg count') + function = rffi.cast(FUNC, function) + res = function(%(args)s) + return %(result)s + """ % dict).compile() in dict2 + if RESULT is lltype.Void: + errbox = None + elif not self.is_oo and isinstance(RESULT, lltype.Ptr) and RESULT.TO._gckind == 'gc': + errbox = BoxPtr() + elif self.is_oo and isinstance(RESULT, ootype.OOType): + errbox = BoxObj() + else: + errbox = BoxInt() + return CallDescr(FUNC, dict2['call'], errbox) + + @cached_method('_arraycache') def arraydescrof(self, ARRAY): dict2 = base_dict.copy() @@ -517,14 +513,12 @@ _, FIELDTYPE = TYPE._lookup_field(name) return TYPE, FIELDTYPE, reveal_obj - def _get_cast_func(self, ARGS, RESULT): - FUNC = ootype.StaticMethod(ARGS, RESULT) - def cast_func(function): - return ootype.cast_from_object(FUNC, function) - return FUNC, cast_func - - def _count_sort_key(self, INSTANCE, name): - fields = sorted(INSTANCE._allfields().keys()) + def _count_sort_key(self, TYPE, name): + try: + fields = TYPE._allfields() + except AttributeError: + fields = TYPE._fields + fields = sorted(fields.keys()) return fields.index(name) def _cast_error_inst(self, ll_inst): @@ -565,6 +559,55 @@ return ootype.cast_to_object(obj) return SizeDescr(alloc) + @cached_method('_callcache') + def calldescrof(self, FUNC, ARGS, RESULT): + from pypy.jit.backend.llgraph.runner import boxresult, make_getargs + getargs = make_getargs(FUNC.ARGS) + def call(cpu, funcobj, argboxes): + func = ootype.cast_from_object(FUNC, funcobj) + funcargs = getargs(argboxes) + res = func(*funcargs) + if RESULT is not ootype.Void: + return boxresult(RESULT, res) + if RESULT is lltype.Void: + errbox = None + elif not self.is_oo and isinstance(RESULT, lltype.Ptr) and RESULT.TO._gckind == 'gc': + errbox = BoxPtr() + elif self.is_oo and isinstance(RESULT, ootype.OOType): + errbox = BoxObj() + else: + errbox = BoxInt() + return CallDescr(FUNC, call, errbox) + + @cached_method('_arraycache') + def arraydescrof(self, ARRAY): + dict2 = base_dict.copy() + dict2['ootype'] = ootype + dict2['ARRAY'] = ARRAY + dict = {'input': make_reader(ARRAY.ITEM, 'xbox', dict2), + 'result': make_writer(ARRAY.ITEM, 'x', dict2)} + exec py.code.Source(""" + def new(length): + array = ootype.oonewarray(ARRAY, length) + return ootype.cast_to_object(array) + def length(cpu, abox): + a = ootype.cast_from_object(ARRAY, abox.getobj()) + return a.ll_length() + def getarrayitem(cpu, abox, index): + a = ootype.cast_from_object(ARRAY, abox.getobj()) + x = a.ll_getitem_fast(index) + return %(result)s + def setarrayitem(cpu, abox, index, xbox): + a = ootype.cast_from_object(ARRAY, abox.getobj()) + x = %(input)s + a.ll_setitem_fast(index, x) + """ % dict).compile() in dict2 + return ArrayDescr(dict2['new'], + dict2['length'], + dict2['getarrayitem'], + dict2['setarrayitem']) + + @cached_method('_methdescrcache') def methdescrof(self, SELFTYPE, methname): return MethDescr(SELFTYPE, methname) @@ -634,15 +677,27 @@ self.call = call self.errbox = errbox + +class StaticMethDescr(AbstractDescr): + + def __init__(self, FUNC, ARGS, RESULT): + from pypy.jit.backend.llgraph.runner import boxresult, make_getargs + getargs = make_getargs(FUNC.ARGS) + def callfunc(funcbox, argboxes): + funcobj = ootype.cast_from_object(FUNC, funcbox.getobj()) + funcargs = getargs(argboxes) + res = funcobj(*funcargs) + if RESULT is not ootype.Void: + return boxresult(RESULT, res) + self.callfunc = callfunc + + class MethDescr(AbstractMethDescr): callmeth = None def __init__(self, SELFTYPE, methname): from pypy.jit.backend.llgraph.runner import boxresult, make_getargs _, meth = SELFTYPE._lookup(methname) METH = ootype.typeOf(meth) - self.SELFTYPE = SELFTYPE - self.METH = METH - self.methname = methname RESULT = METH.RESULT getargs = make_getargs(METH.ARGS) def callmeth(selfbox, argboxes): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Sat May 2 17:22:48 2009 @@ -7,7 +7,15 @@ def skip(self): py.test.skip('in-progress') - test_tl_base = skip + def test_tl_base(self): + # XXX: remove this hack as soon as WarmEnterState is no longer a pbc + from pypy.rlib import jit + try: + jit.PARAMETERS['hash_bits'] = 6 + ToyLanguageTests.test_tl_base(self) + finally: + jit.PARAMETERS['hash_bits'] = 14 + test_tl_2 = skip test_tl_call = skip Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py Sat May 2 17:22:48 2009 @@ -289,6 +289,8 @@ def __repr__(self): return "<%s(%s, %s)>" % (self.__class__.__name__, list(self.ARGS), self.RESULT) + __str__ = __repr__ + def _specialize(self, generic_types): ARGS = tuple([self._specialize_type(ARG, generic_types) for ARG in self.ARGS]) From antocuni at codespeak.net Sat May 2 17:25:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 2 May 2009 17:25:08 +0200 (CEST) Subject: [pypy-svn] r64976 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test Message-ID: <20090502152508.AED09169E9E@codespeak.net> Author: antocuni Date: Sat May 2 17:25:07 2009 New Revision: 64976 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Log: more passing tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Sat May 2 17:25:07 2009 @@ -16,8 +16,24 @@ finally: jit.PARAMETERS['hash_bits'] = 14 - test_tl_2 = skip - test_tl_call = skip + def test_tl_2(self): + # XXX: remove this hack as soon as WarmEnterState is no longer a pbc + from pypy.rlib import jit + try: + jit.PARAMETERS['hash_bits'] = 6 + ToyLanguageTests.test_tl_2(self) + finally: + jit.PARAMETERS['hash_bits'] = 14 + + def test_tl_call(self): + # XXX: remove this hack as soon as WarmEnterState is no longer a pbc + from pypy.rlib import jit + try: + jit.PARAMETERS['hash_bits'] = 6 + ToyLanguageTests.test_tl_call(self) + finally: + jit.PARAMETERS['hash_bits'] = 14 + class TestLLtype(LLTranslatedJitMixin, ToyLanguageTests): From antocuni at codespeak.net Sat May 2 17:43:37 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 2 May 2009 17:43:37 +0200 (CEST) Subject: [pypy-svn] r64977 - pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test Message-ID: <20090502154337.F06A6169EB0@codespeak.net> Author: antocuni Date: Sat May 2 17:43:37 2009 New Revision: 64977 Added: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_basic.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Log: more tests for the minimal backend, with a couple of failures also for lltype :-/ (didn't investigate so far) Added: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_basic.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_basic.py Sat May 2 17:43:37 2009 @@ -0,0 +1,22 @@ +import py +from pypy.jit.metainterp.test.test_basic import BasicTests +from pypy.jit.backend.minimal.test.test_zrpy_exception import LLTranslatedJitMixin, OOTranslatedJitMixin + +class TestOOtype(OOTranslatedJitMixin, BasicTests): + def skip(self): + py.test.skip('in-progress') + + test_stopatxpolicy = skip + test_print = skip + test_bridge_from_interpreter = skip + test_bridge_from_interpreter_2 = skip + + +class TestLLtype(LLTranslatedJitMixin, BasicTests): + def skip(self): + py.test.skip('in-progress') + + test_print = skip + test_bridge_from_interpreter = skip + test_bridge_from_interpreter_2 = skip + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_zrpy_tl.py Sat May 2 17:43:37 2009 @@ -3,9 +3,6 @@ from pypy.jit.backend.minimal.test.test_zrpy_exception import LLTranslatedJitMixin, OOTranslatedJitMixin class TestOOtype(OOTranslatedJitMixin, ToyLanguageTests): - - def skip(self): - py.test.skip('in-progress') def test_tl_base(self): # XXX: remove this hack as soon as WarmEnterState is no longer a pbc From antocuni at codespeak.net Sat May 2 17:48:39 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 2 May 2009 17:48:39 +0200 (CEST) Subject: [pypy-svn] r64978 - pypy/branch/pyjitpl5/pypy/annotation Message-ID: <20090502154839.6C9DC168562@codespeak.net> Author: antocuni Date: Sat May 2 17:48:38 2009 New Revision: 64978 Modified: pypy/branch/pyjitpl5/pypy/annotation/model.py Log: merge part of r54324 from oo-jit/ Modified: pypy/branch/pyjitpl5/pypy/annotation/model.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/model.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/model.py Sat May 2 17:48:38 2009 @@ -624,6 +624,8 @@ return SomeOOStaticMeth(T) elif T == ootype.Class: return SomeOOClass(ootype.ROOT) + elif T == ootype.Object: + return SomeOOObject() elif isinstance(T, ExternalType): return SomeExternalInstance(T._class_) elif isinstance(T, lltype.InteriorPtr): From fijal at codespeak.net Sat May 2 18:37:30 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 18:37:30 +0200 (CEST) Subject: [pypy-svn] r64979 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090502163730.EE0381683BE@codespeak.net> Author: fijal Date: Sat May 2 18:37:29 2009 New Revision: 64979 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: buildbot gets confused by debugging output, ie in a test_doctest, disable 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 May 2 18:37:29 2009 @@ -27,7 +27,7 @@ assert isinstance(arg, (Box, Const)) # debug level: 0 off, 1 normal, 2 detailed -DEBUG = 1 +DEBUG = 0 def log(msg): if not we_are_translated(): From fijal at codespeak.net Sat May 2 18:50:05 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 18:50:05 +0200 (CEST) Subject: [pypy-svn] r64980 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090502165005.24E1C169E83@codespeak.net> Author: fijal Date: Sat May 2 18:50:04 2009 New Revision: 64980 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: disable profile by default, debugging confuses buildbot. 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 May 2 18:50:04 2009 @@ -26,16 +26,22 @@ # ____________________________________________________________ # Bootstrapping +PROFILE = False + def apply_jit(translator, backend_name="auto", **kwds): from pypy.jit.metainterp.simple_optimize import Optimizer if 'CPUClass' not in kwds: from pypy.jit.backend.detect_cpu import getcpuclass kwds['CPUClass'] = getcpuclass(backend_name) + if PROFILE: + profile = Profiler + else: + profile = None warmrunnerdesc = WarmRunnerDesc(translator, translate_support_code=True, listops=True, optimizer=Optimizer, - profile=Profiler, + profile=profile, **kwds) warmrunnerdesc.finish() translator.warmrunnerdesc = warmrunnerdesc # for later debugging From fijal at codespeak.net Sat May 2 20:21:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 20:21:48 +0200 (CEST) Subject: [pypy-svn] r64981 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502182148.66695169E7C@codespeak.net> Author: fijal Date: Sat May 2 20:21:47 2009 New Revision: 64981 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: non-raising calls Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sat May 2 20:21:47 2009 @@ -3,7 +3,8 @@ from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr - +from pypy.rpython.annlowlevel import llhelper +from pypy.rlib.rarithmetic import intmask class LLtypeOperationBuilder(test_random.OperationBuilder): @@ -151,6 +152,33 @@ v_ptr = builder.do(self.opnum, args, self.size_descr(builder, S)) builder.ptrvars.append((v_ptr, S)) +class CallOperation(test_random.AbstractOperation): + def produce_into(self, builder, r): + subset = builder.subset_of_intvars(r) + if len(subset) == 0: + sum = "" + funcargs = "" + else: + funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))]) + sum = "intmask(%s)" % " + ".join(['arg_%d' % i for i in range(len(subset))]) + code = py.code.Source(""" + def f(%s): + return %s + """ % (funcargs, sum)).compile() + d = {'intmask' : intmask} + exec code in d + + if len(subset) == 0: + RES = lltype.Void + else: + RES = lltype.Signed + TP = lltype.FuncType([lltype.Signed] * len(subset), RES) + ptr = llhelper(lltype.Ptr(TP), d['f']) + c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) + args = [c_addr] + subset + descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) + self.put(builder, args, descr) + # ____________________________________________________________ OPERATIONS = test_random.OPERATIONS[:] @@ -163,6 +191,7 @@ OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE)) OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) + OPERATIONS.append(CallOperation(rop.CALL)) LLtypeOperationBuilder.OPERATIONS = OPERATIONS Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sat May 2 20:21:47 2009 @@ -47,6 +47,15 @@ v = self.do(rop.INT_IS_TRUE, [v]) return v + def subset_of_intvars(self, r): + subset = [] + k = r.random() + num = int(k * len(self.intvars)) + for i in range(num): + subset.append(r.choice(self.intvars)) + r.shuffle(subset) + return subset + def process_operation(self, s, op, names, subops): args = [] for v in op.args: @@ -152,9 +161,10 @@ self.boolres = boolres def put(self, builder, args, descr=None): v_result = builder.do(self.opnum, args, descr=descr) - builder.intvars.append(v_result) - if self.boolres: - builder.boolvars.append(v_result) + if v_result is not None: + builder.intvars.append(v_result) + if self.boolres: + builder.boolvars.append(v_result) class UnaryOperation(AbstractOperation): def produce_into(self, builder, r): @@ -199,12 +209,7 @@ def produce_into(self, builder, r): op, passing = self.gen_guard(builder, r) builder.loop.operations.append(op) - k = r.random() - subset = [] - num = int(k * len(builder.intvars)) - for i in range(num): - subset.append(r.choice(builder.intvars)) - r.shuffle(subset) + subset = builder.subset_of_intvars(r) op.suboperations = [ResOperation(rop.FAIL, subset, None)] if not passing: builder.should_fail_by = op.suboperations[0] @@ -405,12 +410,7 @@ op.args[:]) self.generate_ops(bridge_builder, r, subloop, op.args[:]) if r.random() < 0.1: - k = r.random() - subset = [] - num = int(k * len(bridge_builder.intvars)) - for i in range(num): - subset.append(r.choice(bridge_builder.intvars)) - r.shuffle(subset) + subset = bridge_builder.subset_of_intvars(r) if len(subset) == 0: return False args = [x.clonebox() for x in subset] From fijal at codespeak.net Sat May 2 20:25:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 20:25:39 +0200 (CEST) Subject: [pypy-svn] r64982 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502182539.36CDD169E9F@codespeak.net> Author: fijal Date: Sat May 2 20:25:38 2009 New Revision: 64982 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: add a GUARD_NO_EXCEPTION Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sat May 2 20:25:38 2009 @@ -178,6 +178,9 @@ args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) + op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) + op.suboperations = [ResOperation(rop.FAIL, [], None)] + builder.loop.operations.append(op) # ____________________________________________________________ From fijal at codespeak.net Sat May 2 20:37:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 20:37:36 +0200 (CEST) Subject: [pypy-svn] r64983 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502183736.531EA168562@codespeak.net> Author: fijal Date: Sat May 2 20:37:35 2009 New Revision: 64983 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: Document all cases about raising calls Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sat May 2 20:37:35 2009 @@ -152,6 +152,14 @@ v_ptr = builder.do(self.opnum, args, self.size_descr(builder, S)) builder.ptrvars.append((v_ptr, S)) +# there are five options in total: +# 1. non raising call and guard_no_exception +# 2. raising call and guard_exception +# 3. raising call and wrong guard_exception +# 4. raising call and guard_no_exception +# 5. non raising call and guard_exception + +# 1. non raising call and guard_no_exception class CallOperation(test_random.AbstractOperation): def produce_into(self, builder, r): subset = builder.subset_of_intvars(r) @@ -182,6 +190,13 @@ op.suboperations = [ResOperation(rop.FAIL, [], None)] builder.loop.operations.append(op) +# 2. raising call and guard_exception + + +#class RaisingCallOperation(CallOperation): +# def produce_into(self, builder, r): + + # ____________________________________________________________ OPERATIONS = test_random.OPERATIONS[:] From arigo at codespeak.net Sat May 2 20:47:19 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 May 2009 20:47:19 +0200 (CEST) Subject: [pypy-svn] r64984 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090502184719.5DAFC169E9F@codespeak.net> Author: arigo Date: Sat May 2 20:47:18 2009 New Revision: 64984 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: Clarify the error message. This was really needed after all... 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 May 2 20:47:18 2009 @@ -819,6 +819,7 @@ cfunc = get_on_lib(ctypes.windll.kernel32, funcname) else: cfunc = None + not_found = [] for libname in libraries: libpath = ctypes.util.find_library(libname) if not libpath and os.path.isabs(libname): @@ -830,15 +831,26 @@ cfunc = get_on_lib(clib, funcname) if cfunc is not None: break + else: + not_found.append(libname) if cfunc is None: # function name not found in any of the libraries if not libraries: place = 'the standard C library (missing libraries=...?)' + elif len(not_found) == len(libraries): + if len(not_found) == 1: + raise NotImplementedError( + 'cannot find the library %r' % (not_found[0],)) + else: + raise NotImplementedError( + 'cannot find any of the libraries %r' % (not_found,)) elif len(libraries) == 1: place = 'library %r' % (libraries[0],) else: place = 'any of the libraries %r' % (libraries,) + if not_found: + place += ' (did not find %r)' % (not_found,) raise NotImplementedError("function %r not found in %s" % ( funcname, place)) From benjamin at codespeak.net Sat May 2 20:48:22 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sat, 2 May 2009 20:48:22 +0200 (CEST) Subject: [pypy-svn] r64985 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090502184822.31BC0169EC5@codespeak.net> Author: benjamin Date: Sat May 2 20:48:21 2009 New Revision: 64985 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: small typo 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 May 2 20:48:21 2009 @@ -575,7 +575,7 @@ self.Load(v, prev_loc, loc) assert v in self.reg_bindings if self.longevity[v][1] > self.position: - # we need to find a new place for variable x and + # we need to find a new place for variable v and # store result in the same place loc = self.reg_bindings[v] del self.reg_bindings[v] From arigo at codespeak.net Sat May 2 20:53:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 May 2009 20:53:07 +0200 (CEST) Subject: [pypy-svn] r64986 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090502185307.9B49716850E@codespeak.net> Author: arigo Date: Sat May 2 20:53:07 2009 New Revision: 64986 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: Also respect library_dirs in ll2ctypes. 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 May 2 20:53:07 2009 @@ -821,9 +821,21 @@ cfunc = None not_found = [] for libname in libraries: - libpath = ctypes.util.find_library(libname) - if not libpath and os.path.isabs(libname): - libpath = libname + libpath = None + for dir in eci.library_dirs: + if sys.platform == "win32": + tryfile = os.path.join(dir, libname + '.dll') + elif sys.platform == "darwin": + tryfile = os.path.join(dir, libname + '.dylib') + else: + tryfile = os.path.join(dir, libname + '.so') + if os.path.isfile(tryfile): + libpath = tryfile + break + if not libpath: + libpath = ctypes.util.find_library(libname) + if not libpath and os.path.isabs(libname): + libpath = libname if libpath: dllclass = getattr(ctypes, calling_conv + 'dll') # urgh, cannot pass the flag to dllclass.LoadLibrary From fijal at codespeak.net Sat May 2 21:02:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 21:02:20 +0200 (CEST) Subject: [pypy-svn] r64987 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502190220.5434B16855B@codespeak.net> Author: fijal Date: Sat May 2 21:02:16 2009 New Revision: 64987 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: IN-PROGRESS a framework for raising calls, will continue on it later Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sat May 2 21:02:16 2009 @@ -8,6 +8,9 @@ class LLtypeOperationBuilder(test_random.OperationBuilder): + def __init__(self, *args, **kw): + test_random.OperationBuilder.__init__(self, *args, **kw) + def get_structptr_var(self, r, must_have_vtable=False): while True: if self.ptrvars and r.random() < 0.8: @@ -159,9 +162,8 @@ # 4. raising call and guard_no_exception # 5. non raising call and guard_exception -# 1. non raising call and guard_no_exception -class CallOperation(test_random.AbstractOperation): - def produce_into(self, builder, r): +class BaseCallOperation(test_random.AbstractOperation): + def non_raising_func_code(self, builder, r): subset = builder.subset_of_intvars(r) if len(subset) == 0: sum = "" @@ -175,13 +177,25 @@ """ % (funcargs, sum)).compile() d = {'intmask' : intmask} exec code in d + return subset, d['f'] + + def raising_func_code(self, builder, r): + funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))]) + code = py.code.Source(""" + def f(%s): + raise LLException() + """ % funcargs) +# 1. non raising call and guard_no_exception +class CallOperation(BaseCallOperation): + def produce_into(self, builder, r): + subset, f = self.non_raising_func_code(builder, r) if len(subset) == 0: RES = lltype.Void else: RES = lltype.Signed TP = lltype.FuncType([lltype.Signed] * len(subset), RES) - ptr = llhelper(lltype.Ptr(TP), d['f']) + ptr = llhelper(lltype.Ptr(TP), f) c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) args = [c_addr] + subset descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) @@ -192,10 +206,9 @@ # 2. raising call and guard_exception - -#class RaisingCallOperation(CallOperation): -# def produce_into(self, builder, r): - +class RaisingCallOperation(BaseCallOperation): + def produce_into(self, builder, r): + subset, f, exc = self.raising_func_code(builder, r) # ____________________________________________________________ From fijal at codespeak.net Sat May 2 21:16:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 May 2009 21:16:34 +0200 (CEST) Subject: [pypy-svn] r64988 - pypy/branch/pyjitpl5/pypy/rpython Message-ID: <20090502191634.C22A3169E9F@codespeak.net> Author: fijal Date: Sat May 2 21:16:32 2009 New Revision: 64988 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Log: Provide some default for _store_exception hack for x86 backend. Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Sat May 2 21:16:32 2009 @@ -182,6 +182,12 @@ self.mallocs = {} self.mallocs.update(items) + def _store_exception(self, exc): + raise PleaseOverwriteStoreException("You just invoked ll2ctypes callback without overwriting _store_exception on llinterpreter") + +class PleaseOverwriteStoreException(Exception): + pass + def checkptr(ptr): assert isinstance(lltype.typeOf(ptr), lltype.Ptr) From fijal at codespeak.net Sun May 3 00:22:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 00:22:04 +0200 (CEST) Subject: [pypy-svn] r64989 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090502222204.75FE1168515@codespeak.net> Author: fijal Date: Sun May 3 00:22:03 2009 New Revision: 64989 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: support exception in this case as well 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 May 3 00:22:03 2009 @@ -471,9 +471,9 @@ else: resdata = '-> ' + repr1(res, restype, self.memocast) # fish the types - log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.memocast), - resdata)) + #log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, + # self.memocast), + # resdata)) return res def as_int(self, x): @@ -1071,15 +1071,15 @@ args = cast_call_args(ARGS, _call_args, memocast) del _call_args[:] assert len(ARGS) == len(args) - if hasattr(ptr._obj, 'graph'): - llinterp = _llinterp # it's a global set here by CPU.__init__() - try: + try: + if hasattr(ptr._obj, 'graph'): + llinterp = _llinterp # it's a global set here by CPU.__init__() result = llinterp.eval_graph(ptr._obj.graph, args) - except LLException, e: - _last_exception = e - result = err_result - else: - result = ptr._obj._callable(*args) # no exception support in this case + else: + result = ptr._obj._callable(*args) + except LLException, e: + _last_exception = e + result = err_result return result def do_call_void(f, memocast): From fijal at codespeak.net Sun May 3 00:23:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 00:23:27 +0200 (CEST) Subject: [pypy-svn] r64990 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090502222327.7E639168515@codespeak.net> Author: fijal Date: Sun May 3 00:23:27 2009 New Revision: 64990 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: (disabled) raising call. There are some problems with handling exceptions in llgraph backend, investigating. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sun May 3 00:23:27 2009 @@ -2,9 +2,10 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr +from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr, BoxPtr from pypy.rpython.annlowlevel import llhelper from pypy.rlib.rarithmetic import intmask +from pypy.rpython.llinterp import LLException class LLtypeOperationBuilder(test_random.OperationBuilder): @@ -180,11 +181,22 @@ return subset, d['f'] def raising_func_code(self, builder, r): + subset = builder.subset_of_intvars(r) funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))]) + S, v = builder.get_structptr_var(r, must_have_vtable=True) + code = py.code.Source(""" def f(%s): - raise LLException() - """ % funcargs) + raise LLException(ptr, vtable) + """ % funcargs).compile() + vtableptr = v._hints['vtable']._as_ptr() + d = { + 'ptr': S.value._obj.container._as_ptr(), + 'vtable' : vtableptr, + 'LLException' : LLException, + } + exec code in d + return subset, d['f'], vtableptr # 1. non raising call and guard_no_exception class CallOperation(BaseCallOperation): @@ -209,6 +221,16 @@ class RaisingCallOperation(BaseCallOperation): def produce_into(self, builder, r): subset, f, exc = self.raising_func_code(builder, r) + TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) + ptr = llhelper(lltype.Ptr(TP), f) + c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) + args = [c_addr] + subset + descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) + self.put(builder, args, descr) + exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) + op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr()) + op.suboperations = [ResOperation(rop.FAIL, [], None)] + builder.loop.operations.append(op) # ____________________________________________________________ @@ -223,6 +245,7 @@ OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) OPERATIONS.append(CallOperation(rop.CALL)) +# OPERATIONS.append(RaisingCallOperation(rop.CALL)) LLtypeOperationBuilder.OPERATIONS = OPERATIONS From fijal at codespeak.net Sun May 3 04:22:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 04:22:36 +0200 (CEST) Subject: [pypy-svn] r64991 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090503022236.664E6168522@codespeak.net> Author: fijal Date: Sun May 3 04:22:34 2009 New Revision: 64991 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: support raising calls. x86 backend is a bit confused though Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sun May 3 04:22:34 2009 @@ -187,7 +187,7 @@ code = py.code.Source(""" def f(%s): - raise LLException(ptr, vtable) + raise LLException(vtable, ptr) """ % funcargs).compile() vtableptr = v._hints['vtable']._as_ptr() d = { @@ -228,6 +228,8 @@ descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) + assert builder.cpu.get_exception() + builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr()) op.suboperations = [ResOperation(rop.FAIL, [], None)] builder.loop.operations.append(op) @@ -245,7 +247,7 @@ OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) OPERATIONS.append(CallOperation(rop.CALL)) -# OPERATIONS.append(RaisingCallOperation(rop.CALL)) + OPERATIONS.append(RaisingCallOperation(rop.CALL)) LLtypeOperationBuilder.OPERATIONS = OPERATIONS From fijal at codespeak.net Sun May 3 04:58:05 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 04:58:05 +0200 (CEST) Subject: [pypy-svn] r64992 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090503025805.090861684F6@codespeak.net> Author: fijal Date: Sun May 3 04:58:02 2009 New Revision: 64992 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: fix for x86 backend. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sun May 3 04:58:02 2009 @@ -191,7 +191,7 @@ """ % funcargs).compile() vtableptr = v._hints['vtable']._as_ptr() d = { - 'ptr': S.value._obj.container._as_ptr(), + 'ptr': S.value, 'vtable' : vtableptr, 'LLException' : LLException, } From fijal at codespeak.net Sun May 3 05:24:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 05:24:20 +0200 (CEST) Subject: [pypy-svn] r64993 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090503032420.6E1BA16852D@codespeak.net> Author: fijal Date: Sun May 3 05:24:17 2009 New Revision: 64993 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Yet-another-case. Boring, all x86 tests are passing Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sun May 3 05:24:17 2009 @@ -232,7 +232,28 @@ builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr()) op.suboperations = [ResOperation(rop.FAIL, [], None)] - builder.loop.operations.append(op) + builder.loop.operations.append(op) + +# 4. raising call and guard_no_exception + +class RaisingCallOperationGuardNoException(BaseCallOperation): + def produce_into(self, builder, r): + subset, f, exc = self.raising_func_code(builder, r) + TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) + ptr = llhelper(lltype.Ptr(TP), f) + c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) + args = [c_addr] + subset + descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) + self.put(builder, args, descr) + assert builder.cpu.get_exception() + builder.cpu.clear_exception() + op = ResOperation(rop.GUARD_NO_EXCEPTION, [], BoxPtr()) + op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) + subset = builder.subset_of_intvars(r) + op.suboperations = [ResOperation(rop.FAIL, subset, None)] + builder.should_fail_by = op.suboperations[0] + builder.guard_op = op + builder.loop.operations.append(op) # ____________________________________________________________ @@ -248,6 +269,7 @@ OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) OPERATIONS.append(CallOperation(rop.CALL)) OPERATIONS.append(RaisingCallOperation(rop.CALL)) + OPERATIONS.append(RaisingCallOperationGuardNoException(rop.CALL)) LLtypeOperationBuilder.OPERATIONS = OPERATIONS Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sun May 3 05:24:17 2009 @@ -389,6 +389,10 @@ cpu.set_future_value_int(i, v) op = cpu.execute_operations(self.loop) assert op is self.should_fail_by + if (self.guard_op is not None and + self.guard_op.opnum == rop.GUARD_NO_EXCEPTION): + assert cpu.get_exception() + cpu.clear_exception() for i, v in enumerate(op.args): value = cpu.get_latest_value_int(i) assert value == self.expected[v], ( @@ -397,6 +401,13 @@ ) def build_bridge(self): + def exc_handling(guard_op): + # operations need to start with correct GUARD_EXCEPTION + op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box], + BoxPtr()) + op.suboperations = [ResOperation(rop.FAIL, [], None)] + return op + if self.dont_generate_more: return False r = self.r @@ -406,6 +417,8 @@ if not op.args: return False subloop = DummyLoop(guard_op.suboperations) + if guard_op.opnum == rop.GUARD_NO_EXCEPTION: + guard_op.suboperations.append(exc_handling(guard_op)) bridge_builder = self.builder.__class__(self.builder.cpu, subloop, op.args[:]) self.generate_ops(bridge_builder, r, subloop, op.args[:]) @@ -424,6 +437,10 @@ if self.guard_op is None: guard_op.suboperations[-1] = jump_op else: + if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: + # exception clearing + self.guard_op.suboperations.insert(-1, exc_handling( + self.guard_op)) self.guard_op.suboperations[-1] = jump_op self.guard_op = jump_target.guard_op self.prebuilt_ptr_consts += jump_target.prebuilt_ptr_consts From fijal at codespeak.net Sun May 3 05:39:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 05:39:49 +0200 (CEST) Subject: [pypy-svn] r64994 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090503033949.BEE9216852D@codespeak.net> Author: fijal Date: Sun May 3 05:39:49 2009 New Revision: 64994 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: convinient helper Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sun May 3 05:39:49 2009 @@ -59,6 +59,10 @@ def is_guard(self): return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST + def is_guard_exception(self): + return (self.opnum == rop.GUARD_EXCEPTION or + self.opnum == rop.GUARD_NO_EXCEPTION) + def is_always_pure(self): return rop._ALWAYS_PURE_FIRST <= self.opnum <= rop._ALWAYS_PURE_LAST From fijal at codespeak.net Sun May 3 05:40:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 05:40:17 +0200 (CEST) Subject: [pypy-svn] r64995 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090503034017.E978216852D@codespeak.net> Author: fijal Date: Sun May 3 05:40:15 2009 New Revision: 64995 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Point 3. wrong guard_exception after call Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Sun May 3 05:40:15 2009 @@ -11,6 +11,7 @@ def __init__(self, *args, **kw): test_random.OperationBuilder.__init__(self, *args, **kw) + self.vtable_counter = 0 def get_structptr_var(self, r, must_have_vtable=False): while True: @@ -42,6 +43,9 @@ def get_random_structure_type_and_vtable(self, r): vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) + vtable.subclassrange_min = self.vtable_counter + vtable.subclassrange_max = self.vtable_counter + self.vtable_counter += 1 S = self.get_random_structure_type(r, with_vtable=vtable) name = S._name vtable.name = lltype.malloc(lltype.Array(lltype.Char), len(name)+1, @@ -255,6 +259,30 @@ builder.guard_op = op builder.loop.operations.append(op) +# 3. raising call and wrong guard_exception + +class RaisingCallOperationWrongGuardException(BaseCallOperation): + def produce_into(self, builder, r): + subset, f, exc = self.raising_func_code(builder, r) + TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) + ptr = llhelper(lltype.Ptr(TP), f) + c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) + args = [c_addr] + subset + descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) + self.put(builder, args, descr) + assert builder.cpu.get_exception() + builder.cpu.clear_exception() + _, vtableptr = builder.get_random_structure_type_and_vtable(r) + assert vtableptr != exc + other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) + op = ResOperation(rop.GUARD_EXCEPTION, [other_box], BoxPtr()) + op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) + subset = builder.subset_of_intvars(r) + op.suboperations = [ResOperation(rop.FAIL, subset, None)] + builder.should_fail_by = op.suboperations[0] + builder.guard_op = op + builder.loop.operations.append(op) + # ____________________________________________________________ OPERATIONS = test_random.OPERATIONS[:] @@ -270,6 +298,7 @@ OPERATIONS.append(CallOperation(rop.CALL)) OPERATIONS.append(RaisingCallOperation(rop.CALL)) OPERATIONS.append(RaisingCallOperationGuardNoException(rop.CALL)) + OPERATIONS.append(RaisingCallOperationWrongGuardException(rop.CALL)) LLtypeOperationBuilder.OPERATIONS = OPERATIONS Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sun May 3 05:40:15 2009 @@ -390,7 +390,7 @@ op = cpu.execute_operations(self.loop) assert op is self.should_fail_by if (self.guard_op is not None and - self.guard_op.opnum == rop.GUARD_NO_EXCEPTION): + self.guard_op.is_guard_exception()): assert cpu.get_exception() cpu.clear_exception() for i, v in enumerate(op.args): @@ -417,7 +417,7 @@ if not op.args: return False subloop = DummyLoop(guard_op.suboperations) - if guard_op.opnum == rop.GUARD_NO_EXCEPTION: + if guard_op.is_guard_exception(): guard_op.suboperations.append(exc_handling(guard_op)) bridge_builder = self.builder.__class__(self.builder.cpu, subloop, op.args[:]) @@ -437,7 +437,7 @@ if self.guard_op is None: guard_op.suboperations[-1] = jump_op else: - if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: + if self.guard_op.is_guard_exception(): # exception clearing self.guard_op.suboperations.insert(-1, exc_handling( self.guard_op)) From fijal at codespeak.net Sun May 3 05:52:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 05:52:42 +0200 (CEST) Subject: [pypy-svn] r64996 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090503035242.B3DB6168522@codespeak.net> Author: fijal Date: Sun May 3 05:52:42 2009 New Revision: 64996 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: disable jump_reg_candidates, probably only for now. The reason is that it is just an optimization and we want to get it right first. 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 Sun May 3 05:52:42 2009 @@ -101,6 +101,7 @@ def _create_jump_reg_candidates(self, jump): self.jump_reg_candidates = {} + return for i in range(len(jump.args)): arg = jump.args[i] loc = jump.jump_target.arglocs[i] @@ -609,9 +610,9 @@ # it's better to say here that we're always in dirty stack # than worry at the jump point self.dirty_stack[arg] = True - if jump is not None: - jarg = jump.args[i] - self.jump_reg_candidates[jarg] = reg + #if jump is not None: + # jarg = jump.args[i] + # self.jump_reg_candidates[jarg] = reg else: loc = stack_pos(i) self.stack_bindings[arg] = loc From arigo at codespeak.net Sun May 3 12:06:29 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 12:06:29 +0200 (CEST) Subject: [pypy-svn] r64997 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090503100629.E1AEA168525@codespeak.net> Author: arigo Date: Sun May 3 12:06:27 2009 New Revision: 64997 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: Complete the test by testing for a second case. 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 Sun May 3 12:06:27 2009 @@ -59,6 +59,8 @@ res = self.meta_interp(f, [20], policy=StopAtXPolicy(check)) assert res == f(20) + res = self.meta_interp(f, [21], policy=StopAtXPolicy(check)) + assert res == f(21) def test_bridge_from_guard_no_exception(self): myjitdriver = JitDriver(greens = [], reds = ['n']) From arigo at codespeak.net Sun May 3 12:07:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 12:07:32 +0200 (CEST) Subject: [pypy-svn] r64998 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090503100732.49CA81683EB@codespeak.net> Author: arigo Date: Sun May 3 12:07:31 2009 New Revision: 64998 Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/ (props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/ (props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py (contents, props changed) Log: Start the llvm backend. As usual, using the many llvm libs and .o files dynamically is a complete mess. The current solution seems to work, even though I'm not completely sure how :-/ Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/__init__.py ============================================================================== Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c Sun May 3 12:07:31 2009 @@ -0,0 +1,12 @@ +/* LLVM includes */ +#include "llvm-c/Analysis.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm-c/ExecutionEngine.h" + +/* The following list of functions seems to be necessary to force the + * functions to be included in pypy_cache_llvm.so. The list is never + * used. + */ +void* llvm_c_functions[] = { + (void*) LLVMModuleCreateWithName +}; Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 12:07:31 2009 @@ -0,0 +1,57 @@ +import py, os, sys +import pypy +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.translator.tool.cbuild import ExternalCompilationInfo, log + +if sys.platform != 'linux2': + py.test.skip("Linux only for now") + +# ____________________________________________________________ + +llvm_config = 'llvm-config' +cachename = os.path.join(os.path.dirname(pypy.__file__), '_cache') +dirname = os.path.join(cachename, 'libs') +libname = os.path.join(dirname, 'pypy_cache_llvm.so') +cname = os.path.join(os.path.dirname(__file__), 'demo1.c') + +if not os.path.isfile(libname) or (os.path.getmtime(cname) > + os.path.getmtime(libname)): + if not os.path.isdir(dirname): + if not os.path.isdir(cachename): + os.mkdir(cachename) + os.mkdir(dirname) + + def do(cmdline): + log(cmdline) + err = os.system(cmdline) + if err: + raise Exception("gcc command failed") + + oname = os.path.join(dirname, 'demo1.o') + do("gcc -c '%s' -o '%s'" % (cname, oname)) + do("g++ -shared '%s' -o '%s'" % (oname, libname) + + " `%s --libs jit`" % llvm_config + + " `%s --cflags`" % llvm_config + + " `%s --ldflags`" % llvm_config + + "") + +compilation_info = ExternalCompilationInfo( + library_dirs = [dirname], + libraries = ['pypy_cache_llvm'], +) + +# ____________________________________________________________ + +def llexternal(name, args, result, **kwds): + return rffi.llexternal(name, args, result, + compilation_info=compilation_info, + **kwds) + +def opaqueptr(name): + return rffi.VOIDP # lltype.Ptr(rffi.COpaque(name)) + +LLVMModuleRef = opaqueptr('struct LLVMModuleOpaque') + +LLVMModuleCreateWithName = llexternal('LLVMModuleCreateWithName', + [rffi.CCHARP], + LLVMModuleRef) Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/__init__.py ============================================================================== Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py Sun May 3 12:07:31 2009 @@ -0,0 +1,5 @@ + +from pypy.jit.backend.llvm.llvm_rffi import * + +def test_basic(): + LLVMModuleCreateWithName("hello") From arigo at codespeak.net Sun May 3 13:49:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 13:49:17 +0200 (CEST) Subject: [pypy-svn] r64999 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090503114917.CE7CF1684D7@codespeak.net> Author: arigo Date: Sun May 3 13:49:16 2009 New Revision: 64999 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py Log: Work hard until the first example of 'llvm-py'is complete and runs with a JIT. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c Sun May 3 13:49:16 2009 @@ -5,7 +5,7 @@ /* The following list of functions seems to be necessary to force the * functions to be included in pypy_cache_llvm.so. The list is never - * used. + * used. Actually, any single function seems to be enough... */ void* llvm_c_functions[] = { (void*) LLVMModuleCreateWithName Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 13:49:16 2009 @@ -30,10 +30,7 @@ oname = os.path.join(dirname, 'demo1.o') do("gcc -c '%s' -o '%s'" % (cname, oname)) do("g++ -shared '%s' -o '%s'" % (oname, libname) + - " `%s --libs jit`" % llvm_config + - " `%s --cflags`" % llvm_config + - " `%s --ldflags`" % llvm_config + - "") + " `%s --cflags --ldflags --libs jit engine`" % llvm_config) compilation_info = ExternalCompilationInfo( library_dirs = [dirname], @@ -50,8 +47,87 @@ def opaqueptr(name): return rffi.VOIDP # lltype.Ptr(rffi.COpaque(name)) -LLVMModuleRef = opaqueptr('struct LLVMModuleOpaque') +LLVMModuleRef = opaqueptr('struct LLVMOpaqueModule') +LLVMTypeRef = opaqueptr('struct LLVMOpaqueType') +LLVMValueRef = opaqueptr('struct LLVMOpaqueValue') +LLVMBasicBlockRef = opaqueptr('struct LLVMOpaqueBasicBlock') +LLVMBuilderRef = opaqueptr('struct LLVMOpaqueBuilder') +LLVMModuleProviderRef = opaqueptr('struct LLVMOpaqueModuleProvider') +LLVMGenericValueRef = opaqueptr('struct LLVMOpaqueGenericValue') +LLVMExecutionEngineRef = opaqueptr('struct LLVMOpaqueExecutionEngine') + +# ____________________________________________________________ LLVMModuleCreateWithName = llexternal('LLVMModuleCreateWithName', [rffi.CCHARP], LLVMModuleRef) +LLVMDumpModule = llexternal('LLVMDumpModule', [LLVMModuleRef], lltype.Void) + +LLVMInt32Type = llexternal('LLVMInt32Type', [], LLVMTypeRef) +LLVMFunctionType = llexternal('LLVMFunctionType', + [LLVMTypeRef, # return type + rffi.CArrayPtr(LLVMTypeRef), # param types + rffi.UINT, # param count + rffi.INT], # flag: is vararg + LLVMTypeRef) + +LLVMAddFunction = llexternal('LLVMAddFunction', + [LLVMModuleRef, # module + rffi.CCHARP, # name + LLVMTypeRef], # function type + LLVMValueRef) +LLVMGetParam = llexternal('LLVMGetParam', + [LLVMValueRef, # function + rffi.UINT], # index + LLVMValueRef) + +LLVMAppendBasicBlock = llexternal('LLVMAppendBasicBlock', + [LLVMValueRef, # function + rffi.CCHARP], # name + LLVMBasicBlockRef) + +LLVMCreateBuilder = llexternal('LLVMCreateBuilder', [], LLVMBuilderRef) +LLVMPositionBuilderAtEnd = llexternal('LLVMPositionBuilderAtEnd', + [LLVMBuilderRef, # builder + LLVMBasicBlockRef], # block + lltype.Void) + +LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef, # builder, + LLVMValueRef], # result + LLVMValueRef) +LLVMBuildAdd = llexternal('LLVMBuildAdd', [LLVMBuilderRef, # builder + LLVMValueRef, # left-hand side + LLVMValueRef, # right-hand side + rffi.CCHARP], # name of result + LLVMValueRef) + +LLVMCreateModuleProviderForExistingModule = llexternal( + 'LLVMCreateModuleProviderForExistingModule', [LLVMModuleRef], + LLVMModuleProviderRef) + +# ____________________________________________________________ + +LLVMCreateGenericValueOfInt = llexternal('LLVMCreateGenericValueOfInt', + [LLVMTypeRef, # type + rffi.ULONGLONG, # value + rffi.INT], # flag: is_signed + LLVMGenericValueRef) + +LLVMGenericValueToInt = llexternal('LLVMGenericValueToInt', + [LLVMGenericValueRef, + rffi.INT], # flag: is_signed + rffi.ULONGLONG) + +LLVMCreateJITCompiler = llexternal('LLVMCreateJITCompiler', + [rffi.CArrayPtr(LLVMExecutionEngineRef), + LLVMModuleProviderRef, + rffi.INT, # "fast" + rffi.CArrayPtr(rffi.CCHARP)], # -> error + rffi.INT) + +LLVMRunFunction = llexternal('LLVMRunFunction', + [LLVMExecutionEngineRef, + LLVMValueRef, # function + rffi.UINT, # num args + rffi.CArrayPtr(LLVMGenericValueRef)], # args + LLVMGenericValueRef) # return value Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py Sun May 3 13:49:16 2009 @@ -1,5 +1,91 @@ from pypy.jit.backend.llvm.llvm_rffi import * -def test_basic(): - LLVMModuleCreateWithName("hello") + +def test_from_llvm_py_example_1(): + # NOTE: no GC so far!!!!!!!!! + + # Create an (empty) module. + my_module = LLVMModuleCreateWithName("my_module") + + # All the types involved here are "int"s. This type is represented + # by an object of type LLVMTypeRef: + ty_int = LLVMInt32Type() + + # We need to represent the class of functions that accept two integers + # and return an integer. This is represented by another LLVMTypeRef: + arglist = lltype.malloc(rffi.CArray(LLVMTypeRef), 2, flavor='raw') + arglist[0] = ty_int + arglist[1] = ty_int + ty_func = LLVMFunctionType(ty_int, arglist, 2, False) + lltype.free(arglist, flavor='raw') + + # Now we need a function named 'sum' of this type. Functions are not + # free-standing; it needs to be contained in a module. + f_sum = LLVMAddFunction(my_module, "sum", ty_func) + f_arg_0 = LLVMGetParam(f_sum, 0) + f_arg_1 = LLVMGetParam(f_sum, 1) + + # Our function needs a "basic block" -- a set of instructions that + # end with a terminator (like return, branch etc.). By convention + # the first block is called "entry". + bb = LLVMAppendBasicBlock(f_sum, "entry") + + # Let's add instructions into the block. For this, we need an + # instruction builder: + builder = LLVMCreateBuilder() + LLVMPositionBuilderAtEnd(builder, bb) + + # OK, now for the instructions themselves. We'll create an add + # instruction that returns the sum as a value, which we'll use + # a ret instruction to return. + tmp = LLVMBuildAdd(builder, f_arg_0, f_arg_1, "tmp") + LLVMBuildRet(builder, tmp) + + # We've completed the definition now! Let's see the LLVM assembly + # language representation of what we've created: (it goes to stderr) + LLVMDumpModule(my_module) + return locals() + + +class LLVMException(Exception): + pass + + +def test_from_llvm_py_example_2(): + d = test_from_llvm_py_example_1() + my_module = d['my_module'] + ty_int = d['ty_int'] + f_sum = d['f_sum'] + + # Create a module provider object first. Modules can come from + # in-memory IRs like what we created now, or from bitcode (.bc) + # files. The module provider abstracts this detail. + mp = LLVMCreateModuleProviderForExistingModule(my_module) + + # Create an execution engine object. This creates a JIT compiler, + # or complain on platforms that don't support it. + ee_out = lltype.malloc(rffi.CArray(LLVMExecutionEngineRef), 1, flavor='raw') + error_out = lltype.malloc(rffi.CArray(rffi.CCHARP), 1, flavor='raw') + try: + error = LLVMCreateJITCompiler(ee_out, mp, True, error_out) + if rffi.cast(lltype.Signed, error) != 0: + raise LLVMException(rffi.charp2str(error_out[0])) + ee = ee_out[0] + finally: + lltype.free(error_out, flavor='raw') + lltype.free(ee_out, flavor='raw') + + # The arguments needs to be passed as "GenericValue" objects. + args = lltype.malloc(rffi.CArray(LLVMGenericValueRef), 2, flavor='raw') + args[0] = LLVMCreateGenericValueOfInt(ty_int, 100, True) + args[1] = LLVMCreateGenericValueOfInt(ty_int, 42, True) + + # Now let's compile and run! + retval = LLVMRunFunction(ee, f_sum, 2, args) + lltype.free(args, flavor='raw') + + # The return value is also GenericValue. Let's check it. + ulonglong = LLVMGenericValueToInt(retval, True) + res = rffi.cast(lltype.Signed, ulonglong) + assert res == 142 From arigo at codespeak.net Sun May 3 16:50:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 16:50:34 +0200 (CEST) Subject: [pypy-svn] r65000 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090503145034.6735B1684E7@codespeak.net> Author: arigo Date: Sun May 3 16:50:33 2009 New Revision: 65000 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py Log: Some freeing of temporary values, at least. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 16:50:33 2009 @@ -58,6 +58,9 @@ # ____________________________________________________________ +LLVMDisposeMessage = llexternal('LLVMDisposeMessage', [rffi.CCHARP], + lltype.Void) + LLVMModuleCreateWithName = llexternal('LLVMModuleCreateWithName', [rffi.CCHARP], LLVMModuleRef) @@ -91,6 +94,8 @@ [LLVMBuilderRef, # builder LLVMBasicBlockRef], # block lltype.Void) +LLVMDisposeBuilder = llexternal('LLVMDisposeBuilder', [LLVMBuilderRef], + lltype.Void) LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef, # builder, LLVMValueRef], # result @@ -112,6 +117,8 @@ rffi.ULONGLONG, # value rffi.INT], # flag: is_signed LLVMGenericValueRef) +LLVMDisposeGenericValue = llexternal('LLVMDisposeGenericValue', + [LLVMGenericValueRef], lltype.Void) LLVMGenericValueToInt = llexternal('LLVMGenericValueToInt', [LLVMGenericValueRef, Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py Sun May 3 16:50:33 2009 @@ -3,7 +3,7 @@ def test_from_llvm_py_example_1(): - # NOTE: no GC so far!!!!!!!!! + # NOTE: minimal GC (some objects are never freed) # Create an (empty) module. my_module = LLVMModuleCreateWithName("my_module") @@ -41,6 +41,7 @@ # a ret instruction to return. tmp = LLVMBuildAdd(builder, f_arg_0, f_arg_1, "tmp") LLVMBuildRet(builder, tmp) + LLVMDisposeBuilder(builder) # We've completed the definition now! Let's see the LLVM assembly # language representation of what we've created: (it goes to stderr) @@ -67,12 +68,15 @@ # or complain on platforms that don't support it. ee_out = lltype.malloc(rffi.CArray(LLVMExecutionEngineRef), 1, flavor='raw') error_out = lltype.malloc(rffi.CArray(rffi.CCHARP), 1, flavor='raw') + error_out[0] = lltype.nullptr(rffi.CCHARP.TO) try: error = LLVMCreateJITCompiler(ee_out, mp, True, error_out) if rffi.cast(lltype.Signed, error) != 0: raise LLVMException(rffi.charp2str(error_out[0])) ee = ee_out[0] finally: + if error_out[0]: + LLVMDisposeMessage(error_out[0]) lltype.free(error_out, flavor='raw') lltype.free(ee_out, flavor='raw') @@ -83,9 +87,12 @@ # Now let's compile and run! retval = LLVMRunFunction(ee, f_sum, 2, args) + LLVMDisposeGenericValue(args[1]) + LLVMDisposeGenericValue(args[0]) lltype.free(args, flavor='raw') # The return value is also GenericValue. Let's check it. ulonglong = LLVMGenericValueToInt(retval, True) + LLVMDisposeGenericValue(retval) res = rffi.cast(lltype.Signed, ulonglong) assert res == 142 From arigo at codespeak.net Sun May 3 17:17:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 17:17:23 +0200 (CEST) Subject: [pypy-svn] r65001 - in pypy/branch/pyjitpl5/pypy/jit: backend backend/x86 metainterp Message-ID: <20090503151723.5E6A31684EA@codespeak.net> Author: arigo Date: Sun May 3 17:17:21 2009 New Revision: 65001 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/model.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Change the one-time runtime initialization to give the cpu a chance to do it too. Useful for llvm. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/model.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/model.py Sun May 3 17:17:21 2009 @@ -1,5 +1,9 @@ class AbstractCPU(object): + def setup_once(self): + """Called once by the front-end when the program starts.""" + pass + def compile_operations(self, loop): """Assemble the given list of operations.""" raise NotImplementedError 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 Sun May 3 17:17:21 2009 @@ -182,6 +182,9 @@ # def set_meta_interp(self, metainterp): # self.metainterp = metainterp + def setup_once(self): + pass + def get_exception(self): self.assembler.make_sure_mc_exists() return self.assembler._exception_bck[0] 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 May 3 17:17:21 2009 @@ -870,12 +870,19 @@ def _freeze_(self): return True - def _recompute_class_sizes(self): - if self.cpu.class_sizes is None: - cs = {} - for key, value in self._class_sizes: - cs[key] = value - self.cpu.class_sizes = cs + def _setup_once(self): + """Runtime setup needed by the various components of the JIT.""" + if not self.globaldata.initialized: + if self.cpu.class_sizes is None: + cs = {} + for key, value in self._class_sizes: + cs[key] = value + self.cpu.class_sizes = cs + self.cpu.setup_once() + if not self.profiler.initialized: + self.profiler.start() + self.profiler.initialized = True + self.globaldata.initialized = True def generate_bytecode(self, policy, ts): self._codewriter = codewriter.CodeWriter(self, policy, ts) @@ -906,6 +913,7 @@ self._debug_history = [] self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash) # { greenkey: list-of-MergePoints } + self.initialized = False # ____________________________________________________________ @@ -1244,8 +1252,8 @@ *args[1:]) def initialize_state_from_start(self, *args): + self.staticdata._setup_once() self.staticdata.profiler.start_tracing() - self.staticdata._recompute_class_sizes() self.create_empty_history() num_green_args = self.staticdata.num_green_args original_boxes = [] 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 Sun May 3 17:17:21 2009 @@ -589,9 +589,6 @@ return #interp.debug_trace("jit_compile", *greenargs) metainterp_sd = warmrunnerdesc.metainterp_sd - if not metainterp_sd.profiler.initialized: - metainterp_sd.profiler.start() - metainterp_sd.profiler.initialized = True metainterp = MetaInterp(metainterp_sd) loop = metainterp.compile_and_run_once(*args) else: From arigo at codespeak.net Sun May 3 17:30:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 17:30:48 +0200 (CEST) Subject: [pypy-svn] r65002 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090503153048.6B2561684A8@codespeak.net> Author: arigo Date: Sun May 3 17:30:48 2009 New Revision: 65002 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Comment out old operations, not used any more. 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 May 3 17:30:48 2009 @@ -609,13 +609,13 @@ def opimpl_residual_oosend_pure(self, methdescr, boxes): self.execute(rop.OOSEND_PURE, boxes, descr=methdescr) - @arguments("box", "box") - def opimpl_oostring_char(self, obj, base): - self.execute(rop.OOSTRING_CHAR, [obj, base]) - - @arguments("box", "box") - def opimpl_oounicode_unichar(self, obj, base): - self.execute(rop.OOUNICODE_UNICHAR, [obj, base]) +# @arguments("box", "box") +# def opimpl_oostring_char(self, obj, base): +# self.execute(rop.OOSTRING_CHAR, [obj, base]) +# +# @arguments("box", "box") +# def opimpl_oounicode_unichar(self, obj, base): +# self.execute(rop.OOUNICODE_UNICHAR, [obj, base]) @arguments("orgpc", "box") def opimpl_guard_value(self, pc, box): From arigo at codespeak.net Sun May 3 17:31:12 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 17:31:12 +0200 (CEST) Subject: [pypy-svn] r65003 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090503153112.A42F31684A8@codespeak.net> Author: arigo Date: Sun May 3 17:31:12 2009 New Revision: 65003 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Log: Remove dead import. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Sun May 3 17:31:12 2009 @@ -2,7 +2,6 @@ """ import py -from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask From arigo at codespeak.net Sun May 3 17:39:55 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 17:39:55 +0200 (CEST) Subject: [pypy-svn] r65004 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090503153955.3EDD71684D7@codespeak.net> Author: arigo Date: Sun May 3 17:39:54 2009 New Revision: 65004 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Log: Implement oohash, as a call to a small helper function (good enough for now). 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 May 3 17:39:54 2009 @@ -1142,10 +1142,9 @@ self.emit(self.get_position(virtualizabledesc)) self.emit(self.get_position(guard_field)) - def serialize_op_oostring(self, op): - self.handle_builtin_call(op) - - serialize_op_oounicode = serialize_op_oostring + serialize_op_oostring = handle_builtin_call + serialize_op_oounicode = handle_builtin_call + serialize_op_oohash = handle_builtin_call # ---------- 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 Sun May 3 17:39:54 2009 @@ -194,6 +194,12 @@ def _ll_1_oounicode_unichar_foldable(ch): return ootype.oounicode(ch, -1) +def _ll_1_oohash_string_foldable(s): + return ootype.oohash(s) + +def _ll_1_oohash_unicode_foldable(u): + return ootype.oohash(u) + # ------------------------------------------------------- def setup_extra_builtin(oopspec_name, nb_args): @@ -255,6 +261,15 @@ args = op.args return '%s_%s_foldable' % (op.opname, T._name.lower()), args +def get_oohash_oopspec(op): + T = op.args[0].concretetype + if T is ootype.String: + return 'oohash_string_foldable', op.args + elif T is ootype.Unicode: + return 'oohash_unicode_foldable', op.args + else: + raise Exception("oohash() of type %r" % (T,)) + RENAMED_ADT_NAME = { 'list': { @@ -279,6 +294,8 @@ return get_send_oopspec(SELFTYPE, name), opargs elif op.opname in ('oostring', 'oounicode'): return get_oostring_oopspec(op) + elif op.opname == 'oohash': + return get_oohash_oopspec(op) elif op.opname == 'direct_call': fnobj = get_funcobj(op.args[0].value) opargs = op.args[1:] 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 Sun May 3 17:39:54 2009 @@ -559,7 +559,15 @@ class TestOOtype(BasicTests, OOJitMixin): - pass + + def test_oohash(self): + def f(): + s = ootype.oostring(5, -1) + return ootype.oohash(s) + res = self.interp_operations(f, []) + # xxx can we rely on oohash() returning the same value in and out of + # translation? + assert res == ootype.oohash(ootype.oostring(5, -1)) class TestLLtype(BasicTests, LLJitMixin): 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 Sun May 3 17:39:54 2009 @@ -575,8 +575,7 @@ res = self.meta_interp(f, [200]) class TestOOtype(LoopTest, OOJitMixin): - def test_loop_unicode(self): - py.test.skip("oohash") + pass class TestLLtype(LoopTest, LLJitMixin): pass From fijal at codespeak.net Sun May 3 18:42:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 May 2009 18:42:04 +0200 (CEST) Subject: [pypy-svn] r65005 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090503164204.B869D1684E7@codespeak.net> Author: fijal Date: Sun May 3 18:42:03 2009 New Revision: 65005 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: Even more incredible hack to cooperate with llhelpers. I think the chance that random callback raises LLException is small, although maybe we should come up with something saner at some point.... 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 Sun May 3 18:42:03 2009 @@ -564,12 +564,22 @@ raise AssertionError llinterp = LLInterpreter.current_interpreter try: + import pdb + pdb.set_trace() llres = llinterp.eval_graph(container.graph, llargs) except LLException, lle: llinterp._store_exception(lle) return 0 + except: + import pdb + pdb.set_trace() else: - llres = container._callable(*llargs) + try: + llres = container._callable(*llargs) + except LLException, lle: + llinterp = LLInterpreter.current_interpreter + llinterp._store_exception(lle) + return 0 assert lltype.typeOf(llres) == T.TO.RESULT if T.TO.RESULT is lltype.Void: return None From benjamin at codespeak.net Sun May 3 19:13:21 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 3 May 2009 19:13:21 +0200 (CEST) Subject: [pypy-svn] r65006 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test Message-ID: <20090503171321.569BF1684E1@codespeak.net> Author: benjamin Date: Sun May 3 19:13:19 2009 New Revision: 65006 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: only one failing llgraph test now 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 Sun May 3 19:13:19 2009 @@ -1,4 +1,5 @@ import py +from pypy.translator import translator from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rclass from pypy.rpython.test.test_llinterp import interpret from pypy.rlib.unroll import unrolling_iterable @@ -7,7 +8,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute -from pypy.jit.backend.test.runner import BaseBackendTest +from pypy.jit.backend.test.runner import LLtypeBackendTest NODE = lltype.GcForwardReference() NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed), @@ -16,10 +17,14 @@ SUBNODE = lltype.GcStruct('SUBNODE', ('parent', NODE)) -class LLGraphTest(BaseBackendTest): +class LLGraphTests: def setup_method(self, _): - self.cpu = self.cpu_type(None) + context = translator.TranslationContext() + context.buildannotator() + typer = context.buildrtyper() + typer.getexceptiondata().make_helpers(typer) + self.cpu = self.cpu_type(typer) def eval_llinterp(self, runme, *args, **kwds): expected_class = kwds.pop('expected_class', None) @@ -218,9 +223,9 @@ assert x.getptr(lltype.Ptr(rstr.STR)).chars[4] == '/' -class TestLLTypeLLGraph(LLGraphTest): +class TestLLTypeLLGraph(LLtypeBackendTest, LLGraphTests): from pypy.jit.backend.llgraph.runner import LLtypeCPU as cpu_type - + ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): ## from pypy.jit.backend.llgraph.runner import OOtypeCPU as cpu_type From benjamin at codespeak.net Sun May 3 20:07:38 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sun, 3 May 2009 20:07:38 +0200 (CEST) Subject: [pypy-svn] r65007 - pypy/branch/pyjitpl5/pypy/jit/metainterp/doc Message-ID: <20090503180738.A1110168528@codespeak.net> Author: benjamin Date: Sun May 3 20:07:35 2009 New Revision: 65007 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/warmspot.txt Log: update Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/warmspot.txt ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/warmspot.txt (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/warmspot.txt Sun May 3 20:07:35 2009 @@ -3,25 +3,24 @@ We introduce two jit hints: -can_enter_jit(**keys) +jit_merge_point(**keys) and -can_leave_jit() +can_enter_jit(**keys) -In case of python interpreter, can_enter_jit is invoked at -a place where app-level jump takes place (JUMP_ABSOLUTE opcode) -and can_leave_jit is invoked at the beginning of the main interpreter -loop. +In case of python interpreter, can_enter_jit is invoked at a place where +app-level jump takes place (JUMP_ABSOLUTE opcode) and jit_merge_point is +invoked at the beginning of the main interpreter loop. The interpreter starts from running normally, without generating any assembler at all. When it encounters can_enter_jit with exactly the same key enough number of times, it starts tracing (the "slow" path of pyjitpl), -until it finds out efficient loop (XXX or loop at all?). +until it finds a loop to compile. Next time we run the efficient loop (assembler code) and we encounter -failing guard, we use JIT without tracing (ie compiling and executing -one instruction at a time, but not doing anything more) for fast -"get out of here" until we encounter can_leave_jit (end of the opcode usually), -where we completely exit jit. +failing guard, we use JIT without tracing (ie compiling and executing one +instruction at a time, but not doing anything more) for fast "get out of +here" until we encounter jit_merge_point (end of the opcode usually), where +we completely exit jit. From arigo at codespeak.net Sun May 3 20:44:43 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 20:44:43 +0200 (CEST) Subject: [pypy-svn] r65008 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090503184443.C81A6168496@codespeak.net> Author: arigo Date: Sun May 3 20:44:42 2009 New Revision: 65008 Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Log: Add the CPU class. The first test passes. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 20:44:42 2009 @@ -71,8 +71,20 @@ [LLVMTypeRef, # return type rffi.CArrayPtr(LLVMTypeRef), # param types rffi.UINT, # param count - rffi.INT], # flag: is vararg + rffi.INT], # flag: is_vararg LLVMTypeRef) +LLVMPointerType = llexternal('LLVMPointerType', [LLVMTypeRef, # element type + rffi.UINT], # address space + LLVMTypeRef) + +LLVMConstInt = llexternal('LLVMConstInt', [LLVMTypeRef, # type + rffi.ULONGLONG, # value + rffi.INT], # flag: is_signed + LLVMValueRef) +LLVMConstIntToPtr = llexternal('LLVMConstIntToPtr', + [LLVMValueRef, # constant integer value + LLVMTypeRef], # type of the result + LLVMValueRef) LLVMAddFunction = llexternal('LLVMAddFunction', [LLVMModuleRef, # module @@ -100,11 +112,27 @@ LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef, # builder, LLVMValueRef], # result LLVMValueRef) -LLVMBuildAdd = llexternal('LLVMBuildAdd', [LLVMBuilderRef, # builder - LLVMValueRef, # left-hand side - LLVMValueRef, # right-hand side - rffi.CCHARP], # name of result - LLVMValueRef) + +for _name in ['Add', 'Sub', 'LShr']: + globals()['LLVMBuild' + _name] = llexternal('LLVMBuild' + _name, + [LLVMBuilderRef, # builder + LLVMValueRef, # left-hand side + LLVMValueRef, # right-hand side + rffi.CCHARP], # name of result + LLVMValueRef) + +for _name in ['Neg', 'Not']: + globals()['LLVMBuild' + _name] = llexternal('LLVMBuild' + _name, + [LLVMBuilderRef, # builder + LLVMValueRef, # argument + rffi.CCHARP], # name of result + LLVMValueRef) + +LLVMBuildStore = llexternal('LLVMBuildStore', + [LLVMBuilderRef, # builder + LLVMValueRef, # value + LLVMValueRef], # pointer location + LLVMValueRef) LLVMCreateModuleProviderForExistingModule = llexternal( 'LLVMCreateModuleProviderForExistingModule', [LLVMModuleRef], Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Sun May 3 20:44:42 2009 @@ -0,0 +1,197 @@ +import sys +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.metainterp.history import ConstInt +from pypy.jit.backend import model +from pypy.jit.backend.llvm import llvm_rffi +from pypy.jit.metainterp import resoperation +from pypy.jit.metainterp.resoperation import rop + + +class LLVMException(Exception): + pass + + +class LLVMCPU(model.AbstractCPU): + ARRAY_OF_VALUE_REFS = rffi.CArray(llvm_rffi.LLVMGenericValueRef) + RAW_VALUE = rffi.CFixedArray(rffi.ULONGLONG, 1) + + def __init__(self, rtyper, stats=None, translate_support_code=False, + annmixlevel=None): + self.rtyper = rtyper + self.translate_support_code = translate_support_code + self.ty_funcs = {} + self.fail_ops = [] + self.in_args_count = 0 + self.in_args = lltype.malloc(self.ARRAY_OF_VALUE_REFS, 0, + flavor='raw') + self.out_args = [] + + def setup_once(self): + self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit") + if sys.maxint == 2147483647: + self.ty_int = llvm_rffi.LLVMInt32Type() + else: + self.ty_int = llvm_rffi.LLVMInt64Type() + self.ty_int_ptr = llvm_rffi.LLVMPointerType(self.ty_int, 0) + + mp = llvm_rffi.LLVMCreateModuleProviderForExistingModule(self.module) + ee_out = lltype.malloc(rffi.CArray(llvm_rffi.LLVMExecutionEngineRef), + 1, flavor='raw') + error_out = lltype.malloc(rffi.CArray(rffi.CCHARP), 1, flavor='raw') + error_out[0] = lltype.nullptr(rffi.CCHARP.TO) + try: + error = llvm_rffi.LLVMCreateJITCompiler(ee_out, mp, True, + error_out) + if rffi.cast(lltype.Signed, error) != 0: + raise LLVMException(rffi.charp2str(error_out[0])) + self.ee = ee_out[0] + finally: + if error_out[0]: + llvm_rffi.LLVMDisposeMessage(error_out[0]) + lltype.free(error_out, flavor='raw') + lltype.free(ee_out, flavor='raw') + + # ------------------------------ + # Compilation + + def compile_operations(self, loop): + self._ensure_in_args(len(loop.inputargs)) + ty_func = self.get_ty_func(len(loop.inputargs)) + func = llvm_rffi.LLVMAddFunction(self.module, "", ty_func) + self.vars = {} + for i in range(len(loop.inputargs)): + self.vars[loop.inputargs[i]] = llvm_rffi.LLVMGetParam(func, i) + self.builder = llvm_rffi.LLVMCreateBuilder() + self._generate_branch(loop.operations, func) + llvm_rffi.LLVMDisposeBuilder(self.builder) + self.builder = None + self.vars = None + #... + llvm_rffi.LLVMDumpModule(self.module) + loop._llvm_func = func + + def get_ty_func(self, nb_args): + try: + return self.ty_funcs[nb_args] + except KeyError: + arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef), + nb_args, flavor='raw') + for i in range(nb_args): + arglist[i] = self.ty_int + ty_func = llvm_rffi.LLVMFunctionType(self.ty_int, arglist, + nb_args, False) + lltype.free(arglist, flavor='raw') + self.ty_funcs[nb_args] = ty_func + return ty_func + + def _ensure_in_args(self, count): + if self.in_args_count <= count: + count = (count + 8) & ~7 # increment by at least one + new = lltype.malloc(self.ARRAY_OF_VALUE_REFS, count, flavor='raw') + lltype.free(self.in_args, flavor='raw') + for i in range(count): + new[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO) + self.in_args = new + self.in_args_count = count + + def _ensure_out_args(self, count): + while len(self.out_args) < count: + self.out_args.append(lltype.malloc(self.RAW_VALUE, flavor='raw')) + + def _generate_branch(self, operations, func): + bb = llvm_rffi.LLVMAppendBasicBlock(func, "") + llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb) + # + for op in operations: + self._generate_op(op) + # + return bb + + def _generate_op(self, op): + opnum = op.opnum + for i, name in all_operations: + if opnum == i: + meth = getattr(self, name) + meth(op) + return + else: + raise MissingOperation(resoperation.opname[opnum]) + + def getarg(self, v): + try: + return self.vars[v] + except KeyError: + assert isinstance(v, ConstInt) + return self._make_const_int(v.value) + + def _make_const_int(self, value): + return llvm_rffi.LLVMConstInt(self.ty_int, value, True) + + def generate_int_add(self, op): + self.vars[op.result] = llvm_rffi.LLVMBuildAdd(self.builder, + self.getarg(op.args[0]), + self.getarg(op.args[1]), + "") + + def generate_uint_rshift(self, op): + self.vars[op.result] = llvm_rffi.LLVMBuildLShr(self.builder, + self.getarg(op.args[0]), + self.getarg(op.args[1]), + "") + + def generate_int_invert(self, op): + self.vars[op.result] = llvm_rffi.LLVMBuildNot(self.builder, + self.vars[op.args[0]], + "") + + def generate_fail(self, op): + self._ensure_out_args(len(op.args)) + for i in range(len(op.args)): + addr_as_signed = rffi.cast(lltype.Signed, self.out_args[i]) + llvmconstint = self._make_const_int(addr_as_signed) + llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint, + self.ty_int_ptr) + llvm_rffi.LLVMBuildStore(self.builder, self.vars[op.args[i]], + llvmconstptr) + i = len(self.fail_ops) + self.fail_ops.append(op) + llvm_rffi.LLVMBuildRet(self.builder, self._make_const_int(i)) + + # ------------------------------ + # Execution + + def set_future_value_int(self, index, intvalue): + assert index < self.in_args_count - 1 + self.in_args[index] = llvm_rffi.LLVMCreateGenericValueOfInt( + self.ty_int, intvalue, True) + + def execute_operations(self, loop): + retval = llvm_rffi.LLVMRunFunction(self.ee, loop._llvm_func, + len(loop.inputargs), + self.in_args) + ulonglong = llvm_rffi.LLVMGenericValueToInt(retval, True) + res = rffi.cast(lltype.Signed, ulonglong) + llvm_rffi.LLVMDisposeGenericValue(retval) + i = 0 + while self.in_args[i]: + llvm_rffi.LLVMDisposeGenericValue(self.in_args[i]) + self.in_args[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO) + i += 1 + + def get_latest_value_int(self, index): + return rffi.cast(lltype.Signed, self.out_args[index][0]) + +# ____________________________________________________________ + +class MissingOperation(Exception): + pass + +all_operations = {} +for _key, _value in rop.__dict__.items(): + if 'A' <= _key <= 'Z': + assert _value not in all_operations + methname = 'generate_' + _key.lower() + if hasattr(LLVMCPU, methname): + all_operations[_value] = methname +all_operations = unrolling_iterable(all_operations.items()) Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Sun May 3 20:44:42 2009 @@ -0,0 +1,27 @@ + +from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ + BoxPtr, ConstPtr, TreeLoop +from pypy.jit.metainterp.resoperation import rop +from pypy.jit.backend.llvm.runner import LLVMCPU + + +def test_simple_case(): + v1 = BoxInt() + v2 = BoxInt() + v3 = BoxInt() + v4 = BoxInt() + loop = TreeLoop('test') + loop.inputargs = [v1] + loop.operations = [ + ResOperation(rop.INT_ADD, [v1, v1], v2), + ResOperation(rop.INT_INVERT, [v2], v3), + ResOperation(rop.UINT_RSHIFT, [v1, ConstInt(3)], v4), + ResOperation(rop.FAIL, [v4, v3], None), + ] + cpu = LLVMCPU(None) + cpu.setup_once() + cpu.compile_operations(loop) + cpu.set_future_value_int(0, 19) + cpu.execute_operations(loop) + assert cpu.get_latest_value_int(0) == (19 >> 3) + assert cpu.get_latest_value_int(1) == (~38) From arigo at codespeak.net Sun May 3 21:49:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 21:49:38 +0200 (CEST) Subject: [pypy-svn] r65009 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090503194938.D85421684EA@codespeak.net> Author: arigo Date: Sun May 3 21:49:36 2009 New Revision: 65009 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Log: Pass a test with a simple loop. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 21:49:36 2009 @@ -56,6 +56,18 @@ LLVMGenericValueRef = opaqueptr('struct LLVMOpaqueGenericValue') LLVMExecutionEngineRef = opaqueptr('struct LLVMOpaqueExecutionEngine') +class Predicate: + EQ = 32 # equal + NE = 33 # not equal + UGT = 34 # unsigned greater than + UGE = 35 # unsigned greater or equal + ULT = 36 # unsigned less than + ULE = 37 # unsigned less or equal + SGT = 38 # signed greater than + SGE = 39 # signed greater or equal + SLT = 40 # signed less than + SLE = 41 # signed less or equal + # ____________________________________________________________ LLVMDisposeMessage = llexternal('LLVMDisposeMessage', [rffi.CCHARP], @@ -66,7 +78,9 @@ LLVMModuleRef) LLVMDumpModule = llexternal('LLVMDumpModule', [LLVMModuleRef], lltype.Void) +LLVMInt1Type = llexternal('LLVMInt1Type', [], LLVMTypeRef) LLVMInt32Type = llexternal('LLVMInt32Type', [], LLVMTypeRef) +LLVMInt64Type = llexternal('LLVMInt64Type', [], LLVMTypeRef) LLVMFunctionType = llexternal('LLVMFunctionType', [LLVMTypeRef, # return type rffi.CArrayPtr(LLVMTypeRef), # param types @@ -77,6 +91,7 @@ rffi.UINT], # address space LLVMTypeRef) +LLVMTypeOf = llexternal('LLVMTypeOf', [LLVMValueRef], LLVMTypeRef) LLVMConstInt = llexternal('LLVMConstInt', [LLVMTypeRef, # type rffi.ULONGLONG, # value rffi.INT], # flag: is_signed @@ -101,6 +116,11 @@ rffi.CCHARP], # name LLVMBasicBlockRef) +LLVMSetTailCall = llexternal('LLVMSetTailCall', + [LLVMValueRef, # call instruction + rffi.INT], # flag: is_tail + lltype.Void) + LLVMCreateBuilder = llexternal('LLVMCreateBuilder', [], LLVMBuilderRef) LLVMPositionBuilderAtEnd = llexternal('LLVMPositionBuilderAtEnd', [LLVMBuilderRef, # builder @@ -112,6 +132,12 @@ LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef, # builder, LLVMValueRef], # result LLVMValueRef) +LLVMBuildCondBr = llexternal('LLVMBuildCondBr', + [LLVMBuilderRef, # builder + LLVMValueRef, # condition + LLVMBasicBlockRef, # block if true + LLVMBasicBlockRef], # block if false + LLVMValueRef) for _name in ['Add', 'Sub', 'LShr']: globals()['LLVMBuild' + _name] = llexternal('LLVMBuild' + _name, @@ -133,6 +159,32 @@ LLVMValueRef, # value LLVMValueRef], # pointer location LLVMValueRef) +LLVMBuildTrunc = llexternal('LLVMBuildTrunc', + [LLVMBuilderRef, # builder + LLVMValueRef, # value + LLVMTypeRef, # destination type + rffi.CCHARP], # name of result + LLVMValueRef) +LLVMBuildZExt = llexternal('LLVMBuildZExt', + [LLVMBuilderRef, # builder + LLVMValueRef, # value + LLVMTypeRef, # destination type + rffi.CCHARP], # name of result + LLVMValueRef) +LLVMBuildICmp = llexternal('LLVMBuildICmp', + [LLVMBuilderRef, # builder + rffi.INT, # predicate (see LLVMIntPredicate) + LLVMValueRef, # left-hand side + LLVMValueRef, # right-hand side + rffi.CCHARP], # name of result + LLVMValueRef) +LLVMBuildCall = llexternal('LLVMBuildCall', + [LLVMBuilderRef, # builder + LLVMValueRef, # function + rffi.CArrayPtr(LLVMValueRef), # arguments + rffi.UINT, # argument count + rffi.CCHARP], # name of result + LLVMValueRef) LLVMCreateModuleProviderForExistingModule = llexternal( 'LLVMCreateModuleProviderForExistingModule', [LLVMModuleRef], @@ -159,6 +211,9 @@ rffi.INT, # "fast" rffi.CArrayPtr(rffi.CCHARP)], # -> error rffi.INT) +LLVMDisposeExecutionEngine = llexternal('LLVMDisposeExecutionEngine', + [LLVMExecutionEngineRef], + lltype.Void) LLVMRunFunction = llexternal('LLVMRunFunction', [LLVMExecutionEngineRef, Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Sun May 3 21:49:36 2009 @@ -1,5 +1,6 @@ -import sys +import py, sys from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable from pypy.jit.metainterp.history import ConstInt from pypy.jit.backend import model @@ -28,12 +29,14 @@ self.out_args = [] def setup_once(self): + if not we_are_translated(): + teardown_now() self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit") if sys.maxint == 2147483647: self.ty_int = llvm_rffi.LLVMInt32Type() else: self.ty_int = llvm_rffi.LLVMInt64Type() - self.ty_int_ptr = llvm_rffi.LLVMPointerType(self.ty_int, 0) + self.ty_bit = llvm_rffi.LLVMInt1Type() mp = llvm_rffi.LLVMCreateModuleProviderForExistingModule(self.module) ee_out = lltype.malloc(rffi.CArray(llvm_rffi.LLVMExecutionEngineRef), @@ -51,25 +54,35 @@ llvm_rffi.LLVMDisposeMessage(error_out[0]) lltype.free(error_out, flavor='raw') lltype.free(ee_out, flavor='raw') + if not we_are_translated(): + set_teardown_function(self._teardown) + + def _teardown(self): + llvm_rffi.LLVMDisposeExecutionEngine(self.ee) # ------------------------------ # Compilation def compile_operations(self, loop): + self.compiling_loop = loop self._ensure_in_args(len(loop.inputargs)) ty_func = self.get_ty_func(len(loop.inputargs)) func = llvm_rffi.LLVMAddFunction(self.module, "", ty_func) + loop._llvm_func = func self.vars = {} for i in range(len(loop.inputargs)): self.vars[loop.inputargs[i]] = llvm_rffi.LLVMGetParam(func, i) self.builder = llvm_rffi.LLVMCreateBuilder() - self._generate_branch(loop.operations, func) + bb_start = llvm_rffi.LLVMAppendBasicBlock(func, "entry") + self.pending_blocks = [(loop.operations, bb_start)] + while self.pending_blocks: + operations, bb = self.pending_blocks.pop() + self._generate_branch(operations, bb) llvm_rffi.LLVMDisposeBuilder(self.builder) - self.builder = None self.vars = None #... llvm_rffi.LLVMDumpModule(self.module) - loop._llvm_func = func + self.compiling_loop = None def get_ty_func(self, nb_args): try: @@ -99,14 +112,10 @@ while len(self.out_args) < count: self.out_args.append(lltype.malloc(self.RAW_VALUE, flavor='raw')) - def _generate_branch(self, operations, func): - bb = llvm_rffi.LLVMAppendBasicBlock(func, "") - llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb) - # + def _generate_branch(self, operations, basicblock): + llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, basicblock) for op in operations: self._generate_op(op) - # - return bb def _generate_op(self, op): opnum = op.opnum @@ -118,41 +127,107 @@ else: raise MissingOperation(resoperation.opname[opnum]) - def getarg(self, v): + def getintarg(self, v): try: - return self.vars[v] + value_ref = self.vars[v] except KeyError: assert isinstance(v, ConstInt) return self._make_const_int(v.value) + else: + return self._cast_to_int(value_ref) def _make_const_int(self, value): return llvm_rffi.LLVMConstInt(self.ty_int, value, True) - def generate_int_add(self, op): - self.vars[op.result] = llvm_rffi.LLVMBuildAdd(self.builder, - self.getarg(op.args[0]), - self.getarg(op.args[1]), - "") - - def generate_uint_rshift(self, op): - self.vars[op.result] = llvm_rffi.LLVMBuildLShr(self.builder, - self.getarg(op.args[0]), - self.getarg(op.args[1]), - "") + def _cast_to_int(self, value_ref): + ty = llvm_rffi.LLVMTypeOf(value_ref) + if ty == self.ty_int: + return value_ref + elif ty == self.ty_bit: + return llvm_rffi.LLVMBuildZExt(self.builder, value_ref, + self.ty_int, "") + else: + raise AssertionError("type is not an int nor a bit") + + def getbitarg(self, v): + try: + value_ref = self.vars[v] + except KeyError: + assert isinstance(v, ConstInt) + return self._make_const_bit(v.value) + else: + return self._cast_to_bit(value_ref) + + def _make_const_bit(self, value): + assert (value & ~1) == 0, "value is not 0 or 1" + return llvm_rffi.LLVMConstInt(self.ty_bit, value, True) + + def _cast_to_bit(self, value_ref): + ty = llvm_rffi.LLVMTypeOf(value_ref) + if ty == self.ty_bit: + return value_ref + elif ty == self.ty_int: + return llvm_rffi.LLVMBuildTrunc(self.builder, value_ref, + self.ty_bit, "") + else: + raise AssertionError("type is not an int nor a bit") + + for _opname, _llvmname in [('INT_ADD', 'Add'), + ('INT_SUB', 'Sub'), + ('UINT_RSHIFT', 'LShr'), + ]: + exec py.code.Source(''' + def generate_%s(self, op): + self.vars[op.result] = llvm_rffi.LLVMBuild%s( + self.builder, + self.getintarg(op.args[0]), + self.getintarg(op.args[1]), + "") + ''' % (_opname, _llvmname)).compile() - def generate_int_invert(self, op): + def generate_INT_INVERT(self, op): self.vars[op.result] = llvm_rffi.LLVMBuildNot(self.builder, - self.vars[op.args[0]], - "") + self.getintarg(op.args[0]), + "") - def generate_fail(self, op): + def generate_INT_IS_TRUE(self, op): + self.vars[op.result] = llvm_rffi.LLVMBuildICmp(self.builder, + llvm_rffi.Predicate.NE, + self.getintarg(op.args[0]), + self._make_const_int(0), + "") + + def generate_GUARD_TRUE(self, op): + func = self.compiling_loop._llvm_func + bb_on_track = llvm_rffi.LLVMAppendBasicBlock(func, "") + bb_off_track = llvm_rffi.LLVMAppendBasicBlock(func, "") + llvm_rffi.LLVMBuildCondBr(self.builder, self.getbitarg(op.args[0]), + bb_on_track, bb_off_track) + # generate the on-track part first, and the off-track part later + self.pending_blocks.append((op.suboperations, bb_off_track)) + llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_on_track) + + def generate_JUMP(self, op): + args = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), len(op.args), + flavor='raw') + for i in range(len(op.args)): + args[i] = self.getintarg(op.args[i]) + res = llvm_rffi.LLVMBuildCall(self.builder, op.jump_target._llvm_func, + args, len(op.args), "") + llvm_rffi.LLVMBuildRet(self.builder, res) + llvm_rffi.LLVMSetTailCall(res, True) + lltype.free(args, flavor='raw') + + def generate_FAIL(self, op): self._ensure_out_args(len(op.args)) for i in range(len(op.args)): + value_ref = self.vars[op.args[i]] + ty = llvm_rffi.LLVMTypeOf(value_ref) + typtr = llvm_rffi.LLVMPointerType(ty, 0) addr_as_signed = rffi.cast(lltype.Signed, self.out_args[i]) llvmconstint = self._make_const_int(addr_as_signed) - llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint, - self.ty_int_ptr) - llvm_rffi.LLVMBuildStore(self.builder, self.vars[op.args[i]], + llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint, typtr) + llvm_rffi.LLVMBuildStore(self.builder, value_ref, llvmconstptr) i = len(self.fail_ops) self.fail_ops.append(op) @@ -178,6 +253,7 @@ llvm_rffi.LLVMDisposeGenericValue(self.in_args[i]) self.in_args[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO) i += 1 + return self.fail_ops[res] def get_latest_value_int(self, index): return rffi.cast(lltype.Signed, self.out_args[index][0]) @@ -191,7 +267,20 @@ for _key, _value in rop.__dict__.items(): if 'A' <= _key <= 'Z': assert _value not in all_operations - methname = 'generate_' + _key.lower() + methname = 'generate_' + _key if hasattr(LLVMCPU, methname): all_operations[_value] = methname all_operations = unrolling_iterable(all_operations.items()) + +_teardown = None + +def set_teardown_function(fn): + global _teardown + _teardown = fn + +def teardown_now(): + global _teardown + fn = _teardown + _teardown = None + if fn is not None: + fn() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py Sun May 3 21:49:36 2009 @@ -80,19 +80,29 @@ lltype.free(error_out, flavor='raw') lltype.free(ee_out, flavor='raw') - # The arguments needs to be passed as "GenericValue" objects. - args = lltype.malloc(rffi.CArray(LLVMGenericValueRef), 2, flavor='raw') - args[0] = LLVMCreateGenericValueOfInt(ty_int, 100, True) - args[1] = LLVMCreateGenericValueOfInt(ty_int, 42, True) - - # Now let's compile and run! - retval = LLVMRunFunction(ee, f_sum, 2, args) - LLVMDisposeGenericValue(args[1]) - LLVMDisposeGenericValue(args[0]) - lltype.free(args, flavor='raw') - - # The return value is also GenericValue. Let's check it. - ulonglong = LLVMGenericValueToInt(retval, True) - LLVMDisposeGenericValue(retval) - res = rffi.cast(lltype.Signed, ulonglong) - assert res == 142 + try: + # The arguments needs to be passed as "GenericValue" objects. + args = lltype.malloc(rffi.CArray(LLVMGenericValueRef), 2, flavor='raw') + args[0] = LLVMCreateGenericValueOfInt(ty_int, 100, True) + args[1] = LLVMCreateGenericValueOfInt(ty_int, 42, True) + + # Now let's compile and run! + retval = LLVMRunFunction(ee, f_sum, 2, args) + LLVMDisposeGenericValue(args[1]) + LLVMDisposeGenericValue(args[0]) + lltype.free(args, flavor='raw') + + # The return value is also GenericValue. Let's check it. + ulonglong = LLVMGenericValueToInt(retval, True) + LLVMDisposeGenericValue(retval) + res = rffi.cast(lltype.Signed, ulonglong) + assert res == 142 + + finally: + LLVMDisposeExecutionEngine(ee) + + +def test_from_llvm_py_example_3(): + """This test is the same as the previous one. Just tests that we + have freed enough stuff to be able to call it again.""" + test_from_llvm_py_example_2() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Sun May 3 21:49:36 2009 @@ -25,3 +25,28 @@ cpu.execute_operations(loop) assert cpu.get_latest_value_int(0) == (19 >> 3) assert cpu.get_latest_value_int(1) == (~38) + +def test_loop_1(): + v1 = BoxInt(); v2 = BoxInt(); v3 = BoxInt() + v4 = BoxInt(); v5 = BoxInt(); v6 = BoxInt() + loop = TreeLoop('loop_1') + loop.inputargs = [v1, v2, v3] + loop.operations = [ + ResOperation(rop.INT_IS_TRUE, [v1], v4), + ResOperation(rop.GUARD_TRUE, [v4], None), + ResOperation(rop.INT_ADD, [v2, v3], v5), + ResOperation(rop.INT_SUB, [v1, ConstInt(1)], v6), + ResOperation(rop.JUMP, [v6, v2, v5], None), + ] + loop.operations[-1].jump_target = loop + loop.operations[1].suboperations = [ + ResOperation(rop.FAIL, [v3], None), + ] + cpu = LLVMCPU(None) + cpu.setup_once() + cpu.compile_operations(loop) + cpu.set_future_value_int(0, 7) + cpu.set_future_value_int(1, 6) + cpu.set_future_value_int(2, 0) + cpu.execute_operations(loop) + assert cpu.get_latest_value_int(0) == 42 From arigo at codespeak.net Sun May 3 23:04:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 May 2009 23:04:46 +0200 (CEST) Subject: [pypy-svn] r65010 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090503210446.D6BC61684DB@codespeak.net> Author: arigo Date: Sun May 3 23:04:43 2009 New Revision: 65010 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Log: Add some mess with phi nodes instead of doing tail calls. Solves at least in simple cases the issue of loops consuming the stack. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 23:04:43 2009 @@ -68,6 +68,13 @@ SLT = 40 # signed less than SLE = 41 # signed less or equal +class CallConv: + C = 0 + Fast = 8 + Cold = 9 + X86Stdcall = 64 + X86Fastcall = 65 + # ____________________________________________________________ LLVMDisposeMessage = llexternal('LLVMDisposeMessage', [rffi.CCHARP], @@ -106,6 +113,10 @@ rffi.CCHARP, # name LLVMTypeRef], # function type LLVMValueRef) +LLVMSetFunctionCallConv = llexternal('LLVMSetFunctionCallConv', + [LLVMValueRef, # function + rffi.UINT], # new call conv + lltype.Void) LLVMGetParam = llexternal('LLVMGetParam', [LLVMValueRef, # function rffi.UINT], # index @@ -120,18 +131,28 @@ [LLVMValueRef, # call instruction rffi.INT], # flag: is_tail lltype.Void) - +LLVMAddIncoming = llexternal('LLVMAddIncoming', + [LLVMValueRef, # phi node + rffi.CArrayPtr(LLVMValueRef), # incoming values + rffi.CArrayPtr(LLVMBasicBlockRef), # incom.blocks + rffi.UINT], # count + lltype.Void) LLVMCreateBuilder = llexternal('LLVMCreateBuilder', [], LLVMBuilderRef) LLVMPositionBuilderAtEnd = llexternal('LLVMPositionBuilderAtEnd', [LLVMBuilderRef, # builder LLVMBasicBlockRef], # block lltype.Void) +LLVMGetInsertBlock = llexternal('LLVMGetInsertBlock', [LLVMBuilderRef], + LLVMBasicBlockRef) LLVMDisposeBuilder = llexternal('LLVMDisposeBuilder', [LLVMBuilderRef], lltype.Void) LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef, # builder, LLVMValueRef], # result LLVMValueRef) +LLVMBuildBr = llexternal('LLVMBuildBr', [LLVMBuilderRef, # builder, + LLVMBasicBlockRef],# destination block + LLVMValueRef) LLVMBuildCondBr = llexternal('LLVMBuildCondBr', [LLVMBuilderRef, # builder LLVMValueRef, # condition @@ -178,6 +199,11 @@ LLVMValueRef, # right-hand side rffi.CCHARP], # name of result LLVMValueRef) +LLVMBuildPhi = llexternal('LLVMBuildPhi', + [LLVMBuilderRef, # builder + LLVMTypeRef, # type of value + rffi.CCHARP], # name of result + LLVMValueRef) LLVMBuildCall = llexternal('LLVMBuildCall', [LLVMBuilderRef, # builder LLVMValueRef, # function Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Sun May 3 23:04:43 2009 @@ -70,14 +70,45 @@ func = llvm_rffi.LLVMAddFunction(self.module, "", ty_func) loop._llvm_func = func self.vars = {} - for i in range(len(loop.inputargs)): - self.vars[loop.inputargs[i]] = llvm_rffi.LLVMGetParam(func, i) self.builder = llvm_rffi.LLVMCreateBuilder() - bb_start = llvm_rffi.LLVMAppendBasicBlock(func, "entry") - self.pending_blocks = [(loop.operations, bb_start)] + bb_entry = llvm_rffi.LLVMAppendBasicBlock(func, "entry") + bb_start_code = llvm_rffi.LLVMAppendBasicBlock(func, "") + self.bb_start_code = bb_start_code + llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_entry) + llvm_rffi.LLVMBuildBr(self.builder, bb_start_code) + # + llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_start_code) + self.phi_incoming_blocks = [bb_entry] + self.phi_incoming_values = [] + for i in range(len(loop.inputargs)): + phi = llvm_rffi.LLVMBuildPhi(self.builder, self.ty_int, "") + incoming = [llvm_rffi.LLVMGetParam(func, i)] + self.phi_incoming_values.append(incoming) + self.vars[loop.inputargs[i]] = phi + # + self.pending_blocks = [(loop.operations, bb_start_code)] while self.pending_blocks: operations, bb = self.pending_blocks.pop() self._generate_branch(operations, bb) + # + incoming_blocks = lltype.malloc( + rffi.CArray(llvm_rffi.LLVMBasicBlockRef), + len(self.phi_incoming_blocks), flavor='raw') + incoming_values = lltype.malloc( + rffi.CArray(llvm_rffi.LLVMValueRef), + len(self.phi_incoming_blocks), flavor='raw') + for j in range(len(self.phi_incoming_blocks)): + incoming_blocks[j] = self.phi_incoming_blocks[j] + for i in range(len(loop.inputargs)): + phi = self.vars[loop.inputargs[i]] + incoming = self.phi_incoming_values[i] + for j in range(len(self.phi_incoming_blocks)): + incoming_values[j] = incoming[j] + llvm_rffi.LLVMAddIncoming(phi, incoming_values, incoming_blocks, + len(self.phi_incoming_blocks)) + lltype.free(incoming_values, flavor='raw') + lltype.free(incoming_blocks, flavor='raw') + # llvm_rffi.LLVMDisposeBuilder(self.builder) self.vars = None #... @@ -208,15 +239,24 @@ llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_on_track) def generate_JUMP(self, op): - args = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), len(op.args), - flavor='raw') - for i in range(len(op.args)): - args[i] = self.getintarg(op.args[i]) - res = llvm_rffi.LLVMBuildCall(self.builder, op.jump_target._llvm_func, - args, len(op.args), "") - llvm_rffi.LLVMBuildRet(self.builder, res) - llvm_rffi.LLVMSetTailCall(res, True) - lltype.free(args, flavor='raw') + if op.jump_target is self.compiling_loop: + basicblock = llvm_rffi.LLVMGetInsertBlock(self.builder) + self.phi_incoming_blocks.append(basicblock) + for i in range(len(op.args)): + incoming = self.phi_incoming_values[i] + incoming.append(self.getintarg(op.args[i])) + llvm_rffi.LLVMBuildBr(self.builder, self.bb_start_code) + else: + args = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), + len(op.args), flavor='raw') + for i in range(len(op.args)): + args[i] = self.getintarg(op.args[i]) + res = llvm_rffi.LLVMBuildCall(self.builder, + op.jump_target._llvm_func, + args, len(op.args), "") + llvm_rffi.LLVMSetTailCall(res, True) # XXX no effect :-( + llvm_rffi.LLVMBuildRet(self.builder, res) + lltype.free(args, flavor='raw') def generate_FAIL(self, op): self._ensure_out_args(len(op.args)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Sun May 3 23:04:43 2009 @@ -45,8 +45,8 @@ cpu = LLVMCPU(None) cpu.setup_once() cpu.compile_operations(loop) - cpu.set_future_value_int(0, 7) - cpu.set_future_value_int(1, 6) + cpu.set_future_value_int(0, 2**29) + cpu.set_future_value_int(1, 3) cpu.set_future_value_int(2, 0) cpu.execute_operations(loop) - assert cpu.get_latest_value_int(0) == 42 + assert cpu.get_latest_value_int(0) == 3*(2**29) From fijal at codespeak.net Mon May 4 01:18:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 4 May 2009 01:18:27 +0200 (CEST) Subject: [pypy-svn] r65011 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090503231827.1EBB416853F@codespeak.net> Author: fijal Date: Mon May 4 01:18:25 2009 New Revision: 65011 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: didn't mean to check in pdb 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 May 4 01:18:25 2009 @@ -564,8 +564,6 @@ raise AssertionError llinterp = LLInterpreter.current_interpreter try: - import pdb - pdb.set_trace() llres = llinterp.eval_graph(container.graph, llargs) except LLException, lle: llinterp._store_exception(lle) From fijal at codespeak.net Mon May 4 01:19:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 4 May 2009 01:19:26 +0200 (CEST) Subject: [pypy-svn] r65012 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090503231926.61763168548@codespeak.net> Author: fijal Date: Mon May 4 01:19:25 2009 New Revision: 65012 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: simplify handling the guard_index. I *think* in rare cases the previous one might not work, but I didn't encounter one in the wild. Anyway, it's simpler now 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 Mon May 4 01:19:25 2009 @@ -829,7 +829,7 @@ self.mc = oldmc return addr - def generate_failure(self, op, locs, guard_index, exc): + def generate_failure(self, op, locs, exc): pos = self.mc.tell() for i in range(len(locs)): loc = locs[i] @@ -849,6 +849,7 @@ self.generate_exception_handling(eax) self.places_to_patch_framesize.append(self.mc.tell()) self.mc.ADD(esp, imm32(0)) + guard_index = self.cpu.make_guard_index(op) self.mc.MOV(eax, imm(guard_index)) self.mc.RET() 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 May 4 01:19:25 2009 @@ -270,9 +270,6 @@ self._walk_operations(operations) def _walk_operations(self, operations): - fop = operations[-1] - if fop.opnum == rop.FAIL: - self.guard_index = self.assembler.cpu.make_guard_index(fop) i = 0 while i < len(operations): op = operations[i] @@ -638,7 +635,7 @@ def consider_fail(self, op, ignored): # make sure all vars are on stack locs = [self.loc(arg) for arg in op.args] - self.assembler.generate_failure(op, locs, self.guard_index, self.exc) + self.assembler.generate_failure(op, locs, self.exc) self.eventually_free_vars(op.args) def consider_guard_nonvirtualized(self, op, ignored): From benjamin at codespeak.net Mon May 4 01:47:20 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 4 May 2009 01:47:20 +0200 (CEST) Subject: [pypy-svn] r65013 - pypy/branch/pyjitpl5/pypy/module/pypyjit/test Message-ID: <20090503234720.CA9C2168485@codespeak.net> Author: benjamin Date: Mon May 4 01:47:20 2009 New Revision: 65013 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/test/conftest.py Log: use the nifty plugin interface for options Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/test/conftest.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/test/conftest.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/test/conftest.py Mon May 4 01:47:20 2009 @@ -1,9 +1,7 @@ -import py +class PyPyJitTestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypyjit options") + group.addoption("--pypy-c", action="store", default=None, dest="pypy_c", + help="the location of the JIT enabled pypy-c") - -Option = py.test.config.Option - -option = py.test.config.addoptions("ppc options", - Option('--pypy-c', action="store", default=None, - dest="pypy_c", - help="")) +ConftestPlugin = PyPyJitTestPlugin From benjamin at codespeak.net Mon May 4 04:32:25 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Mon, 4 May 2009 04:32:25 +0200 (CEST) Subject: [pypy-svn] r65014 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090504023225.B43BB1684D4@codespeak.net> Author: benjamin Date: Mon May 4 04:32:22 2009 New Revision: 65014 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: this doesn't need to be within the try block 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 Mon May 4 04:32:22 2009 @@ -1163,8 +1163,8 @@ def compile_bridge(self, live_arg_boxes): num_green_args = self.staticdata.num_green_args greenkey = live_arg_boxes[:num_green_args] + glob = self.staticdata.globaldata try: - glob = self.staticdata.globaldata old_loops = glob.compiled_merge_points[greenkey] except KeyError: return From lac at codespeak.net Mon May 4 08:01:23 2009 From: lac at codespeak.net (lac at codespeak.net) Date: Mon, 4 May 2009 08:01:23 +0200 (CEST) Subject: [pypy-svn] r65015 - pypy/dist/pypy/config Message-ID: <20090504060123.4A6F81684CD@codespeak.net> Author: lac Date: Mon May 4 08:01:19 2009 New Revision: 65015 Modified: pypy/dist/pypy/config/translationoption.py Log: fix tiny typo Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Mon May 4 08:01:19 2009 @@ -5,7 +5,7 @@ from pypy.config.config import ConfigError DEFL_INLINE_THRESHOLD = 32.4 # just enough to inline add__Int_Int() -# and just small enough to prevend inlining of some rlist functions. +# and just small enough to prevent inlining of some rlist functions. DEFL_PROF_BASED_INLINE_THRESHOLD = 32.4 DEFL_CLEVER_MALLOC_REMOVAL_INLINE_THRESHOLD = 32.4 From arigo at codespeak.net Mon May 4 12:07:08 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 May 2009 12:07:08 +0200 (CEST) Subject: [pypy-svn] r65016 - pypy/branch/pyjitpl5/pypy/jit/backend/llvm Message-ID: <20090504100708.E5D3416854C@codespeak.net> Author: arigo Date: Mon May 4 12:07:06 2009 New Revision: 65016 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Log: Pointed (indirectly) by antocuni: risk of recursion. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Mon May 4 12:07:06 2009 @@ -278,6 +278,8 @@ def set_future_value_int(self, index, intvalue): assert index < self.in_args_count - 1 + if self.in_args[index]: + llvm_rffi.LLVMDisposeGenericValue(self.in_args[index]) self.in_args[index] = llvm_rffi.LLVMCreateGenericValueOfInt( self.ty_int, intvalue, True) From cfbolz at codespeak.net Mon May 4 13:54:07 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 May 2009 13:54:07 +0200 (CEST) Subject: [pypy-svn] r65019 - pypy/branch/tagged-pointers-framework Message-ID: <20090504115407.F319B1684A7@codespeak.net> Author: cfbolz Date: Mon May 4 13:54:06 2009 New Revision: 65019 Added: pypy/branch/tagged-pointers-framework/ - copied from r65018, pypy/trunk/ Log: A branch to play with supporting tagged pointers with the framework GCs From cfbolz at codespeak.net Mon May 4 13:58:19 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 May 2009 13:58:19 +0200 (CEST) Subject: [pypy-svn] r65020 - pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test Message-ID: <20090504115819.98F671684A7@codespeak.net> Author: cfbolz Date: Mon May 4 13:58:19 2009 New Revision: 65020 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py Log: (failing) tests that I would like to pass Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Mon May 4 13:58:19 2009 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here +from pypy.rlib import rgc def stdout_ignore_ll_functions(msg): @@ -427,7 +428,6 @@ def test_can_move(self): TP = lltype.GcArray(lltype.Float) def func(): - from pypy.rlib import rgc return rgc.can_move(lltype.malloc(TP, 1)) assert self.interpret(func, []) == self.GC_CAN_MOVE @@ -435,7 +435,6 @@ def test_malloc_nonmovable(self): TP = lltype.GcArray(lltype.Char) def func(): - from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP, 3) if a: assert not rgc.can_move(a) @@ -449,7 +448,6 @@ TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) def func(): try: - from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP) rgc.collect() if a: @@ -464,7 +462,6 @@ def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr - from pypy.rlib import rgc def f(): ptr = rgc.resizable_buffer_of_shape(STR, 1) @@ -475,6 +472,36 @@ assert self.interpret(f, []) == 2 + def test_tagged(self): + from pypy.rlib.objectmodel import UnboxedValue + class A(object): + __slots__ = () + def meth(self, x): + raise NotImplementedError + + class B(A): + attrvalue = 66 + def __init__(self, normalint): + self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + + class C(A, UnboxedValue): + __slots__ = 'smallint' + def meth(self, x): + return self.smallint + x + 3 + def fn(n): + if n > 0: + x = B(n) + else: + x = C(n) + rgc.collect() + return x.meth(100) + res = self.interpret(fn, [1000]) + assert res == 1102 + res = self.interpret(fn, [-1000]) + assert res == -897 + class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py Mon May 4 13:58:19 2009 @@ -9,6 +9,7 @@ from pypy.rpython.memory.gc.marksweep import X_CLONE, X_POOL, X_POOL_PTR from pypy.rlib.objectmodel import compute_unique_id from pypy.rlib.debug import ll_assert +from pypy.rlib import rgc from pypy import conftest from pypy.rlib.rstring import StringBuilder @@ -455,7 +456,6 @@ def test_can_move(self): TP = lltype.GcArray(lltype.Float) def func(): - from pypy.rlib import rgc return rgc.can_move(lltype.malloc(TP, 1)) run = self.runner(func) res = run([]) @@ -465,7 +465,6 @@ TP = lltype.GcArray(lltype.Char) def func(): #try: - from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP, 3) rgc.collect() if a: @@ -483,7 +482,6 @@ TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) def func(): try: - from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP) rgc.collect() if a: @@ -499,7 +497,6 @@ def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr - from pypy.rlib import rgc def f(): ptr = rgc.resizable_buffer_of_shape(STR, 2) @@ -528,6 +525,37 @@ res = fn([]) assert res == 'y' + def test_tagged(self): + from pypy.rlib.objectmodel import UnboxedValue + class A(object): + __slots__ = () + def meth(self, x): + raise NotImplementedError + + class B(A): + attrvalue = 66 + def __init__(self, normalint): + self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + + class C(A, UnboxedValue): + __slots__ = 'smallint' + def meth(self, x): + return self.smallint + x + 3 + def fn(n): + if n > 0: + x = B(n) + else: + x = C(n) + rgc.collect() + return x.meth(100) + def func(): + return fn(1000) + fn(-1000) + func = self.runner(func) + res = func([]) + assert res == fn(1000) + fn(-1000) + class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True GC_CANNOT_MALLOC_NONMOVABLE = True @@ -638,7 +666,6 @@ assert res == 22220221 def test_cloning_highlevel(self): - from pypy.rlib import rgc class A: pass class B(A): @@ -672,7 +699,6 @@ assert res == 1 def test_cloning_highlevel_varsize(self): - from pypy.rlib import rgc class A: pass def func(n, dummy): From cfbolz at codespeak.net Mon May 4 13:59:30 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 May 2009 13:59:30 +0200 (CEST) Subject: [pypy-svn] r65021 - in pypy/branch/tagged-pointers-framework/pypy/rpython/memory: . gc gctransform Message-ID: <20090504115930.80CE21684AE@codespeak.net> Author: cfbolz Date: Mon May 4 13:59:29 2009 New Revision: 65021 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/marksweep.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/semispace.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py Log: Refactor things so that there is only one place where it is checked whether a pointed-to object is NULL. This place can later be used for checking tagged pointers as well. Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py Mon May 4 13:59:29 2009 @@ -148,14 +148,17 @@ length = (obj + llmemory.gcarrayofptr_lengthoffset).signed[0] item = obj + llmemory.gcarrayofptr_itemsoffset while length > 0: - callback(item, arg) + if self.points_to_valid_gc_object(item): + callback(item, arg) item += llmemory.gcarrayofptr_singleitemoffset length -= 1 return offsets = self.offsets_to_gc_pointers(typeid) i = 0 while i < len(offsets): - callback(obj + offsets[i], arg) + item = obj + offsets[i] + if self.points_to_valid_gc_object(item): + callback(item, arg) i += 1 if self.has_gcptr_in_varsize(typeid): item = obj + self.varsize_offset_to_variable_part(typeid) @@ -165,12 +168,18 @@ while length > 0: j = 0 while j < len(offsets): - callback(item + offsets[j], arg) + itemobj = item + offsets[j] + if self.points_to_valid_gc_object(itemobj): + callback(itemobj, arg) j += 1 item += itemlength length -= 1 trace._annspecialcase_ = 'specialize:arg(2)' + def points_to_valid_gc_object(self, addr): + pointsto = addr.address[0] + return pointsto != NULL + def debug_check_consistency(self): """To use after a collection. If self.DEBUG is set, this enumerates all roots and traces all objects to check if we didn't @@ -205,8 +214,8 @@ self._debug_record(obj) def _debug_callback2(self, pointer, ignored): obj = pointer.address[0] - if obj: - self._debug_record(obj) + ll_assert(bool(obj), "NULL address from self.trace()") + self._debug_record(obj) def debug_check_object(self, obj): pass Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py Mon May 4 13:59:29 2009 @@ -295,10 +295,9 @@ def _trace_external_obj(self, pointer, obj): addr = pointer.address[0] - if addr != NULL: - newaddr = self.copy(addr) - pointer.address[0] = newaddr - self.write_into_last_generation_obj(obj, newaddr) + newaddr = self.copy(addr) + pointer.address[0] = newaddr + self.write_into_last_generation_obj(obj, newaddr) # ____________________________________________________________ # Implementation of nursery-only collections Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py Mon May 4 13:59:29 2009 @@ -342,11 +342,10 @@ def _mark_obj(self, pointer, ignored): obj = pointer.address[0] - if obj != NULL: - if self.marked(obj): - return - self.mark(obj) - self.to_see.append(obj) + if self.marked(obj): + return + self.mark(obj) + self.to_see.append(obj) def _mark_root_recursively(self, root): self.mark(root.address[0]) Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/marksweep.py Mon May 4 13:59:29 2009 @@ -499,8 +499,7 @@ def _add_reachable(pointer, objects): obj = pointer.address[0] - if obj: - objects.append(obj) + objects.append(obj) _add_reachable = staticmethod(_add_reachable) def statistics(self, index): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/semispace.py Mon May 4 13:59:29 2009 @@ -331,8 +331,7 @@ self.trace(obj, self._trace_copy, None) def _trace_copy(self, pointer, ignored): - if pointer.address[0] != NULL: - pointer.address[0] = self.copy(pointer.address[0]) + pointer.address[0] = self.copy(pointer.address[0]) def surviving(self, obj): # To use during a collection. Check if the object is currently @@ -451,8 +450,7 @@ return scan def _append_if_nonnull(pointer, stack): - if pointer.address[0] != NULL: - stack.append(pointer.address[0]) + stack.append(pointer.address[0]) _append_if_nonnull = staticmethod(_append_if_nonnull) def _finalization_state(self, obj): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py Mon May 4 13:59:29 2009 @@ -909,7 +909,7 @@ addr = gcdata.root_stack_base end = gcdata.root_stack_top while addr != end: - if addr.address[0] != llmemory.NULL: + if self.gc.points_to_valid_gc_object(addr): collect_stack_root(gc, addr) addr += sizeofaddr if self.collect_stacks_from_other_threads is not None: Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py Mon May 4 13:59:29 2009 @@ -141,15 +141,15 @@ gc = gcheap.gc if collect_static_in_prebuilt_gc: for addrofaddr in gcheap.constantroots: - if addrofaddr.address[0]: + if self.gcheap.gc.points_to_valid_gc_object(addrofaddr): collect_static_in_prebuilt_gc(gc, addrofaddr) if collect_static_in_prebuilt_nongc: for addrofaddr in gcheap.constantrootsnongc: - if addrofaddr.address[0]: + if self.gcheap.gc.points_to_valid_gc_object(addrofaddr): collect_static_in_prebuilt_nongc(gc, addrofaddr) if collect_stack_root: for addrofaddr in gcheap.llinterp.find_roots(): - if addrofaddr.address[0]: + if self.gcheap.gc.points_to_valid_gc_object(addrofaddr): collect_stack_root(gc, addrofaddr) def _walk_prebuilt_gc(self, collect): # debugging only! not RPython From antocuni at codespeak.net Mon May 4 14:40:55 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 14:40:55 +0200 (CEST) Subject: [pypy-svn] r65022 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli jit/backend/cli/test jit/backend/minimal jit/backend/test translator/cli/src Message-ID: <20090504124055.0B1EB1684F0@codespeak.net> Author: antocuni Date: Mon May 4 14:40:54 2009 New Revision: 65022 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/ pypy/branch/pyjitpl5/pypy/jit/backend/cli/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/cli/methodfactory.py - copied unchanged from r61964, pypy/branch/oo-jit/pypy/jit/codegen/cli/methodfactory.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Log: first version of the cli jit backend. So far, it knows only about int_lshift and fail operations :-) Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/__init__.py ============================================================================== Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 14:40:54 2009 @@ -0,0 +1,163 @@ +from pypy.tool.pairtype import extendabletype +from pypy.rpython.ootypesystem import ootype +from pypy.translator.cli import dotnet +from pypy.translator.cli.dotnet import CLR +from pypy.jit.metainterp import history +from pypy.jit.metainterp.history import AbstractValue, Const +from pypy.jit.metainterp.resoperation import rop, opname +from pypy.jit.backend.cli.methodfactory import get_method_wrapper + +System = CLR.System +OpCodes = System.Reflection.Emit.OpCodes +LoopDelegate = CLR.pypy.runtime.LoopDelegate +InputArgs = CLR.pypy.runtime.InputArgs + +cVoid = ootype.nullruntimeclass + + +class __extend__(AbstractValue): + __metaclass__ = extendabletype + + def getCliType(self): + if self.type == history.INT: + return dotnet.typeof(System.Int32) + elif self.type == history.OBJ: + return dotnet.typeof(System.Object) + else: + assert False, 'Unknown type: %s' % self.type + + def load(self, meth): + v = meth.var_for_box(self) + meth.il.Emit(OpCodes.Ldloc, v) + + def store(self, meth): + v = meth.var_for_box(self) + meth.il.Emit(OpCodes.Stloc, v) + + +class __extend__(Const): + __metaclass__ = extendabletype + + def load(self, meth): + raise NotImplementedError + + def store(self, meth): + assert False, 'cannot store() to Constant' + + +class MethodArgument(AbstractValue): + def __init__(self, index, cliType): + self.index = index + self.cliType = cliType + + def getCliType(self): + return self.cliType + + def load(self, meth): + if self.index == 0: + meth.il.Emit(OpCodes.Ldarg_0) + elif self.index == 1: + meth.il.Emit(OpCodes.Ldarg_1) + elif self.index == 2: + meth.il.Emit(OpCodes.Ldarg_2) + elif self.index == 3: + meth.il.Emit(OpCodes.Ldarg_3) + else: + meth.il.Emit(OpCodes.Ldarg, self.index) + + def store(self, meth): + meth.il.Emit(OpCodes.Starg, self.index) + + def __repr__(self): + return "MethodArgument(%d)" % self.index + + +class Method(object): + + def __init__(self, cpu, name, loop): + self.cpu = cpu + self.name = name + self.loop = loop + self.boxes = {} # box --> local var + self.meth_wrapper = self._get_meth_wrapper() + self.il = self.meth_wrapper.get_il_generator() + self.av_consts = MethodArgument(0, System.Type.GetType("System.Object[]")) + self.av_inputargs = MethodArgument(1, dotnet.typeof(InputArgs)) + self.emit_load_inputargs() + self.emit_operations() + self.emit_end() + delegatetype = dotnet.typeof(LoopDelegate) + consts = dotnet.new_array(System.Object, 0) + self.func = self.meth_wrapper.create_delegate(delegatetype, consts) + + + def _get_meth_wrapper(self): + restype = dotnet.class2type(cVoid) + args = self._get_args_array([dotnet.typeof(InputArgs)]) + return get_method_wrapper(self.name, restype, args) + + def _get_args_array(self, arglist): + array = dotnet.new_array(System.Type, len(arglist)+1) + array[0] = System.Type.GetType("System.Object[]") + for i in range(len(arglist)): + array[i+1] = arglist[i] + return array + + def var_for_box(self, box): + try: + return self.boxes[box] + except KeyError: + v = self.il.DeclareLocal(box.getCliType()) + self.boxes[box] = v + return v + + def get_inputarg_field(self, type): + t = dotnet.typeof(InputArgs) + if type == history.INT: + fieldname = 'ints' + elif type == history.OBJ: + fieldname = 'objs' + else: + assert False, 'Unknown type %s' % type + return t.GetField(fieldname) + + def load_inputarg(self, i, type, clitype): + field = self.get_inputarg_field(type) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldfld, field) + self.il.Emit(OpCodes.Ldc_I4, i) + self.il.Emit(OpCodes.Ldelem, clitype) + + def store_inputarg(self, i, type, clitype, valuebox): + field = self.get_inputarg_field(type) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldfld, field) + self.il.Emit(OpCodes.Ldc_I4, i) + valuebox.load(self) + self.il.Emit(OpCodes.Stelem, clitype) + + def emit_load_inputargs(self): + i = 0 + for box in self.loop.inputargs: + self.load_inputarg(i, box.type, box.getCliType()) + box.store(self) + i+=1 + + def emit_operations(self): + for op in self.loop.operations: + if op.opnum == rop.INT_LSHIFT: + for box in op.args: + box.load(self) + self.il.Emit(OpCodes.Shl) + op.result.store(self) + elif op.opnum == rop.FAIL: + i = 0 + for box in op.args: + self.store_inputarg(i, box.type, + box.getCliType(), box) + self.il.Emit(OpCodes.Ret) + else: + assert False, 'TODO' + + def emit_end(self): + self.il.Emit(OpCodes.Ret) Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 4 14:40:54 2009 @@ -0,0 +1,81 @@ +from pypy.rpython.ootypesystem import ootype +from pypy.jit.metainterp.history import AbstractDescr, AbstractMethDescr +from pypy.jit.metainterp.history import Box, BoxInt, BoxObj +from pypy.jit.metainterp import executor +from pypy.jit.metainterp.resoperation import rop, opname +from pypy.jit.backend import model +from pypy.jit.backend.minimal.runner import cached_method +from pypy.jit.backend.cli.method import Method +from pypy.translator.cli import dotnet +from pypy.translator.cli.dotnet import CLR + +System = CLR.System +InputArgs = CLR.pypy.runtime.InputArgs + + +class CliCPU(model.AbstractCPU): + + is_oo = True + + def __init__(self, rtyper, stats, translate_support_code=False, + mixlevelann=None): + self.rtyper = rtyper + if rtyper: + assert rtyper.type_system.name == "ootypesystem" + self.stats = stats + self.translate_support_code = translate_support_code + self.inputargs = InputArgs() + + @cached_method('_callcache') + def calldescrof(self, FUNC, ARGS, RESULT): + return StaticMethDescr(FUNC, ARGS, RESULT) + + # ---------------------- + + def compile_operations(self, loop): + meth = Method(self, 'loop', loop) + loop._cli_meth = meth + + def execute_operations(self, loop): + loop._cli_meth.func(self.inputargs) + + def set_future_value_int(self, index, intvalue): + self.inputargs.ints[index] = intvalue + + def set_future_value_obj(self, index, objvalue): + self.inputargs.objs[index] = objvalue + + def get_latest_value_int(self, index): + return self.inputargs.ints[index] + + def get_latest_value_obj(self, index): + return self.inputargs.objs[index] + + # ---------------------- + + def do_call(self, args, calldescr): + assert isinstance(calldescr, StaticMethDescr) + funcbox, args = args[0], args[1:] + return calldescr.callfunc(funcbox, args) + + +# ---------------------------------------------------------------------- + +class StaticMethDescr(AbstractDescr): + + def __init__(self, FUNC, ARGS, RESULT): + from pypy.jit.backend.llgraph.runner import boxresult, make_getargs + getargs = make_getargs(FUNC.ARGS) + def callfunc(funcbox, argboxes): + funcobj = ootype.cast_from_object(FUNC, funcbox.getobj()) + funcargs = getargs(argboxes) + res = funcobj(*funcargs) + if RESULT is not ootype.Void: + return boxresult(RESULT, res) + self.callfunc = callfunc + + +CPU = CliCPU + +import pypy.jit.metainterp.executor +pypy.jit.metainterp.executor.make_execute_list(CPU) Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Mon May 4 14:40:54 2009 @@ -0,0 +1,36 @@ +import py +from pypy.jit.backend.cli.runner import CliCPU +from pypy.jit.backend.test.runner import OOtypeBackendTest + +class FakeStats(object): + pass + +# ____________________________________________________________ + +class CliJitMixin(object): + + typesystem = 'ootype' + CPUClass = CliCPU + + # for the individual tests see + # ====> ../../test/runner.py + + def setup_class(cls): + cls.cpu = cls.CPUClass(rtyper=None, stats=FakeStats()) + + def _skip(self): + py.test.skip("not supported in non-translated version") + + test_passing_guards = _skip # GUARD_CLASS + test_failing_guards = _skip # GUARD_CLASS + + +class TestRunner(CliJitMixin, OOtypeBackendTest): + + def skip(self): + py.test.skip('in-progress') + + test_uint_rshift = skip + test_binary_operations = skip + test_unary_operations = skip + test_ovf_operations = skip Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Mon May 4 14:40:54 2009 @@ -678,20 +678,6 @@ self.errbox = errbox -class StaticMethDescr(AbstractDescr): - - def __init__(self, FUNC, ARGS, RESULT): - from pypy.jit.backend.llgraph.runner import boxresult, make_getargs - getargs = make_getargs(FUNC.ARGS) - def callfunc(funcbox, argboxes): - funcobj = ootype.cast_from_object(FUNC, funcbox.getobj()) - funcargs = getargs(argboxes) - res = funcobj(*funcargs) - if RESULT is not ootype.Void: - return boxresult(RESULT, res) - self.callfunc = callfunc - - class MethDescr(AbstractMethDescr): callmeth = None def __init__(self, SELFTYPE, methname): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Mon May 4 14:40:54 2009 @@ -346,11 +346,11 @@ class OOtypeBackendTest(BaseBackendTest): type_system = 'ootype' - Ptr = lambda x: x + Ptr = staticmethod(lambda x: x) FuncType = ootype.StaticMethod malloc = staticmethod(ootype.new) nullptr = staticmethod(ootype.null) @classmethod def get_funcbox(cls, cpu, func_ptr): - return ootype.cast_to_object(func_ptr) + return BoxObj(ootype.cast_to_object(func_ptr)) Modified: pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Mon May 4 14:40:54 2009 @@ -109,6 +109,8 @@ namespace pypy.runtime { + public delegate void LoopDelegate(InputArgs args); + public class InputArgs { public int[] ints = new int[32]; public float[] floats = new float[32]; @@ -134,6 +136,7 @@ } } + /* public delegate uint FlexSwitchCase(uint block, InputArgs args); // XXX: there is a lot of code duplication between the next three classes, @@ -268,6 +271,8 @@ } } + */ + public class AutoSaveAssembly { private AssemblyBuilder assembly; From antocuni at codespeak.net Mon May 4 16:10:48 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 16:10:48 +0200 (CEST) Subject: [pypy-svn] r65023 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090504141048.1ABED16801E@codespeak.net> Author: antocuni Date: Mon May 4 16:10:47 2009 New Revision: 65023 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Log: automatically build various emit_op_* based on the definition in translator/cli/opcodes.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 16:10:47 2009 @@ -1,7 +1,9 @@ +import py from pypy.tool.pairtype import extendabletype from pypy.rpython.ootypesystem import ootype from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR +from pypy.translator.cli import opcodes from pypy.jit.metainterp import history from pypy.jit.metainterp.history import AbstractValue, Const from pypy.jit.metainterp.resoperation import rop, opname @@ -74,6 +76,8 @@ class Method(object): + operations = [] # overwritten at the end of the module + def __init__(self, cpu, name, loop): self.cpu = cpu self.name = name @@ -145,19 +149,146 @@ def emit_operations(self): for op in self.loop.operations: - if op.opnum == rop.INT_LSHIFT: - for box in op.args: - box.load(self) - self.il.Emit(OpCodes.Shl) - op.result.store(self) - elif op.opnum == rop.FAIL: - i = 0 - for box in op.args: - self.store_inputarg(i, box.type, - box.getCliType(), box) - self.il.Emit(OpCodes.Ret) - else: - assert False, 'TODO' + func = self.operations[op.opnum] + assert func is not None + func(self, op) def emit_end(self): self.il.Emit(OpCodes.Ret) + + # ----------------------------- + + def push_all_args(self, op): + for box in op.args: + box.load(self) + + def store_result(self, op): + op.result.store(self) + + def emit_op_fail(self, op): + i = 0 + for box in op.args: + self.store_inputarg(i, box.type, box.getCliType(), box) + i+=1 + self.il.Emit(OpCodes.Ret) + + def not_implemented(self, op): + raise NotImplementedError + + emit_op_guard_value = not_implemented + emit_op_cast_int_to_ptr = not_implemented + emit_op_guard_nonvirtualized = not_implemented + emit_op_setarrayitem_gc = not_implemented + emit_op_guard_false = not_implemented + emit_op_unicodelen = not_implemented + emit_op_jump = not_implemented + emit_op_setfield_raw = not_implemented + emit_op_cast_ptr_to_int = not_implemented + emit_op_guard_no_exception = not_implemented + emit_op_newunicode = not_implemented + emit_op_new_array = not_implemented + emit_op_unicodegetitem = not_implemented + emit_op_strgetitem = not_implemented + emit_op_getfield_raw = not_implemented + emit_op_setfield_gc = not_implemented + emit_op_oosend_pure = not_implemented + emit_op_getarrayitem_gc_pure = not_implemented + emit_op_arraylen_gc = not_implemented + emit_op_guard_true = not_implemented + emit_op_unicodesetitem = not_implemented + emit_op_getfield_raw_pure = not_implemented + emit_op_new_with_vtable = not_implemented + emit_op_getfield_gc_pure = not_implemented + emit_op_guard_class = not_implemented + emit_op_getarrayitem_gc = not_implemented + emit_op_getfield_gc = not_implemented + emit_op_call_pure = not_implemented + emit_op_strlen = not_implemented + emit_op_newstr = not_implemented + emit_op_guard_exception = not_implemented + emit_op_call = not_implemented + emit_op_strsetitem = not_implemented + + +# -------------------------------------------------------------------- + +# the follwing functions automatically build the various emit_op_* +# operations based on the definitions in translator/cli/opcodes.py + +def make_operation_list(): + operations = [None] * (rop._LAST+1) + for key, value in rop.__dict__.items(): + key = key.lower() + if key.startswith('_'): + continue + methname = 'emit_op_%s' % key + if hasattr(Method, methname): + func = getattr(Method, methname).im_func + else: + instrlist = opcodes.opcodes[key] + func = render_op(methname, instrlist) + operations[value] = func + return operations + +def render_op(methname, instrlist): + lines = [] + for instr in instrlist: + if instr == opcodes.PushAllArgs: + lines.append('self.push_all_args(op)') + elif instr == opcodes.StoreResult: + lines.append('self.store_result(op)') + else: + if not isinstance(instr, str): + print 'WARNING: unknown instruction %s' % instr + return + + if instr.startswith('call '): + signature = instr[len('call '):] + renderCall(lines, signature) + else: + attrname = opcode2attrname(instr) + lines.append('self.il.Emit(OpCodes.%s)' % attrname) + body = py.code.Source('\n'.join(lines)) + src = body.putaround('def %s(self, op):' % methname) + dic = {'OpCodes': OpCodes, + 'System': System, + 'dotnet': dotnet} + exec src.compile() in dic + return dic[methname] + +def opcode2attrname(opcode): + if opcode == 'ldc.r8 0': + return 'Ldc_R8, 0' # XXX this is a hack + if opcode == 'ldc.i8 0': + return 'Ldc_I8, 0' # XXX this is a hack + parts = map(str.capitalize, opcode.split('.')) + return '_'.join(parts) + +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 = ['dotnet.typeof(%s)' % p for p in params] + + body.append("t = System.Type.GetType('%s')" % typename) + body.append("params = dotnet.init_array(System.Type, %s)" % ', '.join(params)) + body.append("methinfo = t.GetMethod('%s', params)" % methname) + body.append("self.il.Emit(OpCodes.Call, methinfo)") + +Method.operations = make_operation_list() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Mon May 4 16:10:47 2009 @@ -30,7 +30,4 @@ def skip(self): py.test.skip('in-progress') - test_uint_rshift = skip - test_binary_operations = skip - test_unary_operations = skip test_ovf_operations = skip From arigo at codespeak.net Mon May 4 17:18:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 May 2009 17:18:30 +0200 (CEST) Subject: [pypy-svn] r65024 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090504151830.A5609168473@codespeak.net> Author: arigo Date: Mon May 4 17:18:29 2009 New Revision: 65024 Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Log: Revert the phi node trick, and start writing a version of execute_operations() that is much simpler, not involing the tricky LLVMRunFunction(). Also generate a helper function and a main function, in preparation for tail-call optimization (not implemented yet). Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c Mon May 4 17:18:29 2009 @@ -2,11 +2,13 @@ #include "llvm-c/Analysis.h" #include "llvm-c/Transforms/Scalar.h" #include "llvm-c/ExecutionEngine.h" +#include "demo2.h" /* The following list of functions seems to be necessary to force the * functions to be included in pypy_cache_llvm.so. The list is never * used. Actually, any single function seems to be enough... */ void* llvm_c_functions[] = { - (void*) LLVMModuleCreateWithName + (void*) LLVMModuleCreateWithName, + (void*) _LLVM_EE_getPointerToFunction }; Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp Mon May 4 17:18:29 2009 @@ -0,0 +1,16 @@ +/* LLVM includes */ +#include "llvm-c/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "demo2.h" + +using namespace llvm; + + +/* Missing pieces of the C interface... + */ +void *_LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, + LLVMValueRef F) +{ + return unwrap(EE)->getPointerToFunction(unwrap(F)); +} Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h Mon May 4 17:18:29 2009 @@ -0,0 +1,10 @@ +#ifdef __cplusplus +extern "C" { +#endif + +void* _LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, + LLVMValueRef F); + +#ifdef __cplusplus +} +#endif Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Mon May 4 17:18:29 2009 @@ -13,9 +13,11 @@ dirname = os.path.join(cachename, 'libs') libname = os.path.join(dirname, 'pypy_cache_llvm.so') cname = os.path.join(os.path.dirname(__file__), 'demo1.c') +cppname = os.path.join(os.path.dirname(__file__), 'demo2.cpp') -if not os.path.isfile(libname) or (os.path.getmtime(cname) > - os.path.getmtime(libname)): +if (not os.path.isfile(libname) or + os.path.getmtime(cname) > os.path.getmtime(libname) or + os.path.getmtime(cppname) > os.path.getmtime(libname)): if not os.path.isdir(dirname): if not os.path.isdir(cachename): os.mkdir(cachename) @@ -27,9 +29,11 @@ if err: raise Exception("gcc command failed") - oname = os.path.join(dirname, 'demo1.o') - do("gcc -c '%s' -o '%s'" % (cname, oname)) - do("g++ -shared '%s' -o '%s'" % (oname, libname) + + o1name = os.path.join(dirname, 'demo1.o') + o2name = os.path.join(dirname, 'demo2.o') + do("gcc -c '%s' -o '%s'" % (cname, o1name)) + do("g++ -c '%s' -o '%s' `%s --cppflags`" % (cppname, o2name, llvm_config)) + do("g++ -shared '%s' '%s' -o '%s'" % (o1name, o2name, libname) + " `%s --cflags --ldflags --libs jit engine`" % llvm_config) compilation_info = ExternalCompilationInfo( @@ -39,10 +43,21 @@ # ____________________________________________________________ +Debug = False + def llexternal(name, args, result, **kwds): - return rffi.llexternal(name, args, result, - compilation_info=compilation_info, - **kwds) + ll = rffi.llexternal(name, args, result, + compilation_info=compilation_info, + **kwds) + if Debug: + def func(*args): + print name + res = ll(*args) + print '\t->', res + return res + return func + else: + return ll def opaqueptr(name): return rffi.VOIDP # lltype.Ptr(rffi.COpaque(name)) @@ -86,6 +101,7 @@ LLVMDumpModule = llexternal('LLVMDumpModule', [LLVMModuleRef], lltype.Void) LLVMInt1Type = llexternal('LLVMInt1Type', [], LLVMTypeRef) +LLVMInt8Type = llexternal('LLVMInt8Type', [], LLVMTypeRef) LLVMInt32Type = llexternal('LLVMInt32Type', [], LLVMTypeRef) LLVMInt64Type = llexternal('LLVMInt64Type', [], LLVMTypeRef) LLVMFunctionType = llexternal('LLVMFunctionType', @@ -127,6 +143,10 @@ rffi.CCHARP], # name LLVMBasicBlockRef) +LLVMSetInstructionCallConv = llexternal('LLVMSetInstructionCallConv', + [LLVMValueRef, # call instruction + rffi.UINT], # new call conv + lltype.Void) LLVMSetTailCall = llexternal('LLVMSetTailCall', [LLVMValueRef, # call instruction rffi.INT], # flag: is_tail @@ -175,6 +195,11 @@ rffi.CCHARP], # name of result LLVMValueRef) +LLVMBuildLoad = llexternal('LLVMBuildLoad', + [LLVMBuilderRef, # builder + LLVMValueRef, # pointer location + rffi.CCHARP], # name of result + LLVMValueRef) LLVMBuildStore = llexternal('LLVMBuildStore', [LLVMBuilderRef, # builder LLVMValueRef, # value @@ -192,6 +217,12 @@ LLVMTypeRef, # destination type rffi.CCHARP], # name of result LLVMValueRef) +LLVMBuildBitCast = llexternal('LLVMBuildBitCast', + [LLVMBuilderRef, # builder + LLVMValueRef, # value + LLVMTypeRef, # destination type + rffi.CCHARP], # name of result + LLVMValueRef) LLVMBuildICmp = llexternal('LLVMBuildICmp', [LLVMBuilderRef, # builder rffi.INT, # predicate (see LLVMIntPredicate) @@ -247,3 +278,8 @@ rffi.UINT, # num args rffi.CArrayPtr(LLVMGenericValueRef)], # args LLVMGenericValueRef) # return value + +LLVM_EE_getPointerToFunction = llexternal('_LLVM_EE_getPointerToFunction', + [LLVMExecutionEngineRef, + LLVMValueRef], # function + rffi.VOIDP) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Mon May 4 17:18:29 2009 @@ -14,8 +14,9 @@ class LLVMCPU(model.AbstractCPU): - ARRAY_OF_VALUE_REFS = rffi.CArray(llvm_rffi.LLVMGenericValueRef) RAW_VALUE = rffi.CFixedArray(rffi.ULONGLONG, 1) + SIGNED_VALUE = rffi.CFixedArray(lltype.Signed, 1) + STUB_FUNC = lltype.FuncType([rffi.VOIDP], lltype.Signed) def __init__(self, rtyper, stats=None, translate_support_code=False, annmixlevel=None): @@ -23,10 +24,8 @@ self.translate_support_code = translate_support_code self.ty_funcs = {} self.fail_ops = [] - self.in_args_count = 0 - self.in_args = lltype.malloc(self.ARRAY_OF_VALUE_REFS, 0, - flavor='raw') - self.out_args = [] + self.in_out_args = [] + self.entry_stubs = {} def setup_once(self): if not we_are_translated(): @@ -37,7 +36,16 @@ else: self.ty_int = llvm_rffi.LLVMInt64Type() self.ty_bit = llvm_rffi.LLVMInt1Type() - + self.ty_char = llvm_rffi.LLVMInt8Type() + self.ty_charp = llvm_rffi.LLVMPointerType(self.ty_char, 0) + # + arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef), 1, + flavor='raw') + arglist[0] = self.ty_charp + self.ty_stub_func = llvm_rffi.LLVMFunctionType(self.ty_int, arglist, + 1, False) + lltype.free(arglist, flavor='raw') + # mp = llvm_rffi.LLVMCreateModuleProviderForExistingModule(self.module) ee_out = lltype.malloc(rffi.CArray(llvm_rffi.LLVMExecutionEngineRef), 1, flavor='raw') @@ -68,53 +76,66 @@ self._ensure_in_args(len(loop.inputargs)) ty_func = self.get_ty_func(len(loop.inputargs)) func = llvm_rffi.LLVMAddFunction(self.module, "", ty_func) + llvm_rffi.LLVMSetFunctionCallConv(func, llvm_rffi.CallConv.Fast) loop._llvm_func = func self.vars = {} - self.builder = llvm_rffi.LLVMCreateBuilder() - bb_entry = llvm_rffi.LLVMAppendBasicBlock(func, "entry") - bb_start_code = llvm_rffi.LLVMAppendBasicBlock(func, "") - self.bb_start_code = bb_start_code - llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_entry) - llvm_rffi.LLVMBuildBr(self.builder, bb_start_code) - # - llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_start_code) - self.phi_incoming_blocks = [bb_entry] - self.phi_incoming_values = [] for i in range(len(loop.inputargs)): - phi = llvm_rffi.LLVMBuildPhi(self.builder, self.ty_int, "") - incoming = [llvm_rffi.LLVMGetParam(func, i)] - self.phi_incoming_values.append(incoming) - self.vars[loop.inputargs[i]] = phi - # - self.pending_blocks = [(loop.operations, bb_start_code)] + self.vars[loop.inputargs[i]] = llvm_rffi.LLVMGetParam(func, i) + self.builder = llvm_rffi.LLVMCreateBuilder() + bb_start = llvm_rffi.LLVMAppendBasicBlock(func, "entry") + self.pending_blocks = [(loop.operations, bb_start)] while self.pending_blocks: operations, bb = self.pending_blocks.pop() self._generate_branch(operations, bb) - # - incoming_blocks = lltype.malloc( - rffi.CArray(llvm_rffi.LLVMBasicBlockRef), - len(self.phi_incoming_blocks), flavor='raw') - incoming_values = lltype.malloc( - rffi.CArray(llvm_rffi.LLVMValueRef), - len(self.phi_incoming_blocks), flavor='raw') - for j in range(len(self.phi_incoming_blocks)): - incoming_blocks[j] = self.phi_incoming_blocks[j] - for i in range(len(loop.inputargs)): - phi = self.vars[loop.inputargs[i]] - incoming = self.phi_incoming_values[i] - for j in range(len(self.phi_incoming_blocks)): - incoming_values[j] = incoming[j] - llvm_rffi.LLVMAddIncoming(phi, incoming_values, incoming_blocks, - len(self.phi_incoming_blocks)) - lltype.free(incoming_values, flavor='raw') - lltype.free(incoming_blocks, flavor='raw') - # llvm_rffi.LLVMDisposeBuilder(self.builder) self.vars = None - #... + # + loop._llvm_func_addr = llvm_rffi.LLVM_EE_getPointerToFunction( + self.ee, loop._llvm_func) + if not we_are_translated(): + print '--- function is at %r ---' % (loop._llvm_func_addr,) + # + loop._llvm_entry_stub = self._get_entry_stub(loop) llvm_rffi.LLVMDumpModule(self.module) self.compiling_loop = None + def _get_entry_stub(self, loop): + key = len(loop.inputargs) + try: + stub = self.entry_stubs[key] + except KeyError: + stub = self.entry_stubs[key] = self._build_entry_stub(key) + return stub + + def _build_entry_stub(self, nb_args): + stubfunc = llvm_rffi.LLVMAddFunction(self.module, "stub", + self.ty_stub_func) + basicblock = llvm_rffi.LLVMAppendBasicBlock(stubfunc, "entry") + builder = llvm_rffi.LLVMCreateBuilder() + llvm_rffi.LLVMPositionBuilderAtEnd(builder, basicblock) + args = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), nb_args, + flavor='raw') + for i in range(nb_args): + ty_int_ptr = llvm_rffi.LLVMPointerType(self.ty_int, 0) + addr_as_signed = rffi.cast(lltype.Signed, self.in_out_args[i]) + llvmconstint = self._make_const_int(addr_as_signed) + llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint, ty_int_ptr) + args[i] = llvm_rffi.LLVMBuildLoad(builder, llvmconstptr, "") + # + realtype = llvm_rffi.LLVMPointerType(self.get_ty_func(nb_args), 0) + realfunc = llvm_rffi.LLVMGetParam(stubfunc, 0) + realfunc = llvm_rffi.LLVMBuildBitCast(builder, realfunc, realtype, "") + res = llvm_rffi.LLVMBuildCall(builder, realfunc, args, nb_args, "") + llvm_rffi.LLVMSetInstructionCallConv(res, llvm_rffi.CallConv.Fast) + lltype.free(args, flavor='raw') + llvm_rffi.LLVMBuildRet(builder, res) + llvm_rffi.LLVMDisposeBuilder(builder) + # + stub = llvm_rffi.LLVM_EE_getPointerToFunction(self.ee, stubfunc) + if not we_are_translated(): + print '--- stub is at %r ---' % (stub,) + return rffi.cast(lltype.Ptr(self.STUB_FUNC), stub) + def get_ty_func(self, nb_args): try: return self.ty_funcs[nb_args] @@ -130,18 +151,10 @@ return ty_func def _ensure_in_args(self, count): - if self.in_args_count <= count: - count = (count + 8) & ~7 # increment by at least one - new = lltype.malloc(self.ARRAY_OF_VALUE_REFS, count, flavor='raw') - lltype.free(self.in_args, flavor='raw') - for i in range(count): - new[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO) - self.in_args = new - self.in_args_count = count - - def _ensure_out_args(self, count): - while len(self.out_args) < count: - self.out_args.append(lltype.malloc(self.RAW_VALUE, flavor='raw')) + while len(self.in_out_args) < count: + self.in_out_args.append(lltype.malloc(self.RAW_VALUE, flavor='raw')) + + _ensure_out_args = _ensure_in_args def _generate_branch(self, operations, basicblock): llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, basicblock) @@ -239,24 +252,16 @@ llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_on_track) def generate_JUMP(self, op): - if op.jump_target is self.compiling_loop: - basicblock = llvm_rffi.LLVMGetInsertBlock(self.builder) - self.phi_incoming_blocks.append(basicblock) - for i in range(len(op.args)): - incoming = self.phi_incoming_values[i] - incoming.append(self.getintarg(op.args[i])) - llvm_rffi.LLVMBuildBr(self.builder, self.bb_start_code) - else: - args = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), - len(op.args), flavor='raw') - for i in range(len(op.args)): - args[i] = self.getintarg(op.args[i]) - res = llvm_rffi.LLVMBuildCall(self.builder, - op.jump_target._llvm_func, - args, len(op.args), "") - llvm_rffi.LLVMSetTailCall(res, True) # XXX no effect :-( - llvm_rffi.LLVMBuildRet(self.builder, res) - lltype.free(args, flavor='raw') + args = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), len(op.args), + flavor='raw') + for i in range(len(op.args)): + args[i] = self.getintarg(op.args[i]) + res = llvm_rffi.LLVMBuildCall(self.builder, op.jump_target._llvm_func, + args, len(op.args), "") + llvm_rffi.LLVMSetInstructionCallConv(res, llvm_rffi.CallConv.Fast) + llvm_rffi.LLVMSetTailCall(res, True) + llvm_rffi.LLVMBuildRet(self.builder, res) + lltype.free(args, flavor='raw') def generate_FAIL(self, op): self._ensure_out_args(len(op.args)) @@ -264,7 +269,7 @@ value_ref = self.vars[op.args[i]] ty = llvm_rffi.LLVMTypeOf(value_ref) typtr = llvm_rffi.LLVMPointerType(ty, 0) - addr_as_signed = rffi.cast(lltype.Signed, self.out_args[i]) + addr_as_signed = rffi.cast(lltype.Signed, self.in_out_args[i]) llvmconstint = self._make_const_int(addr_as_signed) llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint, typtr) llvm_rffi.LLVMBuildStore(self.builder, value_ref, @@ -277,28 +282,16 @@ # Execution def set_future_value_int(self, index, intvalue): - assert index < self.in_args_count - 1 - if self.in_args[index]: - llvm_rffi.LLVMDisposeGenericValue(self.in_args[index]) - self.in_args[index] = llvm_rffi.LLVMCreateGenericValueOfInt( - self.ty_int, intvalue, True) + p = rffi.cast(lltype.Ptr(self.SIGNED_VALUE), self.in_out_args[index]) + p[0] = intvalue def execute_operations(self, loop): - retval = llvm_rffi.LLVMRunFunction(self.ee, loop._llvm_func, - len(loop.inputargs), - self.in_args) - ulonglong = llvm_rffi.LLVMGenericValueToInt(retval, True) - res = rffi.cast(lltype.Signed, ulonglong) - llvm_rffi.LLVMDisposeGenericValue(retval) - i = 0 - while self.in_args[i]: - llvm_rffi.LLVMDisposeGenericValue(self.in_args[i]) - self.in_args[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO) - i += 1 + res = loop._llvm_entry_stub(loop._llvm_func_addr) return self.fail_ops[res] def get_latest_value_int(self, index): - return rffi.cast(lltype.Signed, self.out_args[index][0]) + p = rffi.cast(lltype.Ptr(self.SIGNED_VALUE), self.in_out_args[index]) + return p[0] # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Mon May 4 17:18:29 2009 @@ -1,4 +1,4 @@ - +import py from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ BoxPtr, ConstPtr, TreeLoop from pypy.jit.metainterp.resoperation import rop @@ -45,6 +45,12 @@ cpu = LLVMCPU(None) cpu.setup_once() cpu.compile_operations(loop) + cpu.set_future_value_int(0, 2**11) + cpu.set_future_value_int(1, 3) + cpu.set_future_value_int(2, 0) + cpu.execute_operations(loop) + assert cpu.get_latest_value_int(0) == 3*(2**11) + py.test.skip("fails because tail-recursion is not handled yet") cpu.set_future_value_int(0, 2**29) cpu.set_future_value_int(1, 3) cpu.set_future_value_int(2, 0) From arigo at codespeak.net Mon May 4 17:40:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 May 2009 17:40:39 +0200 (CEST) Subject: [pypy-svn] r65025 - pypy/branch/pyjitpl5/pypy/jit/backend/llvm Message-ID: <20090504154039.70E8516854D@codespeak.net> Author: arigo Date: Mon May 4 17:40:38 2009 New Revision: 65025 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Log: Move this logic to C++, where it's a bit more readable. It will allow more easily to play with it, too (like adding optimization passes). Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp Mon May 4 17:40:38 2009 @@ -1,4 +1,5 @@ /* LLVM includes */ +#include #include "llvm-c/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" @@ -9,8 +10,22 @@ /* Missing pieces of the C interface... */ +LLVMExecutionEngineRef _LLVM_EE_Create(LLVMModuleRef M) +{ + LLVMModuleProviderRef mp = LLVMCreateModuleProviderForExistingModule(M); + LLVMExecutionEngineRef ee; + char* errormsg; + int error = LLVMCreateJITCompiler(&ee, mp, 1 /*Fast*/, &errormsg); + if (error) + { + fprintf(stderr, "Error creating the JIT compiler:\n%s", errormsg); + abort(); + } + return ee; +} + void *_LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, - LLVMValueRef F) + LLVMValueRef F) { return unwrap(EE)->getPointerToFunction(unwrap(F)); } Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h Mon May 4 17:40:38 2009 @@ -1,8 +1,10 @@ + #ifdef __cplusplus extern "C" { #endif - -void* _LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, + +LLVMExecutionEngineRef _LLVM_EE_Create(LLVMModuleRef M); +void *_LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, LLVMValueRef F); #ifdef __cplusplus Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Mon May 4 17:40:38 2009 @@ -279,6 +279,8 @@ rffi.CArrayPtr(LLVMGenericValueRef)], # args LLVMGenericValueRef) # return value +LLVM_EE_Create = llexternal('_LLVM_EE_Create', [LLVMModuleRef], + LLVMExecutionEngineRef) LLVM_EE_getPointerToFunction = llexternal('_LLVM_EE_getPointerToFunction', [LLVMExecutionEngineRef, LLVMValueRef], # function Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Mon May 4 17:40:38 2009 @@ -9,10 +9,6 @@ from pypy.jit.metainterp.resoperation import rop -class LLVMException(Exception): - pass - - class LLVMCPU(model.AbstractCPU): RAW_VALUE = rffi.CFixedArray(rffi.ULONGLONG, 1) SIGNED_VALUE = rffi.CFixedArray(lltype.Signed, 1) @@ -46,22 +42,7 @@ 1, False) lltype.free(arglist, flavor='raw') # - mp = llvm_rffi.LLVMCreateModuleProviderForExistingModule(self.module) - ee_out = lltype.malloc(rffi.CArray(llvm_rffi.LLVMExecutionEngineRef), - 1, flavor='raw') - error_out = lltype.malloc(rffi.CArray(rffi.CCHARP), 1, flavor='raw') - error_out[0] = lltype.nullptr(rffi.CCHARP.TO) - try: - error = llvm_rffi.LLVMCreateJITCompiler(ee_out, mp, True, - error_out) - if rffi.cast(lltype.Signed, error) != 0: - raise LLVMException(rffi.charp2str(error_out[0])) - self.ee = ee_out[0] - finally: - if error_out[0]: - llvm_rffi.LLVMDisposeMessage(error_out[0]) - lltype.free(error_out, flavor='raw') - lltype.free(ee_out, flavor='raw') + self.ee = llvm_rffi.LLVM_EE_Create(self.module) if not we_are_translated(): set_teardown_function(self._teardown) From antocuni at codespeak.net Mon May 4 17:47:18 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 17:47:18 +0200 (CEST) Subject: [pypy-svn] r65026 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli translator/cli/src Message-ID: <20090504154718.BE5B616854D@codespeak.net> Author: antocuni Date: Mon May 4 17:47:18 2009 New Revision: 65026 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Log: - implement int_add_ovf - implement guard_no_exception - add a general way to add "branches" of the main method - correctly return the last operation that failed - this is enough to make the first bit of test_ovf_operations passing. The test as a whole still fails, because the other ops are still unimplemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 17:47:18 2009 @@ -83,18 +83,23 @@ self.name = name self.loop = loop self.boxes = {} # box --> local var + self.failing_ops = {} # index --> op + self.branches = [] # (Label, operations) self.meth_wrapper = self._get_meth_wrapper() self.il = self.meth_wrapper.get_il_generator() self.av_consts = MethodArgument(0, System.Type.GetType("System.Object[]")) - self.av_inputargs = MethodArgument(1, dotnet.typeof(InputArgs)) + t_InputArgs = dotnet.typeof(InputArgs) + self.av_inputargs = MethodArgument(1,t_InputArgs ) + self.exc_value_field = t_InputArgs.GetField('exc_value') + # ---- self.emit_load_inputargs() - self.emit_operations() + self.emit_operations(loop.operations) + self.emit_branches() self.emit_end() delegatetype = dotnet.typeof(LoopDelegate) consts = dotnet.new_array(System.Object, 0) self.func = self.meth_wrapper.create_delegate(delegatetype, consts) - def _get_meth_wrapper(self): restype = dotnet.class2type(cVoid) args = self._get_args_array([dotnet.typeof(InputArgs)]) @@ -115,6 +120,22 @@ self.boxes[box] = v return v + def get_index_for_failing_op(self, op): + try: + return self.failing_ops[op] + except KeyError: + i = len(self.failing_ops) + self.failing_ops[i] = op + return i + + def newbranch(self, op): + # sanity check, maybe we can remove it later + for _, myop in self.branches: + assert myop is not op + il_label = self.il.DefineLabel() + self.branches.append((il_label, op)) + return il_label + def get_inputarg_field(self, type): t = dotnet.typeof(InputArgs) if type == history.INT: @@ -147,13 +168,22 @@ box.store(self) i+=1 - def emit_operations(self): - for op in self.loop.operations: + def emit_operations(self, operations): + for op in operations: func = self.operations[op.opnum] assert func is not None func(self, op) + def emit_branches(self): + while self.branches: + branches = self.branches + self.branches = [] + for il_label, op in branches: + self.il.MarkLabel(il_label) + self.emit_operations(op.suboperations) + def emit_end(self): + assert self.branches == [] self.il.Emit(OpCodes.Ret) # ----------------------------- @@ -166,15 +196,45 @@ op.result.store(self) def emit_op_fail(self, op): + index_op = self.get_index_for_failing_op(op) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldc_I4, index_op) + field = dotnet.typeof(InputArgs).GetField('failed_op') + self.il.Emit(OpCodes.Stfld, field) + i = 0 for box in op.args: self.store_inputarg(i, box.type, box.getCliType(), box) i+=1 self.il.Emit(OpCodes.Ret) + def emit_op_guard_no_exception(self, op): + assert op.suboperations + il_label = self.newbranch(op) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldfld, self.exc_value_field) + self.il.Emit(OpCodes.Brtrue, il_label) + + def emit_op_int_add_ovf(self, op): + exctype = dotnet.typeof(System.OverflowException) + v = self.il.DeclareLocal(exctype) + lbl = self.il.BeginExceptionBlock() + # XXX: clear_exception + self.push_all_args(op) + self.il.Emit(OpCodes.Add_Ovf) + self.store_result(op) + self.il.Emit(OpCodes.Leave, lbl) + self.il.BeginCatchBlock(exctype) + self.il.Emit(OpCodes.Stloc, v) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldloc, v) + self.il.Emit(OpCodes.Stfld, self.exc_value_field) + self.il.EndExceptionBlock() + def not_implemented(self, op): raise NotImplementedError + emit_op_guard_exception = not_implemented emit_op_guard_value = not_implemented emit_op_cast_int_to_ptr = not_implemented emit_op_guard_nonvirtualized = not_implemented @@ -184,7 +244,6 @@ emit_op_jump = not_implemented emit_op_setfield_raw = not_implemented emit_op_cast_ptr_to_int = not_implemented - emit_op_guard_no_exception = not_implemented emit_op_newunicode = not_implemented emit_op_new_array = not_implemented emit_op_unicodegetitem = not_implemented @@ -205,7 +264,6 @@ emit_op_call_pure = not_implemented emit_op_strlen = not_implemented emit_op_newstr = not_implemented - emit_op_guard_exception = not_implemented emit_op_call = not_implemented emit_op_strsetitem = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 4 17:47:18 2009 @@ -33,11 +33,13 @@ # ---------------------- def compile_operations(self, loop): - meth = Method(self, 'loop', loop) + meth = Method(self, loop.name, loop) loop._cli_meth = meth def execute_operations(self, loop): - loop._cli_meth.func(self.inputargs) + meth = loop._cli_meth + meth.func(self.inputargs) + return meth.failing_ops[self.inputargs.failed_op] def set_future_value_int(self, index, intvalue): self.inputargs.ints[index] = intvalue Modified: pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Mon May 4 17:47:18 2009 @@ -115,6 +115,8 @@ public int[] ints = new int[32]; public float[] floats = new float[32]; public object[] objs = new object[32]; + public Exception exc_value = null; + public int failed_op = -1; public void ensure_ints(int n) { From antocuni at codespeak.net Mon May 4 18:11:01 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 18:11:01 +0200 (CEST) Subject: [pypy-svn] r65027 - pypy/branch/pyjitpl5/pypy/jit/backend/cli Message-ID: <20090504161101.54148168490@codespeak.net> Author: antocuni Date: Mon May 4 18:10:59 2009 New Revision: 65027 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Log: automatically generate also raising ops. More bits of test_raising_ops pass, other still fails Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 18:10:59 2009 @@ -195,13 +195,34 @@ def store_result(self, op): op.result.store(self) + def emit_clear_exception(self): + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldnull) + self.il.Emit(OpCodes.Stfld, self.exc_value_field) + + def emit_raising_op(self, op, emit_op, exctype): + v = self.il.DeclareLocal(exctype) + self.emit_clear_exception() + lbl = self.il.BeginExceptionBlock() + emit_op(self, op) + self.il.Emit(OpCodes.Leave, lbl) + self.il.BeginCatchBlock(exctype) + self.il.Emit(OpCodes.Stloc, v) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldloc, v) + self.il.Emit(OpCodes.Stfld, self.exc_value_field) + self.il.EndExceptionBlock() + + # -------------------------------- + def emit_op_fail(self, op): + # store the index of the failed op index_op = self.get_index_for_failing_op(op) self.av_inputargs.load(self) self.il.Emit(OpCodes.Ldc_I4, index_op) field = dotnet.typeof(InputArgs).GetField('failed_op') self.il.Emit(OpCodes.Stfld, field) - + # store the lates values i = 0 for box in op.args: self.store_inputarg(i, box.type, box.getCliType(), box) @@ -215,25 +236,10 @@ self.il.Emit(OpCodes.Ldfld, self.exc_value_field) self.il.Emit(OpCodes.Brtrue, il_label) - def emit_op_int_add_ovf(self, op): - exctype = dotnet.typeof(System.OverflowException) - v = self.il.DeclareLocal(exctype) - lbl = self.il.BeginExceptionBlock() - # XXX: clear_exception - self.push_all_args(op) - self.il.Emit(OpCodes.Add_Ovf) - self.store_result(op) - self.il.Emit(OpCodes.Leave, lbl) - self.il.BeginCatchBlock(exctype) - self.il.Emit(OpCodes.Stloc, v) - self.av_inputargs.load(self) - self.il.Emit(OpCodes.Ldloc, v) - self.il.Emit(OpCodes.Stfld, self.exc_value_field) - self.il.EndExceptionBlock() - def not_implemented(self, op): raise NotImplementedError + emit_op_oosend = not_implemented emit_op_guard_exception = not_implemented emit_op_guard_value = not_implemented emit_op_cast_int_to_ptr = not_implemented @@ -289,6 +295,8 @@ return operations def render_op(methname, instrlist): + if len(instrlist) == 1 and isinstance(instrlist[0], opcodes.MapException): + return render_raising_op(methname, instrlist) lines = [] for instr in instrlist: if instr == opcodes.PushAllArgs: @@ -314,6 +322,27 @@ exec src.compile() in dic return dic[methname] +def render_raising_op(methname, instrlist): + value = instrlist[0] + 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]'):] + impl_func = render_op(methname + '_impl', value.instr) + if not impl_func: + return + src = py.code.Source(""" + def %s(self, op): + exctype = dotnet.typeof(%s) + self.emit_raising_op(op, impl_func, exctype) + """ % (methname, exctype)) + dic = {'System': System, + 'dotnet': dotnet, + 'impl_func': impl_func} + exec src.compile() in dic + return dic[methname] + def opcode2attrname(opcode): if opcode == 'ldc.r8 0': return 'Ldc_R8, 0' # XXX this is a hack From antocuni at codespeak.net Mon May 4 18:31:02 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 18:31:02 +0200 (CEST) Subject: [pypy-svn] r65028 - in pypy/branch/pyjitpl5/pypy/translator: cli oosupport/test_template Message-ID: <20090504163102.DC30B1684EA@codespeak.net> Author: antocuni Date: Mon May 4 18:31:00 2009 New Revision: 65028 Modified: pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py Log: a test and a fix for int_mod_ovf* Modified: pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py Mon May 4 18:31:00 2009 @@ -19,13 +19,20 @@ return [PushAllArgs, 'call %s class [mscorlib]System.Math::Abs(%s)' % (type_, type_), StoreResult] def _check_ovf(op): - mapping = [('[mscorlib]System.OverflowException', 'exceptions.OverflowError')] + mapping = [('[mscorlib]System.OverflowException', 'exceptions.OverflowError'), + ('[mscorlib]System.ArithmeticException', 'exceptions.OverflowError')] return [MapException(op, mapping)] def _check_zer(op): mapping = [('[mscorlib]System.DivideByZeroException', 'exceptions.ZeroDivisionError')] return [MapException(op, mapping)] +def _check_ovf_zer(op): + mapping = [('[mscorlib]System.OverflowException', 'exceptions.OverflowError'), + ('[mscorlib]System.DivideByZeroException', 'exceptions.ZeroDivisionError'), + ('[mscorlib]System.ArithmeticException', 'exceptions.OverflowError')] + return [MapException(op, mapping)] + # __________ object oriented & misc operations __________ misc_ops = { 'new': [New], @@ -167,7 +174,7 @@ 'int_sub_ovf': _check_ovf('sub.ovf'), 'int_mul_ovf': _check_ovf('mul.ovf'), 'int_floordiv_ovf': 'div', # these can't overflow! - 'int_mod_ovf': 'rem', + 'int_mod_ovf': _check_ovf('rem'), 'int_lt_ovf': 'clt', 'int_le_ovf': _not('cgt'), 'int_eq_ovf': 'ceq', @@ -183,7 +190,7 @@ 'int_rshift_ovf': 'shr', # these can't overflow! 'int_xor_ovf': 'xor', 'int_floordiv_ovf_zer': _check_zer('div'), - 'int_mod_ovf_zer': _check_zer('rem'), + 'int_mod_ovf_zer': _check_ovf_zer('rem'), 'int_mod_zer': _check_zer('rem'), 'uint_add': 'add', Modified: pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py Mon May 4 18:31:00 2009 @@ -56,3 +56,11 @@ except OverflowError: return 42 self.check(fn, [-sys.maxint-1]) + + def test_mod(self): + def fn(x, y): + try: + return ovfcheck(x % y) + except OverflowError: + return 42 + self.check(fn, [-sys.maxint-1, -1]) From antocuni at codespeak.net Mon May 4 18:40:50 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 18:40:50 +0200 (CEST) Subject: [pypy-svn] r65029 - pypy/branch/pyjitpl5/pypy/jit/backend/cli Message-ID: <20090504164050.723D616806E@codespeak.net> Author: antocuni Date: Mon May 4 18:40:49 2009 New Revision: 65029 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Log: add the possibility to catch more than one exception for raising ops. This is needed by int_mod_ovf, which can raises both ArithmeticException and OverflowException. The corresponding bit of test_raising_ops passes (but the last bit still fails) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 18:40:49 2009 @@ -200,17 +200,18 @@ self.il.Emit(OpCodes.Ldnull) self.il.Emit(OpCodes.Stfld, self.exc_value_field) - def emit_raising_op(self, op, emit_op, exctype): - v = self.il.DeclareLocal(exctype) + def emit_raising_op(self, op, emit_op, exctypes): self.emit_clear_exception() lbl = self.il.BeginExceptionBlock() emit_op(self, op) self.il.Emit(OpCodes.Leave, lbl) - self.il.BeginCatchBlock(exctype) - self.il.Emit(OpCodes.Stloc, v) - self.av_inputargs.load(self) - self.il.Emit(OpCodes.Ldloc, v) - self.il.Emit(OpCodes.Stfld, self.exc_value_field) + for exctype in exctypes: + v = self.il.DeclareLocal(exctype) + self.il.BeginCatchBlock(exctype) + self.il.Emit(OpCodes.Stloc, v) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldloc, v) + self.il.Emit(OpCodes.Stfld, self.exc_value_field) self.il.EndExceptionBlock() # -------------------------------- @@ -290,12 +291,15 @@ func = getattr(Method, methname).im_func else: instrlist = opcodes.opcodes[key] - func = render_op(methname, instrlist) + func = render_op(methname, instrlist, False) operations[value] = func return operations +def is_raising_op(instrlist): + return len(instrlist) == 1 and isinstance(instrlist[0], opcodes.MapException) + def render_op(methname, instrlist): - if len(instrlist) == 1 and isinstance(instrlist[0], opcodes.MapException): + if is_raising_op(instrlist): return render_raising_op(methname, instrlist) lines = [] for instr in instrlist: @@ -322,21 +326,23 @@ exec src.compile() in dic return dic[methname] +def parse_exctype(exctype): + assert exctype.startswith('[mscorlib]') + return exctype[len('[mscorlib]'):] + + def render_raising_op(methname, instrlist): value = instrlist[0] - 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]'):] + exctypes = [parse_exctype(exctype) for exctype, _ in value.mapping] + exctypes = ['dotnet.typeof(%s)' % exctype for exctype in exctypes] impl_func = render_op(methname + '_impl', value.instr) if not impl_func: return src = py.code.Source(""" def %s(self, op): - exctype = dotnet.typeof(%s) - self.emit_raising_op(op, impl_func, exctype) - """ % (methname, exctype)) + exctypes = [%s] + self.emit_raising_op(op, impl_func, exctypes) + """ % (methname, ', '.join(exctypes))) dic = {'System': System, 'dotnet': dotnet, 'impl_func': impl_func} From antocuni at codespeak.net Mon May 4 18:48:03 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 18:48:03 +0200 (CEST) Subject: [pypy-svn] r65030 - in pypy/branch/pyjitpl5/pypy/translator: cli oosupport/test_template Message-ID: <20090504164803.CB8B01684E1@codespeak.net> Author: antocuni Date: Mon May 4 18:48:03 2009 New Revision: 65030 Modified: pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py Log: another test&fix for overflow in the cli backend Modified: pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py Mon May 4 18:48:03 2009 @@ -173,7 +173,7 @@ 'int_add_nonneg_ovf': _check_ovf('add.ovf'), 'int_sub_ovf': _check_ovf('sub.ovf'), 'int_mul_ovf': _check_ovf('mul.ovf'), - 'int_floordiv_ovf': 'div', # these can't overflow! + 'int_floordiv_ovf': _check_ovf('div'), 'int_mod_ovf': _check_ovf('rem'), 'int_lt_ovf': 'clt', 'int_le_ovf': _not('cgt'), @@ -189,7 +189,7 @@ 'int_rshift_ovf': 'shr', # these can't overflow! 'int_xor_ovf': 'xor', - 'int_floordiv_ovf_zer': _check_zer('div'), + 'int_floordiv_ovf_zer': _check_ovf_zer('div'), 'int_mod_ovf_zer': _check_ovf_zer('rem'), 'int_mod_zer': _check_zer('rem'), Modified: pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/overflow.py Mon May 4 18:48:03 2009 @@ -64,3 +64,11 @@ except OverflowError: return 42 self.check(fn, [-sys.maxint-1, -1]) + + def test_div(self): + def fn(x, y): + try: + return ovfcheck(x / y) + except OverflowError: + return 42 + self.check(fn, [-sys.maxint-1, -1]) From antocuni at codespeak.net Mon May 4 18:48:53 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 18:48:53 +0200 (CEST) Subject: [pypy-svn] r65031 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090504164853.DBA201684E1@codespeak.net> Author: antocuni Date: Mon May 4 18:48:52 2009 New Revision: 65031 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Log: add support for PushArg. test_overflow_operations finally passes :-) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 18:48:52 2009 @@ -192,6 +192,9 @@ for box in op.args: box.load(self) + def push_arg(self, op, n): + op.args[n].load(self) + def store_result(self, op): op.result.store(self) @@ -291,7 +294,7 @@ func = getattr(Method, methname).im_func else: instrlist = opcodes.opcodes[key] - func = render_op(methname, instrlist, False) + func = render_op(methname, instrlist) operations[value] = func return operations @@ -307,6 +310,8 @@ lines.append('self.push_all_args(op)') elif instr == opcodes.StoreResult: lines.append('self.store_result(op)') + elif isinstance(instr, opcodes.PushArg): + lines.append('self.push_arg(op, %d)' % instr.n) else: if not isinstance(instr, str): print 'WARNING: unknown instruction %s' % instr Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Mon May 4 18:48:52 2009 @@ -26,8 +26,4 @@ class TestRunner(CliJitMixin, OOtypeBackendTest): - - def skip(self): - py.test.skip('in-progress') - - test_ovf_operations = skip + pass From arigo at codespeak.net Mon May 4 19:18:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 May 2009 19:18:02 +0200 (CEST) Subject: [pypy-svn] r65032 - pypy/branch/pyjitpl5/pypy/jit/backend/llvm Message-ID: <20090504171802.6325C16857B@codespeak.net> Author: arigo Date: Mon May 4 19:18:00 2009 New Revision: 65032 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Log: I'm hitting a wall. Checking in anyway for reference. The code produced by LLVM seems buggy, but only if PerformTailCallOpt is set to true. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp Mon May 4 19:18:00 2009 @@ -3,19 +3,27 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Target/TargetOptions.h" #include "demo2.h" using namespace llvm; -/* Missing pieces of the C interface... +/* Set the flag to true. + */ +void _LLVM_SetFlags(void) +{ + PerformTailCallOpt = true; +} + +/* This piece of code regroups conveniently a part of the initialization. */ LLVMExecutionEngineRef _LLVM_EE_Create(LLVMModuleRef M) { LLVMModuleProviderRef mp = LLVMCreateModuleProviderForExistingModule(M); LLVMExecutionEngineRef ee; char* errormsg; - int error = LLVMCreateJITCompiler(&ee, mp, 1 /*Fast*/, &errormsg); + int error = LLVMCreateJITCompiler(&ee, mp, 0 /*Fast*/, &errormsg); if (error) { fprintf(stderr, "Error creating the JIT compiler:\n%s", errormsg); @@ -24,6 +32,8 @@ return ee; } +/* Missing pieces of the C interface... + */ void *_LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.h Mon May 4 19:18:00 2009 @@ -2,7 +2,8 @@ #ifdef __cplusplus extern "C" { #endif - + +void _LLVM_SetFlags(void); LLVMExecutionEngineRef _LLVM_EE_Create(LLVMModuleRef M); void *_LLVM_EE_getPointerToFunction(LLVMExecutionEngineRef EE, LLVMValueRef F); Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Mon May 4 19:18:00 2009 @@ -43,7 +43,7 @@ # ____________________________________________________________ -Debug = False +Debug = True def llexternal(name, args, result, **kwds): ll = rffi.llexternal(name, args, result, @@ -279,6 +279,7 @@ rffi.CArrayPtr(LLVMGenericValueRef)], # args LLVMGenericValueRef) # return value +LLVM_SetFlags = llexternal('_LLVM_SetFlags', [], lltype.Void) LLVM_EE_Create = llexternal('_LLVM_EE_Create', [LLVMModuleRef], LLVMExecutionEngineRef) LLVM_EE_getPointerToFunction = llexternal('_LLVM_EE_getPointerToFunction', Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Mon May 4 19:18:00 2009 @@ -26,6 +26,7 @@ def setup_once(self): if not we_are_translated(): teardown_now() + llvm_rffi.LLVM_SetFlags() self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit") if sys.maxint == 2147483647: self.ty_int = llvm_rffi.LLVMInt32Type() @@ -267,7 +268,10 @@ p[0] = intvalue def execute_operations(self, loop): + print 'execute_operations: %s' % (loop._llvm_func_addr,) + import time; time.sleep(2) res = loop._llvm_entry_stub(loop._llvm_func_addr) + print '\t--->', res return self.fail_ops[res] def get_latest_value_int(self, index): From antocuni at codespeak.net Mon May 4 21:10:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 21:10:08 +0200 (CEST) Subject: [pypy-svn] r65033 - in pypy/branch/pyjitpl5/pypy/jit/backend: cli/test minimal/test test Message-ID: <20090504191008.4346C169E13@codespeak.net> Author: antocuni Date: Mon May 4 21:10:04 2009 New Revision: 65033 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Log: split test_{failing,passing}_guards into smaller tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Mon May 4 21:10:04 2009 @@ -21,8 +21,10 @@ def _skip(self): py.test.skip("not supported in non-translated version") - test_passing_guards = _skip # GUARD_CLASS - test_failing_guards = _skip # GUARD_CLASS + test_passing_guards = _skip # GUARD_CLASS + test_passing_guard_class = _skip # GUARD_CLASS + test_failing_guards = _skip # GUARD_CLASS + test_failing_guard_class = _skip # GUARD_CLASS class TestRunner(CliJitMixin, OOtypeBackendTest): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py Mon May 4 21:10:04 2009 @@ -18,9 +18,10 @@ def _skip(self): py.test.skip("not supported in non-translated version") - test_passing_guards = _skip # GUARD_CLASS - test_failing_guards = _skip # GUARD_CLASS - + test_passing_guards = _skip # GUARD_CLASS + test_passing_guard_class = _skip # GUARD_CLASS + test_failing_guards = _skip # GUARD_CLASS + test_failing_guard_class = _skip # GUARD_CLASS class TestOOtype(OOJitMixin, MinimalTestMixin, OOtypeBackendTest): pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Mon May 4 21:10:04 2009 @@ -241,11 +241,6 @@ def test_passing_guards(self): - T = self.T - vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True) - vtable_for_T_addr = llmemory.cast_ptr_to_adr(vtable_for_T) - cpu = self.cpu - cpu._cache_gcstruct2vtable = {T: vtable_for_T} for (opname, args) in [(rop.GUARD_TRUE, [BoxInt(1)]), (rop.GUARD_FALSE, [BoxInt(0)]), (rop.GUARD_VALUE, [BoxInt(42), BoxInt(42)]), @@ -253,7 +248,13 @@ ]: assert self.execute_operation(opname, args, 'void') == None assert not self.guard_failed - + + def test_passing_guard_class(self): + T = self.T + vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True) + vtable_for_T_addr = llmemory.cast_ptr_to_adr(vtable_for_T) + cpu = self.cpu + cpu._cache_gcstruct2vtable = {T: vtable_for_T} t = lltype.malloc(T) t.parent.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) @@ -265,6 +266,14 @@ # 'void') def test_failing_guards(self): + for opname, args in [(rop.GUARD_TRUE, [BoxInt(0)]), + (rop.GUARD_FALSE, [BoxInt(1)]), + (rop.GUARD_VALUE, [BoxInt(42), BoxInt(41)]), + ]: + assert self.execute_operation(opname, args, 'void') == None + assert self.guard_failed + + def test_failing_guard_class(self): T = self.T U = self.U vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True) @@ -282,10 +291,7 @@ u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) U_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_U_addr)) null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) - for opname, args in [(rop.GUARD_TRUE, [BoxInt(0)]), - (rop.GUARD_FALSE, [BoxInt(1)]), - (rop.GUARD_VALUE, [BoxInt(42), BoxInt(41)]), - (rop.GUARD_CLASS, [t_box, U_box]), + for opname, args in [(rop.GUARD_CLASS, [t_box, U_box]), (rop.GUARD_CLASS, [u_box, T_box]), #(rop.GUARD_VALUE_INVERSE, [BoxInt(10), BoxInt(10)]), ]: From antocuni at codespeak.net Mon May 4 21:26:58 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 21:26:58 +0200 (CEST) Subject: [pypy-svn] r65034 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090504192658.93119169E1A@codespeak.net> Author: antocuni Date: Mon May 4 21:26:57 2009 New Revision: 65034 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Log: implement guard_{true,false,value}. test_{passing,failing}_guards pass :-) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 21:26:57 2009 @@ -5,7 +5,7 @@ from pypy.translator.cli.dotnet import CLR from pypy.translator.cli import opcodes from pypy.jit.metainterp import history -from pypy.jit.metainterp.history import AbstractValue, Const +from pypy.jit.metainterp.history import AbstractValue, Const, ConstInt from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.cli.methodfactory import get_method_wrapper @@ -46,6 +46,11 @@ def store(self, meth): assert False, 'cannot store() to Constant' +class __extend__(ConstInt): + __metaclass__ = extendabletype + + def load(self, meth): + meth.il.Emit(OpCodes.Ldc_I4, self.value) class MethodArgument(AbstractValue): def __init__(self, index, cliType): @@ -233,6 +238,26 @@ i+=1 self.il.Emit(OpCodes.Ret) + def emit_guard_bool(self, op, opcode): + assert op.suboperations + assert len(op.args) == 1 + il_label = self.newbranch(op) + op.args[0].load(self) + self.il.Emit(opcode, il_label) + + def emit_op_guard_true(self, op): + self.emit_guard_bool(op, OpCodes.Brfalse) + + def emit_op_guard_false(self, op): + self.emit_guard_bool(op, OpCodes.Brtrue) + + def emit_op_guard_value(self, op): + assert op.suboperations + assert len(op.args) == 2 + il_label = self.newbranch(op) + self.push_all_args(op) + self.il.Emit(OpCodes.Bne_Un, il_label) + def emit_op_guard_no_exception(self, op): assert op.suboperations il_label = self.newbranch(op) @@ -245,11 +270,9 @@ emit_op_oosend = not_implemented emit_op_guard_exception = not_implemented - emit_op_guard_value = not_implemented emit_op_cast_int_to_ptr = not_implemented emit_op_guard_nonvirtualized = not_implemented emit_op_setarrayitem_gc = not_implemented - emit_op_guard_false = not_implemented emit_op_unicodelen = not_implemented emit_op_jump = not_implemented emit_op_setfield_raw = not_implemented @@ -263,7 +286,6 @@ emit_op_oosend_pure = not_implemented emit_op_getarrayitem_gc_pure = not_implemented emit_op_arraylen_gc = not_implemented - emit_op_guard_true = not_implemented emit_op_unicodesetitem = not_implemented emit_op_getfield_raw_pure = not_implemented emit_op_new_with_vtable = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Mon May 4 21:26:57 2009 @@ -21,9 +21,7 @@ def _skip(self): py.test.skip("not supported in non-translated version") - test_passing_guards = _skip # GUARD_CLASS test_passing_guard_class = _skip # GUARD_CLASS - test_failing_guards = _skip # GUARD_CLASS test_failing_guard_class = _skip # GUARD_CLASS From arigo at codespeak.net Mon May 4 22:08:51 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 May 2009 22:08:51 +0200 (CEST) Subject: [pypy-svn] r65035 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090504200851.4D3A7169DF5@codespeak.net> Author: arigo Date: Mon May 4 22:08:49 2009 New Revision: 65035 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: Test structure fields of type rffi.UCHAR and (disabled for now) rffi.SHORT. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Mon May 4 22:08:49 2009 @@ -1,5 +1,5 @@ import py -from pypy.rpython.lltypesystem import lltype, llmemory, rclass +from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rffi from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr, BoxPtr @@ -8,6 +8,7 @@ from pypy.rpython.llinterp import LLException class LLtypeOperationBuilder(test_random.OperationBuilder): + HAVE_SHORT_FIELDS = False def __init__(self, *args, **kw): test_random.OperationBuilder.__init__(self, *args, **kw) @@ -36,7 +37,16 @@ fields.append(('parent', rclass.OBJECT)) kwds['hints'] = {'vtable': with_vtable._obj} for i in range(r.randrange(1, 5)): - fields.append(('f%d' % i, lltype.Signed)) + rval = r.random() + if rval < 0.5: + TYPE = lltype.Signed + elif rval < 0.75: + TYPE = rffi.UCHAR + else: + TYPE = rffi.SHORT + if not self.HAVE_SHORT_FIELDS: + TYPE = lltype.Signed + fields.append(('f%d' % i, TYPE)) S = lltype.GcStruct('S%d' % self.counter, *fields, **kwds) self.counter += 1 return S @@ -65,7 +75,8 @@ p = lltype.malloc(S) for fieldname in lltype.typeOf(p).TO._names: if fieldname != 'parent': - setattr(p, fieldname, r.random_integer()) + TYPE = getattr(S, fieldname) + setattr(p, fieldname, rffi.cast(TYPE, r.random_integer())) return p def field_values(self, p): @@ -124,12 +135,13 @@ name = r.choice(names) descr = builder.cpu.fielddescrof(S, name) descr._random_info = 'cpu.fielddescrof(%s, %r)' % (S._name, name) - return v, descr + TYPE = getattr(S, name) + return v, descr, TYPE def produce_into(self, builder, r): while True: try: - v, descr = self.field_descr(builder, r) + v, descr, _ = self.field_descr(builder, r) self.put(builder, [v], descr) except lltype.UninitializedMemoryAccess: continue @@ -137,11 +149,14 @@ class SetFieldOperation(GetFieldOperation): def produce_into(self, builder, r): - v, descr = self.field_descr(builder, r) - if r.random() < 0.3: - w = ConstInt(r.random_integer()) - else: - w = r.choice(builder.intvars) + v, descr, TYPE = self.field_descr(builder, r) + while True: + if r.random() < 0.3: + w = ConstInt(r.random_integer()) + else: + w = r.choice(builder.intvars) + if rffi.cast(lltype.Signed, rffi.cast(TYPE, w.value)) == w.value: + break builder.do(self.opnum, [v, w], descr) class NewOperation(test_random.AbstractOperation): From antocuni at codespeak.net Mon May 4 23:03:37 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:03:37 +0200 (CEST) Subject: [pypy-svn] r65036 - in pypy/branch/pyjitpl5/pypy/jit/backend: cli/test test Message-ID: <20090504210337.5DEEE169E1D@codespeak.net> Author: antocuni Date: Mon May 4 23:03:36 2009 New Revision: 65036 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Log: port test_{passing,failing}_guard_class to ootype Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Mon May 4 23:03:36 2009 @@ -18,12 +18,10 @@ def setup_class(cls): cls.cpu = cls.CPUClass(rtyper=None, stats=FakeStats()) - def _skip(self): - py.test.skip("not supported in non-translated version") - - test_passing_guard_class = _skip # GUARD_CLASS - test_failing_guard_class = _skip # GUARD_CLASS - class TestRunner(CliJitMixin, OOtypeBackendTest): - pass + def skip(self): + py.test.skip("not supported in non-translated version") + + test_passing_guard_class = skip # GUARD_CLASS + test_failing_guard_class = skip # GUARD_CLASS Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Mon May 4 23:03:36 2009 @@ -1,7 +1,8 @@ import sys from pypy.jit.metainterp.history import (BoxInt, Box, BoxPtr, TreeLoop, - ConstInt, ConstPtr, BoxObj) + ConstInt, ConstPtr, BoxObj, + ConstObj) from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.typesystem import deref from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass @@ -249,17 +250,10 @@ assert self.execute_operation(opname, args, 'void') == None assert not self.guard_failed + def test_passing_guard_class(self): - T = self.T - vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True) - vtable_for_T_addr = llmemory.cast_ptr_to_adr(vtable_for_T) - cpu = self.cpu - cpu._cache_gcstruct2vtable = {T: vtable_for_T} - t = lltype.malloc(T) - t.parent.parent.typeptr = vtable_for_T - t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(cpu.cast_adr_to_int(vtable_for_T_addr)) - null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) + t_box, T_box = self.alloc_instance(self.T) + #null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) self.execute_operation(rop.GUARD_CLASS, [t_box, T_box], 'void') assert not self.guard_failed #self.execute_operation(rop.GUARD_CLASS_INVERSE, [t_box, null_box], @@ -274,23 +268,9 @@ assert self.guard_failed def test_failing_guard_class(self): - T = self.T - U = self.U - vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True) - vtable_for_T_addr = llmemory.cast_ptr_to_adr(vtable_for_T) - vtable_for_U = lltype.malloc(self.MY_VTABLE, immortal=True) - vtable_for_U_addr = llmemory.cast_ptr_to_adr(vtable_for_U) - cpu = self.cpu - cpu._cache_gcstruct2vtable = {T: vtable_for_T, U: vtable_for_U} - t = lltype.malloc(T) - t.parent.parent.typeptr = vtable_for_T - t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) - T_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_T_addr)) - u = lltype.malloc(U) - u.parent.parent.parent.typeptr = vtable_for_U - u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) - U_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_U_addr)) - null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) + t_box, T_box = self.alloc_instance(self.T) + u_box, U_box = self.alloc_instance(self.U) + #null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) for opname, args in [(rop.GUARD_CLASS, [t_box, U_box]), (rop.GUARD_CLASS, [u_box, T_box]), #(rop.GUARD_VALUE_INVERSE, [BoxInt(10), BoxInt(10)]), @@ -324,6 +304,24 @@ U = lltype.GcStruct('U', ('parent', T), ('next', lltype.Ptr(S))) + + def alloc_instance(self, T): + vtable_for_T = lltype.malloc(self.MY_VTABLE, immortal=True) + vtable_for_T_addr = llmemory.cast_ptr_to_adr(vtable_for_T) + cpu = self.cpu + if not hasattr(cpu, '_cache_gcstruct2vtable'): + cpu._cache_gcstruct2vtable = {} + cpu._cache_gcstruct2vtable.update({T: vtable_for_T}) + t = lltype.malloc(T) + if T == self.T: + t.parent.parent.typeptr = vtable_for_T + elif T == self.U: + t.parent.parent.parent.typeptr = vtable_for_T + t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) + T_box = ConstInt(self.cpu.cast_adr_to_int(vtable_for_T_addr)) + return t_box, T_box + + def test_casts(self): from pypy.rpython.lltypesystem import lltype, llmemory TP = lltype.GcStruct('x') @@ -360,3 +358,15 @@ @classmethod def get_funcbox(cls, cpu, func_ptr): return BoxObj(ootype.cast_to_object(func_ptr)) + + S = ootype.Instance('S', ootype.ROOT, {'value': ootype.Signed}) + S._add_fields({'next': S}) + T = ootype.Instance('T', S) + U = ootype.Instance('U', T) + + def alloc_instance(self, T): + t = ootype.new(T) + cls = ootype.classof(t) + t_box = BoxObj(ootype.cast_to_object(t)) + T_box = ConstObj(ootype.cast_to_object(cls)) + return t_box, T_box From antocuni at codespeak.net Mon May 4 23:04:45 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:04:45 +0200 (CEST) Subject: [pypy-svn] r65037 - pypy/branch/pyjitpl5/pypy/jit/backend/cli Message-ID: <20090504210445.E1027169E1F@codespeak.net> Author: antocuni Date: Mon May 4 23:04:41 2009 New Revision: 65037 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Log: implement guard_class. We cannot test it right now though :-(, because it can works only after translation Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 23:04:41 2009 @@ -41,7 +41,10 @@ __metaclass__ = extendabletype def load(self, meth): - raise NotImplementedError + index = meth.get_index_for_constant(self) + meth.av_consts.load(meth) + meth.il.Emit(OpCodes.Ldc_I4, index) + meth.il.Emit(OpCodes.Ldelem_Ref) def store(self, meth): assert False, 'cannot store() to Constant' @@ -87,9 +90,10 @@ self.cpu = cpu self.name = name self.loop = loop - self.boxes = {} # box --> local var + self.boxes = {} # box --> local var self.failing_ops = {} # index --> op - self.branches = [] # (Label, operations) + self.branches = [] # (Label, operations) + self.consts = {} # object --> index self.meth_wrapper = self._get_meth_wrapper() self.il = self.meth_wrapper.get_il_generator() self.av_consts = MethodArgument(0, System.Type.GetType("System.Object[]")) @@ -101,8 +105,16 @@ self.emit_operations(loop.operations) self.emit_branches() self.emit_end() + # ---- + self.finish_code() + + def finish_code(self): delegatetype = dotnet.typeof(LoopDelegate) - consts = dotnet.new_array(System.Object, 0) + # initialize the array of genconsts + consts = dotnet.new_array(System.Object, len(self.consts)) + for av_const, i in self.consts.iteritems(): + consts[i] = dotnet.cast_to_native_object(av_const.getobj()) + # build the delegate self.func = self.meth_wrapper.create_delegate(delegatetype, consts) def _get_meth_wrapper(self): @@ -133,6 +145,14 @@ self.failing_ops[i] = op return i + def get_index_for_constant(self, obj): + try: + return self.consts[obj] + except KeyError: + index = len(self.consts) + self.consts[obj] = index + return index + def newbranch(self, op): # sanity check, maybe we can remove it later for _, myop in self.branches: @@ -258,6 +278,16 @@ self.push_all_args(op) self.il.Emit(OpCodes.Bne_Un, il_label) + def emit_op_guard_class(self, op): + assert op.suboperations + assert len(op.args) == 2 + il_label = self.newbranch(op) + self.push_arg(op, 0) + meth = dotnet.typeof(System.Object).GetMethod("GetType") + self.il.Emit(OpCodes.Callvirt, meth) + self.push_arg(op, 1) + self.il.Emit(OpCodes.Bne_Un, il_label) + def emit_op_guard_no_exception(self, op): assert op.suboperations il_label = self.newbranch(op) @@ -290,7 +320,6 @@ emit_op_getfield_raw_pure = not_implemented emit_op_new_with_vtable = not_implemented emit_op_getfield_gc_pure = not_implemented - emit_op_guard_class = not_implemented emit_op_getarrayitem_gc = not_implemented emit_op_getfield_gc = not_implemented emit_op_call_pure = not_implemented From fijal at codespeak.net Mon May 4 23:06:32 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 4 May 2009 23:06:32 +0200 (CEST) Subject: [pypy-svn] r65038 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090504210632.03DF5169E22@codespeak.net> Author: fijal Date: Mon May 4 23:06:32 2009 New Revision: 65038 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py Log: a failing test Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py Mon May 4 23:06:32 2009 @@ -24,6 +24,33 @@ res = self.meta_interp(main, [20], optimizer=Optimizer) assert res == main(20) + def test_simple_recursion_with_exc(self): + py.test.skip("Fails") + myjitdriver = JitDriver(greens=[], reds=['n', 'm']) + class Error(Exception): + pass + + def f(n): + m = n - 2 + while True: + myjitdriver.jit_merge_point(n=n, m=m) + n -= 1 + if n == 10: + raise Error + if m == n: + try: + return main(n) * 2 + except Error: + return 2 + myjitdriver.can_enter_jit(n=n, m=m) + def main(n): + if n > 0: + return f(n+1) + else: + return 1 + res = self.meta_interp(main, [20], optimizer=Optimizer) + assert res == main(20) + def test_recursion_three_times(self): myjitdriver = JitDriver(greens=[], reds=['n', 'm', 'total']) def f(n): From antocuni at codespeak.net Mon May 4 23:08:22 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:08:22 +0200 (CEST) Subject: [pypy-svn] r65039 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090504210822.8479116849D@codespeak.net> Author: antocuni Date: Mon May 4 23:08:22 2009 New Revision: 65039 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (contents, props changed) Log: add new tests Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Mon May 4 23:08:22 2009 @@ -0,0 +1,34 @@ +import py +from pypy.jit.backend.cli.runner import CliCPU +from pypy.jit.metainterp.test import test_basic + +class CliJitMixin(test_basic.OOJitMixin): + CPUClass = CliCPU + +class TestBasic(CliJitMixin, test_basic.BasicTests): + # for the individual tests see + # ====> ../../../metainterp/test/test_basic.py + + def skip(self): + py.test.skip("in-progress") + + test_loop = skip + test_string = skip + test_chr2str = skip + test_unicode = skip + test_residual_call = skip + test_constant_across_mp = skip + test_stopatxpolicy = skip + test_we_are_jitted = skip + test_format = skip + test_r_uint = skip + test_getfield = skip + test_getfield_immutable = skip + test_mod_ovf = skip + test_print = skip + test_bridge_from_interpreter = skip + test_bridge_from_interpreter_2 = skip + test_bridge_from_interpreter_3 = skip + test_bridge_from_interpreter_4 = skip + test_instantiate_classes = skip + test_zerodivisionerror = skip From antocuni at codespeak.net Mon May 4 23:22:50 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:22:50 +0200 (CEST) Subject: [pypy-svn] r65040 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090504212250.24A95169E28@codespeak.net> Author: antocuni Date: Mon May 4 23:22:48 2009 New Revision: 65040 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: implement jump: so far, only jumps to the head of the current loop work. test_loop passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 23:22:48 2009 @@ -102,6 +102,7 @@ self.exc_value_field = t_InputArgs.GetField('exc_value') # ---- self.emit_load_inputargs() + self.emit_preamble() self.emit_operations(loop.operations) self.emit_branches() self.emit_end() @@ -193,6 +194,10 @@ box.store(self) i+=1 + def emit_preamble(self): + self.il_loop_start = self.il.DefineLabel() + self.il.MarkLabel(self.il_loop_start) + def emit_operations(self, operations): for op in operations: func = self.operations[op.opnum] @@ -295,6 +300,16 @@ self.il.Emit(OpCodes.Ldfld, self.exc_value_field) self.il.Emit(OpCodes.Brtrue, il_label) + def emit_op_jump(self, op): + target = op.jump_target + assert target is self.loop, 'TODO' + assert len(op.args) == len(target.inputargs) + i = 0 + for i in range(len(op.args)): + op.args[i].load(self) + target.inputargs[i].store(self) + self.il.Emit(OpCodes.Br, self.il_loop_start) + def not_implemented(self, op): raise NotImplementedError @@ -304,7 +319,6 @@ emit_op_guard_nonvirtualized = not_implemented emit_op_setarrayitem_gc = not_implemented emit_op_unicodelen = not_implemented - emit_op_jump = not_implemented emit_op_setfield_raw = not_implemented emit_op_cast_ptr_to_int = not_implemented emit_op_newunicode = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 4 23:22:48 2009 @@ -5,6 +5,7 @@ from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model from pypy.jit.backend.minimal.runner import cached_method +from pypy.jit.backend.llgraph.runner import TypeDescr from pypy.jit.backend.cli.method import Method from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -30,6 +31,10 @@ def calldescrof(self, FUNC, ARGS, RESULT): return StaticMethDescr(FUNC, ARGS, RESULT) + @cached_method('_typecache') + def typedescrof(self, TYPE): + return TypeDescr(TYPE) + # ---------------------- def compile_operations(self, loop): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Mon May 4 23:22:48 2009 @@ -12,7 +12,6 @@ def skip(self): py.test.skip("in-progress") - test_loop = skip test_string = skip test_chr2str = skip test_unicode = skip From cfbolz at codespeak.net Mon May 4 23:35:44 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 May 2009 23:35:44 +0200 (CEST) Subject: [pypy-svn] r65041 - in pypy/branch/tagged-pointers-framework/pypy: config rpython/memory/gc Message-ID: <20090504213544.CE4C4169E28@codespeak.net> Author: cfbolz Date: Mon May 4 23:35:44 2009 New Revision: 65041 Modified: pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py Log: In theory, this should be enough. In practise, it obviously segfaults. Modified: pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py Mon May 4 23:35:44 2009 @@ -186,8 +186,7 @@ BoolOption("withsmallint", "use tagged integers", default=False, - requires=[("translation.gc", "boehm"), - ("objspace.std.withprebuiltint", False)]), + requires=[("objspace.std.withprebuiltint", False)]), BoolOption("withprebuiltint", "prebuild commonly used int objects", default=False), Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py Mon May 4 23:35:44 2009 @@ -178,7 +178,7 @@ def points_to_valid_gc_object(self, addr): pointsto = addr.address[0] - return pointsto != NULL + return pointsto != NULL and llmemory.cast_adr_to_int(pointsto) & 1 == 0 def debug_check_consistency(self): """To use after a collection. If self.DEBUG is set, this From antocuni at codespeak.net Mon May 4 23:36:02 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:36:02 +0200 (CEST) Subject: [pypy-svn] r65042 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090504213602.BDD30169E28@codespeak.net> Author: antocuni Date: Mon May 4 23:36:02 2009 New Revision: 65042 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: start to implement oosend, but stop here because there is no chance to make it working without translating Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 23:36:02 2009 @@ -310,6 +310,11 @@ target.inputargs[i].store(self) self.il.Emit(OpCodes.Br, self.il_loop_start) + def emit_op_call(self, op): + raise NotImplementedError + + emit_op_call_pure = emit_op_call + def not_implemented(self, op): raise NotImplementedError @@ -336,10 +341,8 @@ emit_op_getfield_gc_pure = not_implemented emit_op_getarrayitem_gc = not_implemented emit_op_getfield_gc = not_implemented - emit_op_call_pure = not_implemented emit_op_strlen = not_implemented emit_op_newstr = not_implemented - emit_op_call = not_implemented emit_op_strsetitem = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 4 23:36:02 2009 @@ -31,6 +31,10 @@ def calldescrof(self, FUNC, ARGS, RESULT): return StaticMethDescr(FUNC, ARGS, RESULT) + @cached_method('_methcache') + def methdescrof(self, SELFTYPE, methname): + return MethDescr(SELFTYPE, methname) + @cached_method('_typecache') def typedescrof(self, TYPE): return TypeDescr(TYPE) @@ -65,6 +69,12 @@ funcbox, args = args[0], args[1:] return calldescr.callfunc(funcbox, args) + def do_oosend(self, args, descr=None): + assert isinstance(descr, MethDescr) + selfbox = args[0] + argboxes = args[1:] + return descr.callmeth(selfbox, argboxes) + # ---------------------------------------------------------------------- @@ -80,6 +90,26 @@ if RESULT is not ootype.Void: return boxresult(RESULT, res) self.callfunc = callfunc + self.funcclass = dotnet.classof(FUNC) + + +class MethDescr(AbstractMethDescr): + + callmeth = None + + def __init__(self, SELFTYPE, methname): + from pypy.jit.backend.llgraph.runner import boxresult, make_getargs + _, meth = SELFTYPE._lookup(methname) + METH = ootype.typeOf(meth) + getargs = make_getargs(METH.ARGS) + def callmeth(selfbox, argboxes): + selfobj = ootype.cast_from_object(SELFTYPE, selfbox.getobj()) + meth = getattr(selfobj, methname) + methargs = getargs(argboxes) + res = meth(*methargs) + if METH.RESULT is not ootype.Void: + return boxresult(METH.RESULT, res) + self.callmeth = callmeth CPU = CliCPU Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Mon May 4 23:36:02 2009 @@ -10,24 +10,28 @@ # ====> ../../../metainterp/test/test_basic.py def skip(self): + py.test.skip("works only after translation") + + def _skip(self): py.test.skip("in-progress") test_string = skip - test_chr2str = skip - test_unicode = skip - test_residual_call = skip - test_constant_across_mp = skip - test_stopatxpolicy = skip - test_we_are_jitted = skip - test_format = skip - test_r_uint = skip - test_getfield = skip - test_getfield_immutable = skip - test_mod_ovf = skip - test_print = skip - test_bridge_from_interpreter = skip - test_bridge_from_interpreter_2 = skip - test_bridge_from_interpreter_3 = skip - test_bridge_from_interpreter_4 = skip - test_instantiate_classes = skip - test_zerodivisionerror = skip + + test_chr2str = _skip + test_unicode = _skip + test_residual_call = _skip + test_constant_across_mp = _skip + test_stopatxpolicy = _skip + test_we_are_jitted = _skip + test_format = _skip + test_r_uint = _skip + test_getfield = _skip + test_getfield_immutable = _skip + test_mod_ovf = _skip + test_print = _skip + test_bridge_from_interpreter = _skip + test_bridge_from_interpreter_2 = _skip + test_bridge_from_interpreter_3 = _skip + test_bridge_from_interpreter_4 = _skip + test_instantiate_classes = _skip + test_zerodivisionerror = _skip From antocuni at codespeak.net Mon May 4 23:45:55 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:45:55 +0200 (CEST) Subject: [pypy-svn] r65043 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090504214555.A81EF1684AE@codespeak.net> Author: antocuni Date: Mon May 4 23:45:55 2009 New Revision: 65043 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: bah, start implementing emit_op_new_with_vtable, but need to stop again because it can't work without translation Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 4 23:45:55 2009 @@ -5,7 +5,8 @@ from pypy.translator.cli.dotnet import CLR from pypy.translator.cli import opcodes from pypy.jit.metainterp import history -from pypy.jit.metainterp.history import AbstractValue, Const, ConstInt +from pypy.jit.metainterp.history import (AbstractValue, Const, ConstInt, + ConstObj) from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend.cli.methodfactory import get_method_wrapper @@ -310,6 +311,11 @@ target.inputargs[i].store(self) self.il.Emit(OpCodes.Br, self.il_loop_start) + def emit_op_new_with_vtable(self, op): + assert isinstance(op.args[0], ConstObj) + cls = ootype.cast_from_object(ootype.Class, op.args[0].getobj()) + raise NotImplementedError # XXX finish me + def emit_op_call(self, op): raise NotImplementedError @@ -337,7 +343,6 @@ emit_op_arraylen_gc = not_implemented emit_op_unicodesetitem = not_implemented emit_op_getfield_raw_pure = not_implemented - emit_op_new_with_vtable = not_implemented emit_op_getfield_gc_pure = not_implemented emit_op_getarrayitem_gc = not_implemented emit_op_getfield_gc = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 4 23:45:55 2009 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model from pypy.jit.backend.minimal.runner import cached_method -from pypy.jit.backend.llgraph.runner import TypeDescr +from pypy.jit.backend.llgraph.runner import TypeDescr, FieldDescr from pypy.jit.backend.cli.method import Method from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -39,6 +39,10 @@ def typedescrof(self, TYPE): return TypeDescr(TYPE) + @cached_method('_fieldcache') + def fielddescrof(self, T, fieldname): + return FieldDescr(T, fieldname) + # ---------------------- def compile_operations(self, loop): @@ -64,6 +68,19 @@ # ---------------------- + def do_new_with_vtable(self, args, typedescr): + assert isinstance(typedescr, TypeDescr) + assert len(args) == 1 # but we don't need it, so ignore + return typedescr.create() + + def do_getfield_gc(self, args, fielddescr): + assert isinstance(fielddescr, FieldDescr) + return fielddescr.getfield(args[0]) + + def do_setfield_gc(self, args, fielddescr): + assert isinstance(fielddescr, FieldDescr) + return fielddescr.setfield(args[0], args[1]) + def do_call(self, args, calldescr): assert isinstance(calldescr, StaticMethDescr) funcbox, args = args[0], args[1:] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Mon May 4 23:45:55 2009 @@ -16,11 +16,11 @@ py.test.skip("in-progress") test_string = skip + test_chr2str = skip + test_unicode = skip + test_residual_call = skip + test_constant_across_mp = skip - test_chr2str = _skip - test_unicode = _skip - test_residual_call = _skip - test_constant_across_mp = _skip test_stopatxpolicy = _skip test_we_are_jitted = _skip test_format = _skip From antocuni at codespeak.net Mon May 4 23:55:10 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 May 2009 23:55:10 +0200 (CEST) Subject: [pypy-svn] r65044 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090504215510.416FB1684DD@codespeak.net> Author: antocuni Date: Mon May 4 23:55:09 2009 New Revision: 65044 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: two tests pass out of the box, other three cannot be executed directly Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Mon May 4 23:55:09 2009 @@ -20,13 +20,11 @@ test_unicode = skip test_residual_call = skip test_constant_across_mp = skip + test_format = skip + test_getfield = skip + test_getfield_immutable = skip test_stopatxpolicy = _skip - test_we_are_jitted = _skip - test_format = _skip - test_r_uint = _skip - test_getfield = _skip - test_getfield_immutable = _skip test_mod_ovf = _skip test_print = _skip test_bridge_from_interpreter = _skip From fijal at codespeak.net Tue May 5 01:15:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 May 2009 01:15:57 +0200 (CEST) Subject: [pypy-svn] r65045 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090504231557.024BB169E28@codespeak.net> Author: fijal Date: Tue May 5 01:15:53 2009 New Revision: 65045 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Last case of calls Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 01:15:53 2009 @@ -2,7 +2,8 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rffi from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop -from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr, BoxPtr +from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr, BoxPtr,\ + BoxInt from pypy.rpython.annlowlevel import llhelper from pypy.rlib.rarithmetic import intmask from pypy.rpython.llinterp import LLException @@ -38,8 +39,10 @@ kwds['hints'] = {'vtable': with_vtable._obj} for i in range(r.randrange(1, 5)): rval = r.random() - if rval < 0.5: + if rval < 0.25: TYPE = lltype.Signed + elif rval < 0.5: + TYPE = lltype.Char elif rval < 0.75: TYPE = rffi.UCHAR else: @@ -157,6 +160,8 @@ w = r.choice(builder.intvars) if rffi.cast(lltype.Signed, rffi.cast(TYPE, w.value)) == w.value: break + if not 0 <= w.value <= 256: + w = builder.do(rop.INT_AND, [w, ConstInt(0xff)]) builder.do(self.opnum, [v, w], descr) class NewOperation(test_random.AbstractOperation): @@ -235,6 +240,31 @@ op.suboperations = [ResOperation(rop.FAIL, [], None)] builder.loop.operations.append(op) +# 5. Non raising-call and GUARD_EXCEPTION + +class CallOperationException(BaseCallOperation): + def produce_into(self, builder, r): + subset, f = self.non_raising_func_code(builder, r) + if len(subset) == 0: + RES = lltype.Void + else: + RES = lltype.Signed + TP = lltype.FuncType([lltype.Signed] * len(subset), RES) + ptr = llhelper(lltype.Ptr(TP), f) + c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu) + args = [c_addr] + subset + descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) + self.put(builder, args, descr) + _, vtableptr = builder.get_random_structure_type_and_vtable(r) + exc_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) + op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr()) + subset = builder.subset_of_intvars(r) + op.suboperations = [ResOperation(rop.FAIL, subset, None)] + op._exc_box = None + builder.should_fail_by = op.suboperations[0] + builder.guard_op = op + builder.loop.operations.append(op) + # 2. raising call and guard_exception class RaisingCallOperation(BaseCallOperation): @@ -314,6 +344,7 @@ OPERATIONS.append(RaisingCallOperation(rop.CALL)) OPERATIONS.append(RaisingCallOperationGuardNoException(rop.CALL)) OPERATIONS.append(RaisingCallOperationWrongGuardException(rop.CALL)) + OPERATIONS.append(CallOperationException(rop.CALL)) LLtypeOperationBuilder.OPERATIONS = OPERATIONS Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Tue May 5 01:15:53 2009 @@ -299,7 +299,10 @@ while intmask(result << 2) == (result << 2): result = (result << 2) | (result & 0x3) return result + def get_random_char(): + return chr(get_random_integer() % 256) r.random_integer = get_random_integer + r.random_char = get_random_char return r def get_cpu(): @@ -391,8 +394,8 @@ assert op is self.should_fail_by if (self.guard_op is not None and self.guard_op.is_guard_exception()): - assert cpu.get_exception() - cpu.clear_exception() + if cpu.get_exception(): + cpu.clear_exception() for i, v in enumerate(op.args): value = cpu.get_latest_value_int(i) assert value == self.expected[v], ( @@ -403,8 +406,11 @@ def build_bridge(self): def exc_handling(guard_op): # operations need to start with correct GUARD_EXCEPTION - op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box], - BoxPtr()) + if guard_op._exc_box is None: + op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) + else: + op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box], + BoxPtr()) op.suboperations = [ResOperation(rop.FAIL, [], None)] return op From fijal at codespeak.net Tue May 5 08:21:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 May 2009 08:21:06 +0200 (CEST) Subject: [pypy-svn] r65046 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test Message-ID: <20090505062106.6CF8F169E77@codespeak.net> Author: fijal Date: Tue May 5 08:21:04 2009 New Revision: 65046 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Log: enough hackery to really make this tail call. Still segfaults of course :) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo2.cpp Tue May 5 08:21:04 2009 @@ -1,5 +1,7 @@ /* LLVM includes */ + #include +#include "llvm/LinkAllPasses.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Tue May 5 08:21:04 2009 @@ -31,10 +31,10 @@ o1name = os.path.join(dirname, 'demo1.o') o2name = os.path.join(dirname, 'demo2.o') - do("gcc -c '%s' -o '%s'" % (cname, o1name)) + do("gcc -c '%s' -o '%s' -I/home/fijal/load/llvm/include" % (cname, o1name)) do("g++ -c '%s' -o '%s' `%s --cppflags`" % (cppname, o2name, llvm_config)) - do("g++ -shared '%s' '%s' -o '%s'" % (o1name, o2name, libname) + - " `%s --cflags --ldflags --libs jit engine`" % llvm_config) + do("g++ -shared '%s' '%s' -o '%s' " % (o1name, o2name, libname) + + " `%s --cflags --ldflags --libs jit engine` -lLLVMInstrumentation -lLLVMipo -lLLVMipa -lLLVMTransformUtils -lLLVMAnalysis -lLLVMCore" % llvm_config) compilation_info = ExternalCompilationInfo( library_dirs = [dirname], Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Tue May 5 08:21:04 2009 @@ -26,8 +26,8 @@ def setup_once(self): if not we_are_translated(): teardown_now() - llvm_rffi.LLVM_SetFlags() self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit") + llvm_rffi.LLVM_SetFlags() if sys.maxint == 2147483647: self.ty_int = llvm_rffi.LLVMInt32Type() else: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Tue May 5 08:21:04 2009 @@ -50,7 +50,6 @@ cpu.set_future_value_int(2, 0) cpu.execute_operations(loop) assert cpu.get_latest_value_int(0) == 3*(2**11) - py.test.skip("fails because tail-recursion is not handled yet") cpu.set_future_value_int(0, 2**29) cpu.set_future_value_int(1, 3) cpu.set_future_value_int(2, 0) From antocuni at codespeak.net Tue May 5 10:19:25 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 10:19:25 +0200 (CEST) Subject: [pypy-svn] r65047 - in pypy/branch/pyjitpl5/pypy/rpython/ootypesystem: . test Message-ID: <20090505081925.A657D169F27@codespeak.net> Author: antocuni Date: Tue May 5 10:19:23 2009 New Revision: 65047 Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ooopimpl.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py Log: make sure that bool(ootype.nullruntimeclass) == False Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ooopimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ooopimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ooopimpl.py Tue May 5 10:19:23 2009 @@ -54,9 +54,10 @@ def is_inst(inst): T = ootype.typeOf(inst) - return T is ootype.Object or isinstance(T, (ootype.Instance, - ootype.BuiltinType, - ootype.StaticMethod,)) + return T is ootype.Object or T is ootype.Class or\ + isinstance(T, (ootype.Instance, + ootype.BuiltinType, + ootype.StaticMethod,)) def checkinst(inst): assert is_inst(inst) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py Tue May 5 10:19:23 2009 @@ -906,6 +906,9 @@ def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self._INSTANCE) + def __nonzero__(self): + return self._INSTANCE is not None + nullruntimeclass = _class(None) Class._null = nullruntimeclass Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Tue May 5 10:19:23 2009 @@ -449,3 +449,18 @@ res = interpret(fn, [0], type_system='ootype') assert res == '4' + +def test_bool_class(): + A = Instance("Foo", ROOT) + cls = runtimeClass(A) + def fn(x): + if x: + obj = cls + else: + obj = nullruntimeclass + return bool(obj) + + res = interpret(fn, [0], type_system='ootype') + assert not res + res = interpret(fn, [1], type_system='ootype') + assert res Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py Tue May 5 10:19:23 2009 @@ -644,3 +644,8 @@ b = oonewarray(A, 10) assert ooidentityhash(a) != ooidentityhash(b) +def test_bool_class(): + A = Instance("Foo", ROOT) + cls = runtimeClass(A) + assert bool(cls) + assert not bool(nullruntimeclass) From antocuni at codespeak.net Tue May 5 10:21:44 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 10:21:44 +0200 (CEST) Subject: [pypy-svn] r65048 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090505082144.B0EC5169F40@codespeak.net> Author: antocuni Date: Tue May 5 10:21:43 2009 New Revision: 65048 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: implement some of the exception handling logic. test_mod_ovf passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Tue May 5 10:21:43 2009 @@ -66,6 +66,27 @@ def get_latest_value_obj(self, index): return self.inputargs.objs[index] + def get_exception(self): + exc_value = self.inputargs.exc_value + if exc_value: + assert False, 'TODO' + return ootype.cast_to_object(ootype.nullruntimeclass) + + def get_exc_value(self): + if self.inputargs.exc_value: + assert False, 'TODO' + else: + return ootype.NULL + + def clear_exception(self): + self.inputargs.exc_value = None + + def set_overflow_error(self): + raise NotImplementedError + + def set_zero_division_error(self): + raise NotImplementedError + # ---------------------- def do_new_with_vtable(self, args, typedescr): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Tue May 5 10:21:43 2009 @@ -25,7 +25,6 @@ test_getfield_immutable = skip test_stopatxpolicy = _skip - test_mod_ovf = _skip test_print = _skip test_bridge_from_interpreter = _skip test_bridge_from_interpreter_2 = _skip From antocuni at codespeak.net Tue May 5 10:54:19 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 10:54:19 +0200 (CEST) Subject: [pypy-svn] r65049 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090505085419.8D752169F74@codespeak.net> Author: antocuni Date: Tue May 5 10:54:19 2009 New Revision: 65049 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: more tests that cannot be run withouth translation Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Tue May 5 10:54:19 2009 @@ -23,12 +23,12 @@ test_format = skip test_getfield = skip test_getfield_immutable = skip + test_print = skip + test_bridge_from_interpreter_2 = skip + test_bridge_from_interpreter_3 = skip + test_instantiate_classes = skip + test_zerodivisionerror = skip test_stopatxpolicy = _skip - test_print = _skip test_bridge_from_interpreter = _skip - test_bridge_from_interpreter_2 = _skip - test_bridge_from_interpreter_3 = _skip test_bridge_from_interpreter_4 = _skip - test_instantiate_classes = _skip - test_zerodivisionerror = _skip From antocuni at codespeak.net Tue May 5 13:44:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 13:44:08 +0200 (CEST) Subject: [pypy-svn] r65050 - in pypy/branch/pyjitpl5/pypy: annotation rpython/ootypesystem rpython/ootypesystem/test Message-ID: <20090505114408.2A3D6169F9D@codespeak.net> Author: antocuni Date: Tue May 5 13:44:06 2009 New Revision: 65050 Modified: pypy/branch/pyjitpl5/pypy/annotation/builtin.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Log: test&fix Modified: pypy/branch/pyjitpl5/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/builtin.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/builtin.py Tue May 5 13:44:06 2009 @@ -569,7 +569,8 @@ raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const) def cast_to_object(obj): - assert isinstance(obj.ootype, ootype.OOType) + assert isinstance(obj.ootype, ootype.OOType) or \ + (isinstance(obj, SomeOOClass) and obj.ootype is None) return SomeOOObject() def cast_from_object(T, obj): Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py Tue May 5 13:44:06 2009 @@ -60,7 +60,8 @@ return hop.genop('oodowncast', [v_inst], resulttype = hop.r_result.lowleveltype) def rtype_cast_to_object(hop): - assert isinstance(hop.args_s[0].ootype, ootype.OOType) + assert isinstance(hop.args_s[0].ootype, ootype.OOType) or \ + isinstance(hop.args_s[0], annmodel.SomeOOClass) v_inst = hop.inputarg(hop.args_r[0], arg=0) return hop.genop('cast_to_object', [v_inst], resulttype = hop.r_result.lowleveltype) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Tue May 5 13:44:06 2009 @@ -464,3 +464,10 @@ assert not res res = interpret(fn, [1], type_system='ootype') assert res + +def test_cast_to_object_nullruntimeclass(): + def fn(): + return cast_to_object(nullruntimeclass) + + res = interpret(fn, [], type_system='ootype') + assert cast_from_object(Class, res) == nullruntimeclass From arigo at codespeak.net Tue May 5 13:48:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 13:48:03 +0200 (CEST) Subject: [pypy-svn] r65051 - pypy/branch/pyjitpl5/pypy/jit/backend/llvm Message-ID: <20090505114803.33FF8169FA1@codespeak.net> Author: arigo Date: Tue May 5 13:48:02 2009 New Revision: 65051 Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/conftest.py (contents, props changed) Log: Skip these tests for now. Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/conftest.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/conftest.py Tue May 5 13:48:02 2009 @@ -0,0 +1,5 @@ +import py + +class Directory(py.test.collect.Directory): + def consider_dir(self, path): + py.test.skip("llvm-jit tests skipped") From arigo at codespeak.net Tue May 5 13:53:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 13:53:31 +0200 (CEST) Subject: [pypy-svn] r65052 - pypy/build/bot2/pypybuildbot Message-ID: <20090505115331.BCDC8169F9B@codespeak.net> Author: arigo Date: Tue May 5 13:53:30 2009 New Revision: 65052 Modified: pypy/build/bot2/pypybuildbot/master.py Log: Running our own tests on the branch/pyjitpl5. (Is this all that is needed?) Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Tue May 5 13:53:30 2009 @@ -58,8 +58,8 @@ Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, STACKLESSAPPLVLLINUX32], hour=4, minute=45), - Nightly("nightly-jit", [JITLINUX32], - hour=1, minute=45, branch="branch/pyjitpl5"), + Nightly("nightly-jit", [LINUX32, JITLINUX32], + hour=1, minute=45, branch="branch/pyjitpl5"), ], 'status': [status], From arigo at codespeak.net Tue May 5 14:03:47 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 14:03:47 +0200 (CEST) Subject: [pypy-svn] r65053 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090505120347.B1AD7169F9F@codespeak.net> Author: arigo Date: Tue May 5 14:03:46 2009 New Revision: 65053 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: - generate rop.GETARRAYITEM_GC. - support writing *something* to stdout, even if it's not correct, to get at least an idea of what is generated. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 14:03:46 2009 @@ -15,22 +15,52 @@ test_random.OperationBuilder.__init__(self, *args, **kw) self.vtable_counter = 0 - def get_structptr_var(self, r, must_have_vtable=False): + def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): while True: - if self.ptrvars and r.random() < 0.8: - v, S = r.choice(self.ptrvars) - elif self.prebuilt_ptr_consts and r.random() < 0.7: - v, S, _ = r.choice(self.prebuilt_ptr_consts) + ptrvars = [(v, S) for (v, S) in self.ptrvars + if isinstance(S, type)] + if ptrvars and r.random() < 0.8: + v, S = r.choice(ptrvars) else: - must_have_vtable = must_have_vtable or r.random() < 0.5 - p = self.get_random_structure(r, has_vtable=must_have_vtable) - S = lltype.typeOf(p).TO - v = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, p)) - self.prebuilt_ptr_consts.append((v, S, self.field_values(p))) + prebuilt_ptr_consts = [(v, S) + for (v, S, _) in self.prebuilt_ptr_consts + if isinstance(S, type)] + if prebuilt_ptr_consts and r.random() < 0.7: + v, S = r.choice(prebuilt_ptr_consts) + else: + if type is lltype.Struct: + # create a new constant structure + must_have_vtable = must_have_vtable or r.random() < 0.5 + p = self.get_random_structure(r, + has_vtable=must_have_vtable) + else: + # create a new constant array + p = self.get_random_array(r) + S = lltype.typeOf(p).TO + v = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, p)) + self.prebuilt_ptr_consts.append((v, S, + self.field_values(p))) if not (must_have_vtable and S._names[0] != 'parent'): break return v, S + def get_arrayptr_var(self, r): + return self.get_structptr_var(r, type=lltype.Array) + + def get_random_primitive_type(self, r): + rval = r.random() + if rval < 0.25: + TYPE = lltype.Signed + elif rval < 0.5: + TYPE = lltype.Char + elif rval < 0.75: + TYPE = rffi.UCHAR + else: + TYPE = rffi.SHORT + if not self.HAVE_SHORT_FIELDS: + TYPE = lltype.Signed + return TYPE + def get_random_structure_type(self, r, with_vtable=None): fields = [] kwds = {} @@ -38,17 +68,7 @@ fields.append(('parent', rclass.OBJECT)) kwds['hints'] = {'vtable': with_vtable._obj} for i in range(r.randrange(1, 5)): - rval = r.random() - if rval < 0.25: - TYPE = lltype.Signed - elif rval < 0.5: - TYPE = lltype.Char - elif rval < 0.75: - TYPE = rffi.UCHAR - else: - TYPE = rffi.SHORT - if not self.HAVE_SHORT_FIELDS: - TYPE = lltype.Signed + TYPE = self.get_random_primitive_type(r) fields.append(('f%d' % i, TYPE)) S = lltype.GcStruct('S%d' % self.counter, *fields, **kwds) self.counter += 1 @@ -82,11 +102,29 @@ setattr(p, fieldname, rffi.cast(TYPE, r.random_integer())) return p + def get_random_array_type(self, r): + TYPE = self.get_random_primitive_type(r) + return lltype.GcArray(TYPE) + + def get_random_array(self, r): + A = self.get_random_array_type(r) + length = r.random_integer() % 300 # length: between 0 and 299 + p = lltype.malloc(A, length) + for i in range(length): + p[i] = rffi.cast(A.OF, r.random_integer()) + return p + def field_values(self, p): dic = {} - for fieldname in lltype.typeOf(p).TO._names: - if fieldname != 'parent': - dic[fieldname] = getattr(p, fieldname) + S = lltype.typeOf(p).TO + if isinstance(S, lltype.Struct): + for fieldname in S._names: + if fieldname != 'parent': + dic[fieldname] = getattr(p, fieldname) + else: + assert isinstance(S, lltype.Array) + for i in range(len(p)): + dic[i] = p[i] return dic def print_loop_prebuilt(self, names, writevar, s): @@ -115,7 +153,8 @@ class GuardClassOperation(test_random.GuardOperation): def gen_guard(self, builder, r): ptrvars = [(v, S) for (v, S) in builder.ptrvars - if S._names[0] == 'parent'] + if isinstance(S, lltype.Struct) and + S._names[0] == 'parent'] if not ptrvars: raise test_random.CannotProduceOperation v, S = r.choice(ptrvars) @@ -180,6 +219,33 @@ v_ptr = builder.do(self.opnum, args, self.size_descr(builder, S)) builder.ptrvars.append((v_ptr, S)) +class GetArrayItemOperation(test_random.AbstractOperation): + def field_descr(self, builder, r): + v, A = builder.get_arrayptr_var(r) + array = v.getptr(lltype.Ptr(A)) + length = len(array) + if length == 0: + raise test_random.CannotProduceOperation + v_index = r.choice(builder.intvars) + if not (0 <= v_index.value < length): + v_index = ConstInt(r.random_integer() % length) + descr = builder.cpu.arraydescrof(A) + descr._random_info = 'cpu.arraydescrof(...)' + return v, A, v_index, descr + + def produce_into(self, builder, r): + while True: + try: + v, _, v_index, descr = self.field_descr(builder, r) + self.put(builder, [v, v_index], descr) + except lltype.UninitializedMemoryAccess: + continue + break + +#class NewArrayOperation(test_random.AbstractOperation): +# ... + +# XXX why is the following here, and not in test_random? # there are five options in total: # 1. non raising call and guard_no_exception # 2. raising call and guard_exception @@ -339,6 +405,8 @@ OPERATIONS.append(NewOperation(rop.NEW)) OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE)) + OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC)) + OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) OPERATIONS.append(CallOperation(rop.CALL)) OPERATIONS.append(RaisingCallOperation(rop.CALL)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Tue May 5 14:03:46 2009 @@ -62,24 +62,31 @@ if v in names: args.append(names[v]) elif isinstance(v, ConstAddr): - name = ''.join([v.value.ptr.name[i] - for i in range(len(v.value.ptr.name)-1)]) - args.append( - 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' - % name) + try: + name = ''.join([v.value.ptr.name[i] + for i in range(len(v.value.ptr.name)-1)]) + except AttributeError: + args.append('ConstAddr(...)') + else: + args.append( + 'ConstAddr(llmemory.cast_ptr_to_adr(%s_vtable), cpu)' + % name) else: args.append('ConstInt(%d)' % v.value) if op.descr is None: descrstr = '' else: - descrstr = ', ' + op.descr._random_info + try: + descrstr = ', ' + op.descr._random_info + except AttributeError: + descrstr = ', descr=...' print >>s, ' ResOperation(rop.%s, [%s], %s%s),' % ( opname[op.opnum], ', '.join(args), names[op.result], descrstr) if getattr(op, 'suboperations', None) is not None: subops.append(op) def print_loop(self): - raise PleaseRewriteMe() + #raise PleaseRewriteMe() def update_names(ops): for op in ops: v = op.result @@ -117,8 +124,8 @@ # print >>s, ' cpu = CPU(None, None)' print >>s, " loop = TreeLoop('test')" - print >>s, ' loop.inputargs = [%s]' % ( - ', '.join([names[v] for v in self.loop.inputargs])) + print >>s, ' loop.inputargs = [...]' # % ( + # ', '.join([names[v] for v in self.loop.inputargs])) print >>s, ' loop.operations = [' for op in self.loop.operations: self.process_operation(s, op, names, subops) @@ -136,15 +143,15 @@ #print >>s, ' ResOperation(rop.FAIL, [%s], None)]' % ( # ', '.join([names[v] for v in op.args])) print >>s, ' cpu.compile_operations(loop)' - for i, v in enumerate(self.loop.inputargs): - print >>s, ' cpu.set_future_value_int(%d, %d)' % (i, v.value) + #for i, v in enumerate(self.loop.inputargs): + # print >>s, ' cpu.set_future_value_int(%d, %d)' % (i, v.value) print >>s, ' op = cpu.execute_operations(loop)' if self.should_fail_by is None: for i, v in enumerate(self.loop.operations[-1].args): print >>s, ' assert cpu.get_latest_value_int(%d) == %d' % ( i, v.value) else: - print >>s, ' assert op is loop.operations[%d].suboperations[0]' % self.should_fail_by_num + #print >>s, ' assert op is loop.operations[%d].suboperations[0]' % self.should_fail_by_num for i, v in enumerate(self.should_fail_by.args): print >>s, ' assert cpu.get_latest_value_int(%d) == %d' % ( i, v.value) @@ -377,12 +384,16 @@ self.expected = {} for v in endvars: self.expected[v] = v.value + #builder.print_loop() def clear_state(self): for v, S, fields in self.prebuilt_ptr_consts: container = v.value._obj.container for name, value in fields.items(): - setattr(container, name, value) + if isinstance(name, str): + setattr(container, name, value) + else: + container.setitem(name, value) def run_loop(self): cpu = self.builder.cpu From arigo at codespeak.net Tue May 5 14:06:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 14:06:23 +0200 (CEST) Subject: [pypy-svn] r65054 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090505120623.EC903169FA7@codespeak.net> Author: arigo Date: Tue May 5 14:06:20 2009 New Revision: 65054 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: These two lines included (by accident?) with r65045 don't make sense. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 14:06:20 2009 @@ -199,8 +199,6 @@ w = r.choice(builder.intvars) if rffi.cast(lltype.Signed, rffi.cast(TYPE, w.value)) == w.value: break - if not 0 <= w.value <= 256: - w = builder.do(rop.INT_AND, [w, ConstInt(0xff)]) builder.do(self.opnum, [v, w], descr) class NewOperation(test_random.AbstractOperation): From antocuni at codespeak.net Tue May 5 14:13:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 14:13:04 +0200 (CEST) Subject: [pypy-svn] r65055 - in pypy/branch/pyjitpl5/pypy: jit/tl rpython/test Message-ID: <20090505121304.E4B87169FAC@codespeak.net> Author: antocuni Date: Tue May 5 14:13:04 2009 New Revision: 65055 Modified: 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 pypy/branch/pyjitpl5/pypy/rpython/test/test_llinterp.py Log: - add autopath to pypyjit.py - add a simple loop to pypyjit_demo.py - use optimize.py, it produces kind of good code for simple_loop() - fix test_llinterp as the new conftest doesn't have the option 'view'. I'm sure there is a better way to do it, but I don't know how :-/ 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 Tue May 5 14:13:04 2009 @@ -2,6 +2,7 @@ A file that invokes translation of PyPy with the JIT enabled. """ +import autopath import py, os from pypy.objspace.std import Space 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 Tue May 5 14:13:04 2009 @@ -1,7 +1,8 @@ from pypy.conftest import option from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp import warmspot -from pypy.jit.metainterp.simple_optimize import Optimizer +#from pypy.jit.metainterp.simple_optimize import Optimizer +from pypy.jit.metainterp import optimize as Optimizer from pypy.module.pypyjit.policy import PyPyJitPolicy # Current output: http://paste.pocoo.org/show/106540/ 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 Tue May 5 14:13:04 2009 @@ -4,8 +4,19 @@ __import__('test.' + TESTNAME) print "---ending 1---" +def simple_loop(): + print "simple loop" + i = 0 + N = 100 + step = 3 + while i < N: + i = i + step + print i + + try: - do() + #do() + simple_loop() print "---ending 2---" except BaseException, e: print "---ending 0---" Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_llinterp.py Tue May 5 14:13:04 2009 @@ -45,7 +45,7 @@ a = t.buildannotator(policy=policy) timelog("annotating", a.build_types, func, argtypes) if viewbefore == 'auto': - viewbefore = conftest.option.view + viewbefore = getattr(conftest.option, 'view', False) if viewbefore: a.simplify() t.view() @@ -104,7 +104,7 @@ if len(_lastinterpreted) >= 4: del _tcache[_lastinterpreted.pop(0)] if view == 'auto': - view = conftest.option.view + view = getattr(conftest.option, 'view', False) if view: t.view() return interp, graph From antocuni at codespeak.net Tue May 5 14:14:26 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 14:14:26 +0200 (CEST) Subject: [pypy-svn] r65056 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli jit/backend/cli/test translator/cli/src Message-ID: <20090505121426.3D212169FAC@codespeak.net> Author: antocuni Date: Tue May 5 14:14:25 2009 New Revision: 65056 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Log: lot of translation fixes. First translated tests pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Tue May 5 14:14:25 2009 @@ -92,8 +92,9 @@ self.name = name self.loop = loop self.boxes = {} # box --> local var - self.failing_ops = {} # index --> op - self.branches = [] # (Label, operations) + self.failing_ops = [] # index --> op + self.branches = [] + self.branchlabels = [] self.consts = {} # object --> index self.meth_wrapper = self._get_meth_wrapper() self.il = self.meth_wrapper.get_il_generator() @@ -117,7 +118,8 @@ for av_const, i in self.consts.iteritems(): consts[i] = dotnet.cast_to_native_object(av_const.getobj()) # build the delegate - self.func = self.meth_wrapper.create_delegate(delegatetype, consts) + func = self.meth_wrapper.create_delegate(delegatetype, consts) + self.func = dotnet.clidowncast(func, LoopDelegate) def _get_meth_wrapper(self): restype = dotnet.class2type(cVoid) @@ -141,11 +143,10 @@ def get_index_for_failing_op(self, op): try: - return self.failing_ops[op] - except KeyError: - i = len(self.failing_ops) - self.failing_ops[i] = op - return i + return self.failing_ops.index(op) + except ValueError: + self.failing_ops.append(op) + return len(self.failing_ops)-1 def get_index_for_constant(self, obj): try: @@ -157,10 +158,11 @@ def newbranch(self, op): # sanity check, maybe we can remove it later - for _, myop in self.branches: + for myop in self.branches: assert myop is not op il_label = self.il.DefineLabel() - self.branches.append((il_label, op)) + self.branches.append(op) + self.branchlabels.append(il_label) return il_label def get_inputarg_field(self, type): @@ -208,8 +210,13 @@ def emit_branches(self): while self.branches: branches = self.branches + branchlabels = self.branchlabels self.branches = [] - for il_label, op in branches: + self.branchlabels = [] + assert len(branches) == len(branchlabels) + for i in range(len(branches)): + op = branches[i] + il_label = branchlabels[i] self.il.MarkLabel(il_label) self.emit_operations(op.suboperations) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Tue May 5 14:14:25 2009 @@ -25,8 +25,13 @@ assert rtyper.type_system.name == "ootypesystem" self.stats = stats self.translate_support_code = translate_support_code - self.inputargs = InputArgs() + self.inputargs = None + def get_inputargs(self): + if self.inputargs is None: + self.inputargs = InputArgs() + return self.inputargs + @cached_method('_callcache') def calldescrof(self, FUNC, ARGS, RESULT): return StaticMethDescr(FUNC, ARGS, RESULT) @@ -51,35 +56,37 @@ def execute_operations(self, loop): meth = loop._cli_meth - meth.func(self.inputargs) - return meth.failing_ops[self.inputargs.failed_op] + meth.func(self.get_inputargs()) + return meth.failing_ops[self.inputargs.get_failed_op()] def set_future_value_int(self, index, intvalue): - self.inputargs.ints[index] = intvalue + self.get_inputargs().set_int(index, intvalue) def set_future_value_obj(self, index, objvalue): - self.inputargs.objs[index] = objvalue + obj = dotnet.cast_to_native_object(objvalue) + self.get_inputargs().set_obj(index, obj) def get_latest_value_int(self, index): - return self.inputargs.ints[index] + return self.get_inputargs().get_int(index) def get_latest_value_obj(self, index): - return self.inputargs.objs[index] + obj = self.get_inputargs().get_obj(index) + return dotnet.cast_from_native_object(obj) def get_exception(self): - exc_value = self.inputargs.exc_value + exc_value = self.get_inputargs().get_exc_value() if exc_value: assert False, 'TODO' return ootype.cast_to_object(ootype.nullruntimeclass) def get_exc_value(self): - if self.inputargs.exc_value: + if self.get_inputargs().get_exc_value(): assert False, 'TODO' else: return ootype.NULL def clear_exception(self): - self.inputargs.exc_value = None + self.get_inputargs().set_exc_value(None) def set_overflow_error(self): raise NotImplementedError @@ -94,6 +101,12 @@ assert len(args) == 1 # but we don't need it, so ignore return typedescr.create() + def do_runtimenew(self, args, descr): + classbox = args[0] + classobj = ootype.cast_from_object(ootype.Class, classbox.getobj()) + res = ootype.runtimenew(classobj) + return BoxObj(ootype.cast_to_object(res)) + def do_getfield_gc(self, args, fielddescr): assert isinstance(fielddescr, FieldDescr) return fielddescr.getfield(args[0]) Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Tue May 5 14:14:25 2009 @@ -0,0 +1,28 @@ +import py +from pypy.jit.backend.cli.runner import CliCPU +from pypy.jit.backend.test.support import CliCompiledMixin +from pypy.jit.metainterp.test.test_basic import BasicTests + +class CliTranslatedJitMixin(CliCompiledMixin): + CPUClass = CliCPU + + def meta_interp(self, *args, **kwds): + from pypy.jit.metainterp.simple_optimize import Optimizer + kwds['optimizer'] = Optimizer + return CliCompiledMixin.meta_interp(self, *args, **kwds) + + +class TestBasic(CliTranslatedJitMixin, BasicTests): + # for the individual tests see + # ====> ../../../metainterp/test/test_basic.py + + def skip(self): + py.test.skip('in-progress') + + test_constant_across_mp = skip + test_stopatxpolicy = skip + test_print = skip + test_bridge_from_interpreter = skip + test_bridge_from_interpreter_2 = skip + test_bridge_from_interpreter_3 = skip + test_bridge_from_interpreter_4 = skip Modified: pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Tue May 5 14:14:25 2009 @@ -115,9 +115,44 @@ public int[] ints = new int[32]; public float[] floats = new float[32]; public object[] objs = new object[32]; - public Exception exc_value = null; + public object exc_value = null; public int failed_op = -1; + public int get_int(int i) + { + return ints[i]; + } + + public void set_int(int i, int n) + { + ints[i] = n; + } + + public object get_obj(int i) + { + return objs[i]; + } + + public void set_obj(int i, object o) + { + objs[i] = o; + } + + public object get_exc_value() + { + return exc_value; + } + + public void set_exc_value(object v) + { + exc_value = v; + } + + public int get_failed_op() + { + return failed_op; + } + public void ensure_ints(int n) { if (ints.Length < n) From arigo at codespeak.net Tue May 5 14:17:54 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 14:17:54 +0200 (CEST) Subject: [pypy-svn] r65057 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090505121754.9F1F3169FAE@codespeak.net> Author: arigo Date: Tue May 5 14:17:51 2009 New Revision: 65057 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: rop.SETARRAYITEM_GC. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 14:17:51 2009 @@ -108,7 +108,8 @@ def get_random_array(self, r): A = self.get_random_array_type(r) - length = r.random_integer() % 300 # length: between 0 and 299 + length = (r.random_integer() // 15) % 300 # length: between 0 and 299 + # likely to be small p = lltype.malloc(A, length) for i in range(length): p[i] = rffi.cast(A.OF, r.random_integer()) @@ -240,6 +241,18 @@ continue break +class SetArrayItemOperation(GetArrayItemOperation): + def produce_into(self, builder, r): + v, A, v_index, descr = self.field_descr(builder, r) + while True: + if r.random() < 0.3: + w = ConstInt(r.random_integer()) + else: + w = r.choice(builder.intvars) + if rffi.cast(lltype.Signed, rffi.cast(A.OF, w.value)) == w.value: + break + builder.do(self.opnum, [v, v_index, w], descr) + #class NewArrayOperation(test_random.AbstractOperation): # ... @@ -404,6 +417,7 @@ OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE)) OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC)) + OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC)) OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) OPERATIONS.append(CallOperation(rop.CALL)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Tue May 5 14:17:51 2009 @@ -99,7 +99,8 @@ for op in ops: for arg in op.args: if isinstance(arg, ConstPtr): - writevar(arg, 'const_ptr') + if arg not in names: + writevar(arg, 'const_ptr') if getattr(op, 'suboperations', None) is not None: print_loop_prebuilt(op.suboperations) From arigo at codespeak.net Tue May 5 14:27:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 14:27:48 +0200 (CEST) Subject: [pypy-svn] r65058 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090505122748.07FED169F81@codespeak.net> Author: arigo Date: Tue May 5 14:27:47 2009 New Revision: 65058 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: rop.NEW_ARRAY. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 14:27:47 2009 @@ -218,7 +218,13 @@ v_ptr = builder.do(self.opnum, args, self.size_descr(builder, S)) builder.ptrvars.append((v_ptr, S)) -class GetArrayItemOperation(test_random.AbstractOperation): +class ArrayOperation(test_random.AbstractOperation): + def array_descr(self, builder, A): + descr = builder.cpu.arraydescrof(A) + descr._random_info = 'cpu.arraydescrof(...)' + return descr + +class GetArrayItemOperation(ArrayOperation): def field_descr(self, builder, r): v, A = builder.get_arrayptr_var(r) array = v.getptr(lltype.Ptr(A)) @@ -228,8 +234,7 @@ v_index = r.choice(builder.intvars) if not (0 <= v_index.value < length): v_index = ConstInt(r.random_integer() % length) - descr = builder.cpu.arraydescrof(A) - descr._random_info = 'cpu.arraydescrof(...)' + descr = self.array_descr(builder, A) return v, A, v_index, descr def produce_into(self, builder, r): @@ -253,8 +258,14 @@ break builder.do(self.opnum, [v, v_index, w], descr) -#class NewArrayOperation(test_random.AbstractOperation): -# ... +class NewArrayOperation(ArrayOperation): + def produce_into(self, builder, r): + A = builder.get_random_array_type(r) + v_size = r.choice(builder.intvars) + if not (0 <= v_size.value < 300): + v_size = ConstInt((r.random_integer() // 15) % 300) + v_ptr = builder.do(self.opnum, [v_size], self.array_descr(builder, A)) + builder.ptrvars.append((v_ptr, A)) # XXX why is the following here, and not in test_random? # there are five options in total: @@ -417,8 +428,11 @@ OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE)) OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC)) + OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC)) OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC)) + OPERATIONS.append(NewArrayOperation(rop.NEW_ARRAY)) +for i in range(2): OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) OPERATIONS.append(CallOperation(rop.CALL)) OPERATIONS.append(RaisingCallOperation(rop.CALL)) From arigo at codespeak.net Tue May 5 14:40:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 14:40:45 +0200 (CEST) Subject: [pypy-svn] r65059 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090505124045.4D954168476@codespeak.net> Author: arigo Date: Tue May 5 14:40:44 2009 New Revision: 65059 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: rop.OOIS, rop.OOISNOT, rop.OOISNULL. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 14:40:44 2009 @@ -14,6 +14,8 @@ def __init__(self, *args, **kw): test_random.OperationBuilder.__init__(self, *args, **kw) self.vtable_counter = 0 + self.structure_types = [] + self.structure_types_and_vtables = [] def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): while True: @@ -61,7 +63,9 @@ TYPE = lltype.Signed return TYPE - def get_random_structure_type(self, r, with_vtable=None): + def get_random_structure_type(self, r, with_vtable=None, cache=True): + if cache and self.structure_types and r.random() < 0.5: + return r.choice(self.structure_types) fields = [] kwds = {} if with_vtable: @@ -72,20 +76,25 @@ fields.append(('f%d' % i, TYPE)) S = lltype.GcStruct('S%d' % self.counter, *fields, **kwds) self.counter += 1 + if cache: + self.structure_types.append(S) return S def get_random_structure_type_and_vtable(self, r): + if self.structure_types_and_vtables and r.random() < 0.5: + return r.choice(self.structure_types_and_vtables) vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) vtable.subclassrange_min = self.vtable_counter vtable.subclassrange_max = self.vtable_counter self.vtable_counter += 1 - S = self.get_random_structure_type(r, with_vtable=vtable) + S = self.get_random_structure_type(r, with_vtable=vtable, cache=False) name = S._name vtable.name = lltype.malloc(lltype.Array(lltype.Char), len(name)+1, immortal=True) for i in range(len(name)): vtable.name[i] = name[i] vtable.name[len(name)] = '\x00' + self.structure_types_and_vtables.append((S, vtable)) return S, vtable def get_random_structure(self, r, has_vtable=False): @@ -405,8 +414,10 @@ self.put(builder, args, descr) assert builder.cpu.get_exception() builder.cpu.clear_exception() - _, vtableptr = builder.get_random_structure_type_and_vtable(r) - assert vtableptr != exc + while True: + _, vtableptr = builder.get_random_structure_type_and_vtable(r) + if vtableptr != exc: + break other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu) op = ResOperation(rop.GUARD_EXCEPTION, [other_box], BoxPtr()) op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Tue May 5 14:40:44 2009 @@ -37,11 +37,21 @@ if self.boolvars and r.random() < 0.8: v = r.choice(self.boolvars) elif self.ptrvars and r.random() < 0.4: - v, S = r.choice(self.ptrvars) - if r.random() < 0.5: - v = self.do(rop.OONONNULL, [v]) + v, S = r.choice(self.ptrvars + self.prebuilt_ptr_consts)[:2] + v2, S2 = r.choice(self.ptrvars + self.prebuilt_ptr_consts)[:2] + if S == S2 and not (isinstance(v, ConstPtr) and + isinstance(v2, ConstPtr)): + if r.random() < 0.5: + v = self.do(rop.OOIS, [v, v2]) + else: + v = self.do(rop.OOISNOT, [v, v2]) else: - v = self.do(rop.OOISNULL, [v]) + if isinstance(v, ConstPtr): + v, S = r.choice(self.ptrvars) + if r.random() < 0.5: + v = self.do(rop.OONONNULL, [v]) + else: + v = self.do(rop.OOISNULL, [v]) else: v = r.choice(self.intvars) v = self.do(rop.INT_IS_TRUE, [v]) From arigo at codespeak.net Tue May 5 14:46:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 May 2009 14:46:14 +0200 (CEST) Subject: [pypy-svn] r65060 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090505124614.F36F4169FAE@codespeak.net> Author: arigo Date: Tue May 5 14:46:14 2009 New Revision: 65060 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: rop.ARRAYLEN_GC. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Tue May 5 14:46:14 2009 @@ -276,6 +276,12 @@ v_ptr = builder.do(self.opnum, [v_size], self.array_descr(builder, A)) builder.ptrvars.append((v_ptr, A)) +class ArrayLenOperation(ArrayOperation): + def produce_into(self, builder, r): + v, A = builder.get_arrayptr_var(r) + descr = self.array_descr(builder, A) + self.put(builder, [v], descr) + # XXX why is the following here, and not in test_random? # there are five options in total: # 1. non raising call and guard_no_exception @@ -442,6 +448,7 @@ OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC)) OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC)) OPERATIONS.append(NewArrayOperation(rop.NEW_ARRAY)) + OPERATIONS.append(ArrayLenOperation(rop.ARRAYLEN_GC)) for i in range(2): OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) From antocuni at codespeak.net Tue May 5 16:27:39 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 16:27:39 +0200 (CEST) Subject: [pypy-svn] r65061 - in pypy/branch/pyjitpl5/pypy/rpython: . test Message-ID: <20090505142739.61E29169F8A@codespeak.net> Author: antocuni Date: Tue May 5 16:27:35 2009 New Revision: 65061 Modified: pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py pypy/branch/pyjitpl5/pypy/rpython/test/test_annlowlevel.py Log: implement "oostr", which is the ootype equivalent of llstr Modified: pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/annlowlevel.py Tue May 5 16:27:35 2009 @@ -422,7 +422,6 @@ def llstr(s): from pypy.rpython.lltypesystem.rstr import mallocstr, mallocunicode - # XXX not sure what to do with ootypesystem if strtype is str: ll_s = mallocstr(len(s)) else: @@ -431,6 +430,12 @@ ll_s.chars[i] = c return ll_s + def oostr(s): + if strtype is str: + return ootype.make_string(s) + else: + return ootype.make_unicode(s) + class LLStrEntry(extregistry.ExtRegistryEntry): _about_ = llstr @@ -448,10 +453,21 @@ return hop.genop('same_as', [v_ll_str], resulttype = hop.r_result.lowleveltype) - return hlstr, llstr + class OOStrEntry(extregistry.ExtRegistryEntry): + _about_ = oostr + + def compute_result_annotation(self, s_str): + if strtype is str: + return annmodel.lltype_to_annotation(ootype.String) + else: + return annmodel.lltype_to_annotation(ootype.Unicode) + + specialize_call = LLStrEntry.specialize_call.im_func + + return hlstr, llstr, oostr -hlstr, llstr = make_string_entries(str) -hlunicode, llunicode = make_string_entries(unicode) +hlstr, llstr, oostr = make_string_entries(str) +hlunicode, llunicode, oounicode = make_string_entries(unicode) # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_annlowlevel.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_annlowlevel.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_annlowlevel.py Tue May 5 16:27:35 2009 @@ -4,7 +4,8 @@ from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.lltypesystem.rstr import mallocstr, mallocunicode -from pypy.rpython.annlowlevel import hlstr, llstr +from pypy.rpython.ootypesystem import ootype +from pypy.rpython.annlowlevel import hlstr, llstr, oostr from pypy.rpython.annlowlevel import hlunicode, llunicode class TestLLType(BaseRtypingTest, LLRtypeMixin): @@ -51,3 +52,22 @@ res = self.interpret(f, [self.unicode_to_ll(u"abc")]) assert res == 3 + + +class TestOOType(BaseRtypingTest, OORtypeMixin): + def test_hlstr(self): + s = ootype.make_string("abc") + assert hlstr(s) == "abc" + + def test_oostr(self): + s = oostr("abc") + assert ootype.typeOf(s) == ootype.String + assert s._str == "abc" + + def test_oostr_compile(self): + def f(arg): + s = oostr(hlstr(arg)) + return s.ll_strlen() + + res = self.interpret(f, [self.string_to_ll("abc")]) + assert res == 3 From antocuni at codespeak.net Tue May 5 16:54:59 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 16:54:59 +0200 (CEST) Subject: [pypy-svn] r65062 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090505145459.36D7616840D@codespeak.net> Author: antocuni Date: Tue May 5 16:54:58 2009 New Revision: 65062 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: opimpl_oois 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 May 5 16:54:58 2009 @@ -431,6 +431,7 @@ def opimpl_ptr_ne(self, box1, box2): self.execute(rop.OOISNOT, [box1, box2]) + opimpl_oois = opimpl_ptr_eq @arguments("box", "descr") def opimpl_getfield_gc(self, box, fielddesc): 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 Tue May 5 16:54:58 2009 @@ -569,6 +569,20 @@ # translation? assert res == ootype.oohash(ootype.oostring(5, -1)) + def test_oois(self): + A = ootype.Instance("A", ootype.ROOT) + def f(n): + obj1 = ootype.new(A) + if n: + obj2 = obj1 + else: + obj2 = ootype.new(A) + return obj1 is obj2 + res = self.interp_operations(f, [0]) + assert not res + res = self.interp_operations(f, [1]) + assert res + class TestLLtype(BasicTests, LLJitMixin): From antocuni at codespeak.net Tue May 5 17:10:23 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 17:10:23 +0200 (CEST) Subject: [pypy-svn] r65063 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090505151023.A0A3E169F9D@codespeak.net> Author: antocuni Date: Tue May 5 17:10:22 2009 New Revision: 65063 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Log: sometimes it happens for TYPE to be Void 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 May 5 17:10:22 2009 @@ -86,12 +86,13 @@ cache.append((vt, cpu.sizeof(STRUCT))) elif cpu.is_oo and op.opname == 'new': TYPE = op.args[0].value - cls = ootype.cast_to_object(ootype.runtimeClass(TYPE)) - typedescr = cpu.typedescrof(TYPE) - if not cpu.translate_support_code: - cache[cls] = typedescr - else: - cache.append((cls, typedescr)) + if isinstance(TYPE, ootype.OOType): + cls = ootype.cast_to_object(ootype.runtimeClass(TYPE)) + typedescr = cpu.typedescrof(TYPE) + if not cpu.translate_support_code: + cache[cls] = typedescr + else: + cache.append((cls, typedescr)) return cache testing_gcstruct2vtable = {} From antocuni at codespeak.net Tue May 5 17:11:01 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 17:11:01 +0200 (CEST) Subject: [pypy-svn] r65064 - in pypy/branch/pyjitpl5/pypy/jit: backend backend/llgraph metainterp metainterp/test Message-ID: <20090505151101.2BE9B168436@codespeak.net> Author: antocuni Date: Tue May 5 17:11:00 2009 New Revision: 65064 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/model.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: implement instanceof for ootype 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 May 5 17:11:00 2009 @@ -453,6 +453,11 @@ res = ootype.runtimenew(classobj) return history.BoxObj(ootype.cast_to_object(res)) + def do_instanceof(self, args, typedescr): + assert isinstance(typedescr, TypeDescr) + assert len(args) == 1 + return typedescr.instanceof(args[0]) + def do_getfield_gc(self, args, fielddescr): assert isinstance(fielddescr, FieldDescr) return fielddescr.getfield(args[0]) @@ -614,11 +619,16 @@ array = ootype.cast_from_object(ARRAY, arraybox.getobj()) return boxresult(ootype.Signed, array.ll_length()) + def instanceof(box): + obj = ootype.cast_from_object(ootype.ROOT, box.getobj()) + return history.BoxInt(ootype.instanceof(obj, TYPE)) + self.create = create self.create_array = create_array self.getarrayitem = getarrayitem self.setarrayitem = setarrayitem self.getarraylength = getarraylength + self.instanceof = instanceof class FieldDescr(OODescr): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/model.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/model.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/model.py Tue May 5 17:11:00 2009 @@ -168,3 +168,6 @@ def do_oosend(self, args, descr=None): raise NotImplementedError + + def do_instanceof(self, args, descr=None): + raise NotImplementedError 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 May 5 17:11:00 2009 @@ -707,6 +707,15 @@ self.emit(self.var_position(op.args[1])) self.register_var(op.result) + def serialize_op_instanceof(self, op): + v, c_TYPE = op.args + TYPE = c_TYPE.value + typedescr = self.cpu.typedescrof(TYPE) + self.emit('instanceof') + self.emit(self.var_position(v)) + self.emit(self.get_position(typedescr)) + self.register_var(op.result) + def serialize_op_zero_gc_pointers_inside(self, op): pass # XXX assume Boehm for now 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 May 5 17:11:00 2009 @@ -363,6 +363,10 @@ def opimpl_runtimenew(self, classbox): self.execute(rop.RUNTIMENEW, [classbox]) + @arguments("box", "descr") + def opimpl_instanceof(self, box, typedescr): + self.execute(rop.INSTANCEOF, [box], descr=typedescr) + @arguments("descr", "box") def opimpl_new_array(self, itemsize, countbox): self.execute(rop.NEW_ARRAY, [countbox], descr=itemsize) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Tue May 5 17:11:00 2009 @@ -154,6 +154,7 @@ UNICODEGETITEM = 84 # # ootype operations + INSTANCEOF = 86 OOSEND_PURE = 87 # _ALWAYS_PURE_LAST = 87 # ----- end of always_pure operations ----- 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 Tue May 5 17:11:00 2009 @@ -557,6 +557,21 @@ res = self.interp_operations(f, [0]) assert res == -667 + def test_isinstance(self): + class A: + pass + class B(A): + pass + def fn(n): + if n: + obj = A() + else: + obj = B() + return isinstance(obj, B) + res = self.interp_operations(fn, [0]) + assert res + res = self.interp_operations(fn, [1]) + assert not res class TestOOtype(BasicTests, OOJitMixin): From antocuni at codespeak.net Tue May 5 17:41:09 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 17:41:09 +0200 (CEST) Subject: [pypy-svn] r65065 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090505154109.63FFC169FA5@codespeak.net> Author: antocuni Date: Tue May 5 17:41:08 2009 New Revision: 65065 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_basic.py Log: I don't feel like fighting with oonewcustomdict right now. Write a failing test, and a dummy implementation of it in codewriter, so that it doesn't crash at least during code generation 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 May 5 17:41:08 2009 @@ -707,6 +707,10 @@ self.emit(self.var_position(op.args[1])) self.register_var(op.result) + def serialize_op_oonewcustomdict(self, op): + self.emit('not_implemented') + self.register_var(op.result) + def serialize_op_instanceof(self, op): v, c_TYPE = op.args TYPE = c_TYPE.value 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 May 5 17:41:08 2009 @@ -715,6 +715,10 @@ return self.metainterp.finishframe_exception(self.exception_box, self.exc_value_box) + @arguments() + def opimpl_not_implemented(self): + raise NotImplementedError + # ------------------------------ def setup_call(self, argboxes): 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 Tue May 5 17:41:08 2009 @@ -573,6 +573,28 @@ res = self.interp_operations(fn, [1]) assert not res + def test_r_dict(self): + from pypy.rlib.objectmodel import r_dict + class FooError(Exception): + pass + def myeq(n, m): + return n == m + def myhash(n): + if n < 0: + raise FooError + return -n + def f(n): + d = r_dict(myeq, myhash) + for i in range(10): + d[i] = i*i + try: + return d[n] + except FooError: + return 99 + res = self.interp_operations(f, [5]) + assert res == f(5) + + class TestOOtype(BasicTests, OOJitMixin): def test_oohash(self): @@ -627,3 +649,6 @@ x = lltype.malloc(TP) expected = lltype.cast_opaque_ptr(llmemory.GCREF, x) assert self.interp_operations(f, [x]) == expected + + def test_r_dict(self): + py.test.skip('in-progress') From antocuni at codespeak.net Tue May 5 18:09:47 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 18:09:47 +0200 (CEST) Subject: [pypy-svn] r65066 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090505160947.57369169FA4@codespeak.net> Author: antocuni Date: Tue May 5 18:09:44 2009 New Revision: 65066 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py Log: don't use lltype helpers when using ootypesystem :-). This makes test_dict passing 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 May 5 18:09:44 2009 @@ -1,8 +1,9 @@ from pypy.rpython.lltypesystem import lltype, rclass from pypy.rpython.ootypesystem import ootype from pypy.rpython import rlist -from pypy.rpython.lltypesystem import rdict, rstr +from pypy.rpython.lltypesystem import rstr as ll_rstr, rdict as ll_rdict from pypy.rpython.lltypesystem import rlist as lltypesystem_rlist +from pypy.rpython.ootypesystem import rdict as oo_rdict from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.extregistry import ExtRegistryEntry from pypy.translator.simplify import get_funcobj @@ -24,7 +25,7 @@ def _annotation(a, x): T = lltype.typeOf(x) - if T == lltype.Ptr(rstr.STR): + if T == lltype.Ptr(ll_rstr.STR): t = str else: t = annmodel.lltype_to_annotation(T) @@ -132,89 +133,138 @@ _ll_2_list_getitem_foldable = _ll_2_list_getitem _ll_1_list_len_foldable = _ll_1_list_len -# ---------- dict ---------- +class LLtypeHelpers: -def _ll_0_newdict(DICT): - return rdict.ll_newdict(DICT) -_ll_0_newdict.need_result_type = True + # ---------- dict ---------- -_ll_2_dict_getitem = rdict.ll_dict_getitem -_ll_3_dict_setitem = rdict.ll_dict_setitem -_ll_2_dict_delitem = rdict.ll_dict_delitem -_ll_3_dict_setdefault = rdict.ll_setdefault -_ll_2_dict_contains = rdict.ll_contains -_ll_3_dict_get = rdict.ll_get -_ll_1_dict_copy = rdict.ll_copy -_ll_1_dict_clear = rdict.ll_clear -_ll_2_dict_update = rdict.ll_update + def _ll_0_newdict(DICT): + return ll_rdict.ll_newdict(DICT) + _ll_0_newdict.need_result_type = True -# ---------- dict keys(), values(), items(), iter ---------- + _ll_2_dict_getitem = ll_rdict.ll_dict_getitem + _ll_3_dict_setitem = ll_rdict.ll_dict_setitem + _ll_2_dict_delitem = ll_rdict.ll_dict_delitem + _ll_3_dict_setdefault = ll_rdict.ll_setdefault + _ll_2_dict_contains = ll_rdict.ll_contains + _ll_3_dict_get = ll_rdict.ll_get + _ll_1_dict_copy = ll_rdict.ll_copy + _ll_1_dict_clear = ll_rdict.ll_clear + _ll_2_dict_update = ll_rdict.ll_update -_ll_1_dict_keys = rdict.ll_dict_keys -_ll_1_dict_values = rdict.ll_dict_values -_ll_1_dict_items = rdict.ll_dict_items -_ll_1_dict_keys .need_result_type = True -_ll_1_dict_values.need_result_type = True -_ll_1_dict_items .need_result_type = True + # ---------- dict keys(), values(), items(), iter ---------- -def _ll_1_newdictiter(ITER, d): - return rdict.ll_dictiter(lltype.Ptr(ITER), d) -_ll_1_newdictiter.need_result_type = True + _ll_1_dict_keys = ll_rdict.ll_dict_keys + _ll_1_dict_values = ll_rdict.ll_dict_values + _ll_1_dict_items = ll_rdict.ll_dict_items + _ll_1_dict_keys .need_result_type = True + _ll_1_dict_values.need_result_type = True + _ll_1_dict_items .need_result_type = True -_dictnext_keys = rdict.ll_dictnext_group['keys'] -_dictnext_values = rdict.ll_dictnext_group['values'] -_dictnext_items = rdict.ll_dictnext_group['items'] + def _ll_1_newdictiter(ITER, d): + return ll_rdict.ll_dictiter(lltype.Ptr(ITER), d) + _ll_1_newdictiter.need_result_type = True -def _ll_1_dictiter_nextkeys(iter): - return _dictnext_keys(None, iter) -def _ll_1_dictiter_nextvalues(iter): - return _dictnext_values(None, iter) -def _ll_1_dictiter_nextitems(RES, iter): - return _dictnext_items(lltype.Ptr(RES), iter) -_ll_1_dictiter_nextitems.need_result_type = True + _dictnext_keys = staticmethod(ll_rdict.ll_dictnext_group['keys']) + _dictnext_values = staticmethod(ll_rdict.ll_dictnext_group['values']) + _dictnext_items = staticmethod(ll_rdict.ll_dictnext_group['items']) -# ---------- strings and unicode ---------- + def _ll_1_dictiter_nextkeys(iter): + return LLtypeHelpers._dictnext_keys(None, iter) + def _ll_1_dictiter_nextvalues(iter): + return LLtypeHelpers._dictnext_values(None, iter) + def _ll_1_dictiter_nextitems(RES, iter): + return LLtypeHelpers._dictnext_items(lltype.Ptr(RES), iter) + _ll_1_dictiter_nextitems.need_result_type = True -_ll_5_string_copy_contents = rstr.copy_string_contents + # ---------- strings and unicode ---------- -_ll_1_str_str2unicode = rstr.LLHelpers.ll_str2unicode -_ll_5_unicode_copy_contents = rstr.copy_unicode_contents + _ll_5_string_copy_contents = ll_rstr.copy_string_contents -# --------------- oostring and oounicode ---------------- + _ll_1_str_str2unicode = ll_rstr.LLHelpers.ll_str2unicode + _ll_5_unicode_copy_contents = ll_rstr.copy_unicode_contents -def _ll_2_oostring_signed_foldable(n, base): - return ootype.oostring(n, base) -def _ll_1_oostring_char_foldable(ch): - return ootype.oostring(ch, -1) +class OOtypeHelpers: -def _ll_2_oounicode_signed_foldable(n, base): - return ootype.oounicode(n, base) + # ---------- dict ---------- -def _ll_1_oounicode_unichar_foldable(ch): - return ootype.oounicode(ch, -1) + def _ll_0_newdict(DICT): + return oo_rdict.ll_newdict(DICT) + _ll_0_newdict.need_result_type = True -def _ll_1_oohash_string_foldable(s): - return ootype.oohash(s) + def _ll_3_dict_setitem(d, key, value): + d.ll_set(key, value) -def _ll_1_oohash_unicode_foldable(u): - return ootype.oohash(u) + def _ll_2_dict_contains(d, key): + return d.ll_contains(key) + + def _ll_1_dict_clear(d): + d.ll_clear() + + _ll_2_dict_getitem = oo_rdict.ll_dict_getitem + _ll_2_dict_delitem = oo_rdict.ll_dict_delitem + _ll_3_dict_setdefault = oo_rdict.ll_dict_setdefault + _ll_3_dict_get = oo_rdict.ll_dict_get + _ll_1_dict_copy = oo_rdict.ll_dict_copy + _ll_2_dict_update = oo_rdict.ll_dict_update + + # ---------- dict keys(), values(), items(), iter ---------- + + _ll_1_dict_keys = oo_rdict.ll_dict_keys + _ll_1_dict_values = oo_rdict.ll_dict_values + _ll_1_dict_items = oo_rdict.ll_dict_items + _ll_1_dict_keys .need_result_type = True + _ll_1_dict_values.need_result_type = True + _ll_1_dict_items .need_result_type = True + + def _ll_1_newdictiter(ITER, d): + return oo_rdict.ll_dictiter(ITER, d) + _ll_1_newdictiter.need_result_type = True + + _dictnext_keys = staticmethod(oo_rdict.ll_dictnext_group['keys']) + _dictnext_values = staticmethod(oo_rdict.ll_dictnext_group['values']) + _dictnext_items = staticmethod(oo_rdict.ll_dictnext_group['items']) + + def _ll_1_dictiter_nextkeys(iter): + return OOtypeHelpers._dictnext_keys(None, iter) + def _ll_1_dictiter_nextvalues(iter): + return OOtypeHelpers._dictnext_values(None, iter) + def _ll_1_dictiter_nextitems(RES, iter): + return OOtypeHelpers._dictnext_items(RES, iter) + _ll_1_dictiter_nextitems.need_result_type = True + + # --------------- oostring and oounicode ---------------- + + def _ll_2_oostring_signed_foldable(n, base): + return ootype.oostring(n, base) + + def _ll_1_oostring_char_foldable(ch): + return ootype.oostring(ch, -1) + + def _ll_2_oounicode_signed_foldable(n, base): + return ootype.oounicode(n, base) + + def _ll_1_oounicode_unichar_foldable(ch): + return ootype.oounicode(ch, -1) + + def _ll_1_oohash_string_foldable(s): + return ootype.oohash(s) + + def _ll_1_oohash_unicode_foldable(u): + return ootype.oohash(u) # ------------------------------------------------------- -def setup_extra_builtin(oopspec_name, nb_args): +def setup_extra_builtin(rtyper, oopspec_name, nb_args): name = '_ll_%d_%s' % (nb_args, oopspec_name.replace('.', '_')) -## try: - wrapper = globals()[name] -## except KeyError: -## if '.' not in oopspec_name: -## raise -## if not isinstance(SELFTYPE, ootype.BuiltinADTType): -## raise -## _, meth = SELFTYPE._lookup(oopspec_name.split('.')[1]) -## if not meth: -## raise -## wrapper = ootype.build_unbound_method_wrapper(meth) + try: + wrapper = globals()[name] + except KeyError: + if rtyper.type_system.name == 'lltypesystem': + Helpers = LLtypeHelpers + else: + Helpers = OOtypeHelpers + wrapper = getattr(Helpers, name).im_func return wrapper # # ____________________________________________________________ @@ -315,7 +365,7 @@ else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) - impl = setup_extra_builtin(oopspec_name, len(args_s)) + impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s)) if getattr(impl, 'need_result_type', False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) 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 Tue May 5 18:09:44 2009 @@ -620,6 +620,9 @@ res = self.interp_operations(f, [1]) assert res + def test_r_dict(self): + py.test.skip('in-progress') + class TestLLtype(BasicTests, LLJitMixin): @@ -649,6 +652,3 @@ x = lltype.malloc(TP) expected = lltype.cast_opaque_ptr(llmemory.GCREF, x) assert self.interp_operations(f, [x]) == expected - - def test_r_dict(self): - py.test.skip('in-progress') Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py Tue May 5 18:09:44 2009 @@ -63,10 +63,11 @@ class TestOOtype(DictTests, OOJitMixin): - def test_dict_keys_values_items(self): - py.test.skip("implement me") - def test_dict_iter(self): - py.test.skip("implement me") +## def test_dict_keys_values_items(self): +## py.test.skip("implement me") +## def test_dict_iter(self): +## py.test.skip("implement me") + pass class TestLLtype(DictTests, LLJitMixin): pass From fijal at codespeak.net Tue May 5 18:20:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 May 2009 18:20:42 +0200 (CEST) Subject: [pypy-svn] r65067 - pypy/trunk/pypy/translator/platform Message-ID: <20090505162042.35DC41683F0@codespeak.net> Author: fijal Date: Tue May 5 18:20:39 2009 New Revision: 65067 Modified: pypy/trunk/pypy/translator/platform/freebsd7.py pypy/trunk/pypy/translator/platform/posix.py Log: (kirma) FreeBSD platform code should not assume make=gmake Modified: pypy/trunk/pypy/translator/platform/freebsd7.py ============================================================================== --- pypy/trunk/pypy/translator/platform/freebsd7.py (original) +++ pypy/trunk/pypy/translator/platform/freebsd7.py Tue May 5 18:20:39 2009 @@ -10,6 +10,7 @@ standalone_only = [] shared_only = [] so_ext = 'so' + make_cmd = 'gmake' def _args_for_shared(self, args): return ['-shared'] + args Modified: pypy/trunk/pypy/translator/platform/posix.py ============================================================================== --- pypy/trunk/pypy/translator/platform/posix.py (original) +++ pypy/trunk/pypy/translator/platform/posix.py Tue May 5 18:20:39 2009 @@ -8,6 +8,7 @@ class BasePosix(Platform): exe_ext = '' + make_cmd = 'make' def __init__(self, cc=None): if cc is None: @@ -108,7 +109,7 @@ else: path = path_to_makefile log.execute('make in %s' % (path,)) - returncode, stdout, stderr = _run_subprocess('make', ['-C', str(path)]) + returncode, stdout, stderr = _run_subprocess(self.make_cmd, ['-C', str(path)]) self._handle_error(returncode, stdout, stderr, path.join('make')) class Definition(object): From fijal at codespeak.net Tue May 5 19:39:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 May 2009 19:39:06 +0200 (CEST) Subject: [pypy-svn] r65068 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090505173906.BDF92169FD9@codespeak.net> Author: fijal Date: Tue May 5 19:39:05 2009 New Revision: 65068 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: A tiny check in that prevents overflow error from being constant folded into int at set_overflow_error. This at least should prevent some segfaults when translated. 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 Tue May 5 19:39:05 2009 @@ -574,7 +574,7 @@ @staticmethod def cast_adr_to_int(x): - res = ll2ctypes.cast_adr_to_int(x) + res = rffi.cast(lltype.Signed, x) return res @staticmethod From antocuni at codespeak.net Tue May 5 20:48:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 20:48:08 +0200 (CEST) Subject: [pypy-svn] r65069 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090505184808.2B901169F62@codespeak.net> Author: antocuni Date: Tue May 5 20:48:04 2009 New Revision: 65069 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: implement ooidentityhash Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Tue May 5 20:48:04 2009 @@ -3,6 +3,7 @@ import py from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask from pypy.jit.metainterp.history import BoxInt, ConstInt, check_descr @@ -145,6 +146,10 @@ x = args[0].getobj() != args[1].getobj() return ConstInt(x) +def do_ooidentityhash(cpu, args, descr=None): + obj = args[0].getobj() + return ConstInt(ootype.ooidentityhash(obj)) + # ---------- # the following operations just delegate to the cpu: 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 May 5 20:48:04 2009 @@ -367,6 +367,10 @@ def opimpl_instanceof(self, box, typedescr): self.execute(rop.INSTANCEOF, [box], descr=typedescr) + @arguments("box") + def opimpl_ooidentityhash(self, box): + self.execute(rop.OOIDENTITYHASH, [box], descr=None) + @arguments("descr", "box") def opimpl_new_array(self, itemsize, countbox): self.execute(rop.NEW_ARRAY, [countbox], descr=itemsize) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Tue May 5 20:48:04 2009 @@ -154,6 +154,7 @@ UNICODEGETITEM = 84 # # ootype operations + OOIDENTITYHASH = 85 INSTANCEOF = 86 OOSEND_PURE = 87 # 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 Tue May 5 20:48:04 2009 @@ -606,6 +606,14 @@ # translation? assert res == ootype.oohash(ootype.oostring(5, -1)) + def test_ooidentityhash(self): + def f(): + s1 = ootype.oostring(5, -1) + s2 = ootype.oostring(6, -1) + return ootype.ooidentityhash(s1) == ootype.ooidentityhash(s2) + res = self.interp_operations(f, []) + assert not res + def test_oois(self): A = ootype.Instance("A", ootype.ROOT) def f(n): From antocuni at codespeak.net Tue May 5 21:57:12 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 21:57:12 +0200 (CEST) Subject: [pypy-svn] r65070 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090505195712.40C941684C4@codespeak.net> Author: antocuni Date: Tue May 5 21:57:10 2009 New Revision: 65070 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py Log: don't try to pass void arguments to oosend 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 May 5 21:57:10 2009 @@ -1116,7 +1116,9 @@ methdescr = self.codewriter.get_methdescr(SELFTYPE, methname, False) self.emit('residual_oosend' + kind) self.emit(self.get_position(methdescr)) - self.emit_varargs(op.args[1:]) + non_void_args = [arg for arg in op.args[1:] + if arg.concretetype is not ootype.Void] + self.emit_varargs(non_void_args) self.register_var(op.result) def handle_residual_oosend(self, op): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py Tue May 5 21:57:10 2009 @@ -4,6 +4,14 @@ class DictTests: + def test_dict_set_none(self): + def fn(n): + d = {} + d[0] = None + return bool(d[n]) + res = self.interp_operations(fn, [0]) + assert not res + def test_dict_keys_values_items(self): for name, extract, expected in [('keys', None, 'k'), ('values', None, 'v'), From antocuni at codespeak.net Tue May 5 21:57:42 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 May 2009 21:57:42 +0200 (CEST) Subject: [pypy-svn] r65071 - in pypy/branch/pyjitpl5/pypy: jit/metainterp rpython/ootypesystem Message-ID: <20090505195742.D88581684C4@codespeak.net> Author: antocuni Date: Tue May 5 21:57:42 2009 New Revision: 65071 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py Log: implement oostring of strings and unicode 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 May 5 21:57:42 2009 @@ -241,12 +241,18 @@ def _ll_1_oostring_char_foldable(ch): return ootype.oostring(ch, -1) + def _ll_1_oostring_string_foldable(s): + return ootype.oostring(s, -1) + def _ll_2_oounicode_signed_foldable(n, base): return ootype.oounicode(n, base) def _ll_1_oounicode_unichar_foldable(ch): return ootype.oounicode(ch, -1) + def _ll_1_oounicode_string_foldable(s): + return ootype.oounicode(s, -1) + def _ll_1_oohash_string_foldable(s): return ootype.oohash(s) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py Tue May 5 21:57:42 2009 @@ -439,6 +439,7 @@ class String(AbstractString): SELFTYPE_T = object() CHAR = Char + _name = 'String' # TODO: should it return _null or ''? def _defl(self): @@ -457,6 +458,7 @@ class Unicode(AbstractString): SELFTYPE_T = object() CHAR = UniChar + _name = 'Unicode' # TODO: should it return _null or ''? def _defl(self): From fijal at codespeak.net Tue May 5 22:24:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 May 2009 22:24:27 +0200 (CEST) Subject: [pypy-svn] r65072 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090505202427.79B57169F8D@codespeak.net> Author: fijal Date: Tue May 5 22:24:25 2009 New Revision: 65072 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: Adapt the test so it makes x86 backend explode (GRRRR) 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 Tue May 5 22:24:25 2009 @@ -377,12 +377,14 @@ try: ovfcheck(x< Author: cfbolz Date: Wed May 6 09:39:43 2009 New Revision: 65078 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py Log: missed a copy of trace Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py Wed May 6 09:39:43 2009 @@ -409,14 +409,17 @@ length = (obj + llmemory.gcarrayofptr_lengthoffset).signed[0] item = obj + llmemory.gcarrayofptr_itemsoffset while length > 0: - callback(item, arg) + if self.points_to_valid_gc_object(item): + callback(item, arg) item += llmemory.gcarrayofptr_singleitemoffset length -= 1 return offsets = self.offsets_to_gc_pointers(typeid) i = 0 while i < len(offsets): - callback(obj + offsets[i], arg) + item = obj + offsets[i] + if self.points_to_valid_gc_object(item): + callback(item, arg) i += 1 if self.has_gcptr_in_varsize(typeid): item = obj + self.varsize_offset_to_variable_part(typeid) @@ -426,7 +429,9 @@ while length > 0: j = 0 while j < len(offsets): - callback(item + offsets[j], arg) + itemobj = item + offsets[j] + if self.points_to_valid_gc_object(itemobj): + callback(itemobj, arg) j += 1 item += itemlength length -= 1 From cfbolz at codespeak.net Wed May 6 09:55:30 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 May 2009 09:55:30 +0200 (CEST) Subject: [pypy-svn] r65079 - in pypy/branch/tagged-pointers-framework/pypy/rpython/memory: gc test Message-ID: <20090506075530.5649E168558@codespeak.net> Author: cfbolz Date: Wed May 6 09:55:29 2009 New Revision: 65079 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Log: fix write barrier Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py Wed May 6 09:55:29 2009 @@ -177,8 +177,10 @@ trace._annspecialcase_ = 'specialize:arg(2)' def points_to_valid_gc_object(self, addr): - pointsto = addr.address[0] - return pointsto != NULL and llmemory.cast_adr_to_int(pointsto) & 1 == 0 + return self.is_valid_gc_object(addr.address[0]) + + def is_valid_gc_object(self, addr): + return addr != NULL and llmemory.cast_adr_to_int(addr) & 1 == 0 def debug_check_consistency(self): """To use after a collection. If self.DEBUG is set, this Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py Wed May 6 09:55:29 2009 @@ -413,11 +413,11 @@ def remember_young_pointer(self, addr_struct, addr): ll_assert(not self.is_in_nursery(addr_struct), "nursery object with GCFLAG_NO_YOUNG_PTRS") + if not self.is_valid_gc_object(addr): + return if self.is_in_nursery(addr): self.old_objects_pointing_to_young.append(addr_struct) self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS - elif addr == NULL: - return self.write_into_last_generation_obj(addr_struct, addr) remember_young_pointer._dont_inline_ = True Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Wed May 6 09:55:29 2009 @@ -490,11 +490,17 @@ __slots__ = 'smallint' def meth(self, x): return self.smallint + x + 3 + + class Unrelated(object): + pass + + u = Unrelated() def fn(n): if n > 0: x = B(n) else: x = C(n) + u.x = x # invoke write barrier rgc.collect() return x.meth(100) res = self.interpret(fn, [1000]) From antocuni at codespeak.net Wed May 6 11:04:56 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 11:04:56 +0200 (CEST) Subject: [pypy-svn] r65080 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090506090456.9F31B169EAB@codespeak.net> Author: antocuni Date: Wed May 6 11:04:55 2009 New Revision: 65080 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Log: make sure to use all ootype tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Wed May 6 11:04:55 2009 @@ -5,7 +5,7 @@ class CliJitMixin(test_basic.OOJitMixin): CPUClass = CliCPU -class TestBasic(CliJitMixin, test_basic.BasicTests): +class TestBasic(CliJitMixin, test_basic.TestOOtype): # for the individual tests see # ====> ../../../metainterp/test/test_basic.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Wed May 6 11:04:55 2009 @@ -1,7 +1,7 @@ import py from pypy.jit.backend.cli.runner import CliCPU from pypy.jit.backend.test.support import CliCompiledMixin -from pypy.jit.metainterp.test.test_basic import BasicTests +from pypy.jit.metainterp.test import test_basic class CliTranslatedJitMixin(CliCompiledMixin): CPUClass = CliCPU @@ -12,7 +12,7 @@ return CliCompiledMixin.meta_interp(self, *args, **kwds) -class TestBasic(CliTranslatedJitMixin, BasicTests): +class TestBasic(CliTranslatedJitMixin, test_basic.TestOOtype): # for the individual tests see # ====> ../../../metainterp/test/test_basic.py From antocuni at codespeak.net Wed May 6 11:05:20 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 11:05:20 +0200 (CEST) Subject: [pypy-svn] r65081 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090506090520.E672E169EAB@codespeak.net> Author: antocuni Date: Wed May 6 11:05:20 2009 New Revision: 65081 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: implement oostring for instances 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 Wed May 6 11:05:20 2009 @@ -244,6 +244,9 @@ def _ll_1_oostring_string_foldable(s): return ootype.oostring(s, -1) + def _ll_1_oostring_root_foldable(s): + return ootype.oostring(s, -1) + def _ll_2_oounicode_signed_foldable(n, base): return ootype.oounicode(n, base) @@ -315,6 +318,8 @@ args = op.args[:-1] else: args = op.args + if isinstance(T, ootype.Instance): + T = ootype.ROOT return '%s_%s_foldable' % (op.opname, T._name.lower()), args def get_oohash_oopspec(op): 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 May 6 11:05:20 2009 @@ -628,6 +628,20 @@ res = self.interp_operations(f, [1]) assert res + def test_oostring_instance(self): + A = ootype.Instance("A", ootype.ROOT) + B = ootype.Instance("B", ootype.ROOT) + def f(n): + obj1 = ootype.new(A) + obj2 = ootype.new(B) + s1 = ootype.oostring(obj1, -1) + s2 = ootype.oostring(obj2, -1) + ch1 = s1.ll_stritem_nonneg(1) + ch2 = s2.ll_stritem_nonneg(1) + return ord(ch1) + ord(ch2) + res = self.interp_operations(f, [0]) + assert res == ord('A') + ord('B') + def test_r_dict(self): py.test.skip('in-progress') From antocuni at codespeak.net Wed May 6 12:00:20 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 12:00:20 +0200 (CEST) Subject: [pypy-svn] r65082 - in pypy/branch/pyjitpl5/pypy/rpython: ootypesystem ootypesystem/test test Message-ID: <20090506100020.F1BEE169F13@codespeak.net> Author: antocuni Date: Wed May 6 12:00:19 2009 New Revision: 65082 Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py pypy/branch/pyjitpl5/pypy/rpython/test/test_rpbc.py Log: for the series "how could have it ever worked": make sure that if sm is a _static_method, bool(ootype.null(sm)) == False Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/ootype.py Wed May 6 12:00:19 2009 @@ -277,7 +277,7 @@ def __init__(self, args, result): self.ARGS = tuple(args) self.RESULT = result - self._null = _static_meth(self, _callable=None) + self._null = _null_static_meth(self) def _example(self): _retval = self.RESULT._example() @@ -1188,6 +1188,14 @@ def _as_ptr(self): return self +class _null_static_meth(_null_mixin(_static_meth), _static_meth): + + def __init__(self, STATICMETHOD): + self.__dict__["_TYPE"] = STATICMETHOD + self.__dict__["_name"] = "? (null)" + self.__dict__["_callable"] = None + + class _forward_static_meth(_static_meth): allowed_types = (StaticMethod, ForwardReference) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_ootype.py Wed May 6 12:00:19 2009 @@ -649,3 +649,8 @@ cls = runtimeClass(A) assert bool(cls) assert not bool(nullruntimeclass) + +def test_bool_default_sm(): + SM = StaticMethod([], Void) + sm = SM._defl() + assert not bool(sm) Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_rpbc.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_rpbc.py Wed May 6 12:00:19 2009 @@ -1594,6 +1594,24 @@ self.interpret(f, [int]) + + def test_funcpointer_default_value(self): + def foo(x): return x+1 + class Foo: + func = None + def __init__(self, n): + if n == 1: + self.func = foo + + def fn(n): + a = Foo(n) + if a.func: + return a.func(n) + return -1 + + res = self.interpret(fn, [0]) + assert res == -1 + class TestLLtype(BaseTestRPBC, LLRtypeMixin): pass From cfbolz at codespeak.net Wed May 6 12:26:52 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 May 2009 12:26:52 +0200 (CEST) Subject: [pypy-svn] r65083 - in pypy/branch/tagged-pointers-framework/pypy/rpython/memory: . test Message-ID: <20090506102652.BDEF3169E96@codespeak.net> Author: cfbolz Date: Wed May 6 12:26:50 2009 New Revision: 65083 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Log: Fix gcwrapper to support prebuilt tagged pointers. Doesn't find the bug I am hunting though. Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py Wed May 6 12:26:50 2009 @@ -205,7 +205,8 @@ def reccollect(constants, llvalue): if (isinstance(llvalue, lltype._abstract_ptr) - and llvalue._obj is not None and llvalue._obj not in constants): + and llvalue._obj is not None and llvalue._obj not in constants + and not isinstance(llvalue._obj, int)): TYPE = llvalue._T constants[llvalue._obj] = True if isinstance(TYPE, lltype.Struct): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Wed May 6 12:26:50 2009 @@ -495,7 +495,9 @@ pass u = Unrelated() + u.x = C(47) def fn(n): + rgc.collect() # check that a prebuilt tagged pointer doesn't explode if n > 0: x = B(n) else: From arigo at codespeak.net Wed May 6 12:55:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 12:55:07 +0200 (CEST) Subject: [pypy-svn] r65084 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090506105507.4CFBD168571@codespeak.net> Author: arigo Date: Wed May 6 12:55:06 2009 New Revision: 65084 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: Fix the test to actually test a bit more (now it returns the number of ovfchecks that failed, instead of always 100 or 101). 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 May 6 12:55:06 2009 @@ -1,7 +1,7 @@ import py from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver -from pypy.rlib.rarithmetic import ovfcheck +from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT from pypy.jit.metainterp.policy import StopAtXPolicy @@ -368,18 +368,20 @@ def test_int_lshift_ovf(self): from pypy.jit.metainterp.simple_optimize import Optimizer - myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y', 'm']) def f(x, y, n): + m = 0 while n < 100: - myjitdriver.can_enter_jit(n=n, x=x, y=y) - myjitdriver.jit_merge_point(n=n, x=x, y=y) + myjitdriver.can_enter_jit(n=n, x=x, y=y, m=m) + myjitdriver.jit_merge_point(n=n, x=x, y=y, m=m) y += 1 + y &= (LONG_BIT-1) try: ovfcheck(x< Author: arigo Date: Wed May 6 13:09:08 2009 New Revision: 65085 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Log: Really write test_ovf_operations_reversed, checking the case of INT_xxx_OVF followed by a GUARD_EXCEPTION. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py Wed May 6 13:09:08 2009 @@ -22,6 +22,7 @@ test_passing_guard_class = _skip # GUARD_CLASS test_failing_guards = _skip # GUARD_CLASS test_failing_guard_class = _skip # GUARD_CLASS + test_ovf_operations_reversed = _skip # exception class TestOOtype(OOJitMixin, MinimalTestMixin, OOtypeBackendTest): pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Wed May 6 13:09:08 2009 @@ -152,7 +152,7 @@ 'int') assert res.value == y - def test_ovf_operations(self): + def test_ovf_operations(self, reversed=False): minint = -sys.maxint-1 boom = 'boom' for opnum, testcases in [ @@ -192,15 +192,33 @@ v1 = BoxInt(testcases[0][0]) v2 = BoxInt(testcases[0][1]) v_res = BoxInt() - ops = [ - ResOperation(opnum, [v1, v2], v_res), - ResOperation(rop.GUARD_NO_EXCEPTION, [], None), - ResOperation(rop.FAIL, [v_res], None), - ] + # + if not reversed: + ops = [ + ResOperation(opnum, [v1, v2], v_res), + ResOperation(rop.GUARD_NO_EXCEPTION, [], None), + ResOperation(rop.FAIL, [v_res], None), + ] + ops[1].suboperations = [ResOperation(rop.FAIL, [], None)] + else: + self.cpu.set_overflow_error() + ovferror = self.cpu.get_exception() + self.cpu.clear_exception() + if self.cpu.is_oo: + v_exc = BoxPtr() + c_ovferror = ConstObj(ovferror) + else: + v_exc = BoxObj() + c_ovferror = ConstInt(ovferror) + ops = [ + ResOperation(opnum, [v1, v2], v_res), + ResOperation(rop.GUARD_EXCEPTION, [c_ovferror], v_exc), + ResOperation(rop.FAIL, [], None), + ] + ops[1].suboperations = [ResOperation(rop.FAIL, [v_res], None)] + # if opnum in (rop.INT_NEG_OVF, rop.INT_ABS_OVF): del ops[0].args[1] - ops[1].suboperations = [ResOperation(rop.FAIL, [], - None)] loop = TreeLoop('name') loop.operations = ops loop.inputargs = [v1, v2] @@ -209,36 +227,15 @@ self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) op = self.cpu.execute_operations(loop) - if z == boom: + if (z == boom) ^ reversed: assert op is ops[1].suboperations[0] else: assert op is ops[-1] + if z != boom: assert self.cpu.get_latest_value_int(0) == z - # ---------- - # the same thing but with the exception path reversed -## v1 = BoxInt(testcases[0][0]) -## v2 = BoxInt(testcases[0][1]) -## v_res = BoxInt() -## v_exc = BoxPtr() -## self.cpu.set_overflow_error() -## ovferror = self.cpu.get_exception() -## self.cpu.clear_exception() -## ops = [ -## ResOperation(opnum, [v1, v2], v_res), -## ResOperation(rop.GUARD_EXCEPTION, [ConstInt(ovferror)], v_exc), -## ResOperation(rop.FAIL, [ConstInt(boom)], None), -## ] -## if opnum in (rop.INT_NEG_OVF, rop.INT_ABS_OVF): -## del ops[0].args[1] -## ops[1].suboperations = [ResOperation(rop.FAIL, [ConstInt(v_res)], -## None)] -## loop = TreeLoop('inverted') -## loop.operations = ops -## loop.inputargs = [v1, v2] -## self.cpu.compile_operations(loop) -## for x, y, z in testcases: -## op = self.cpu.execute_operations(loop, [BoxInt(x), BoxInt(y)]) -## assert op.args[0].value == z + + def test_ovf_operations_reversed(self): + self.test_ovf_operations(reversed=True) def test_passing_guards(self): From arigo at codespeak.net Wed May 6 13:31:50 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 13:31:50 +0200 (CEST) Subject: [pypy-svn] r65086 - in pypy/branch/pyjitpl5/pypy/jit/backend: minimal/test test x86/test Message-ID: <20090506113150.0BF76169E51@codespeak.net> Author: arigo Date: Wed May 6 13:31:48 2009 New Revision: 65086 Added: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py - copied unchanged from r65085, pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Removed: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: Rename this Nth file "runner.py" into "runner_test.py". Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py Wed May 6 13:31:48 2009 @@ -1,6 +1,7 @@ import py from pypy.jit.backend.minimal.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.backend.test.runner import LLtypeBackendTest, OOtypeBackendTest +from pypy.jit.backend.test.runner_test import LLtypeBackendTest +from pypy.jit.backend.test.runner_test import OOtypeBackendTest class FakeStats(object): 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 Wed May 6 13:31:48 2009 @@ -8,7 +8,7 @@ from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.executor import execute -from pypy.jit.backend.test.runner import LLtypeBackendTest +from pypy.jit.backend.test.runner_test import LLtypeBackendTest import ctypes import sys From arigo at codespeak.net Wed May 6 14:15:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 14:15:23 +0200 (CEST) Subject: [pypy-svn] r65087 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090506121523.9DAE1169E89@codespeak.net> Author: arigo Date: Wed May 6 14:15:22 2009 New Revision: 65087 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Log: Need to call clear_exception() too. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Wed May 6 14:15:22 2009 @@ -233,6 +233,12 @@ assert op is ops[-1] if z != boom: assert self.cpu.get_latest_value_int(0) == z + ovferror = self.cpu.get_exception() + if ovferror: + assert z == boom + self.cpu.clear_exception() + else: + assert z != boom def test_ovf_operations_reversed(self): self.test_ovf_operations(reversed=True) From arigo at codespeak.net Wed May 6 14:16:06 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 14:16:06 +0200 (CEST) Subject: [pypy-svn] r65088 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090506121606.E83AD169E8B@codespeak.net> Author: arigo Date: Wed May 6 14:15:59 2009 New Revision: 65088 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Support some INT_xxx_OVF operations. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Wed May 6 14:15:59 2009 @@ -282,7 +282,6 @@ descr = self.array_descr(builder, A) self.put(builder, [v], descr) -# XXX why is the following here, and not in test_random? # there are five options in total: # 1. non raising call and guard_no_exception # 2. raising call and guard_exception Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Wed May 6 14:15:59 2009 @@ -1,5 +1,6 @@ import py, sys from pypy.rlib.rarithmetic import intmask, LONG_BIT +from pypy.rpython.lltypesystem import llmemory from pypy.jit.backend.test import conftest as demo_conftest from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstAddr @@ -63,7 +64,6 @@ num = int(k * len(self.intvars)) for i in range(num): subset.append(r.choice(self.intvars)) - r.shuffle(subset) return subset def process_operation(self, s, op, names, subops): @@ -135,8 +135,9 @@ # print >>s, ' cpu = CPU(None, None)' print >>s, " loop = TreeLoop('test')" - print >>s, ' loop.inputargs = [...]' # % ( - # ', '.join([names[v] for v in self.loop.inputargs])) + if hasattr(self.loop, 'inputargs'): + print >>s, ' loop.inputargs = [%s]' % ( + ', '.join([names[v] for v in self.loop.inputargs])) print >>s, ' loop.operations = [' for op in self.loop.operations: self.process_operation(s, op, names, subops) @@ -154,8 +155,10 @@ #print >>s, ' ResOperation(rop.FAIL, [%s], None)]' % ( # ', '.join([names[v] for v in op.args])) print >>s, ' cpu.compile_operations(loop)' - #for i, v in enumerate(self.loop.inputargs): - # print >>s, ' cpu.set_future_value_int(%d, %d)' % (i, v.value) + if hasattr(self.loop, 'inputargs'): + for i, v in enumerate(self.loop.inputargs): + print >>s, ' cpu.set_future_value_int(%d, %d)' % (i, + v.value) print >>s, ' op = cpu.execute_operations(loop)' if self.should_fail_by is None: for i, v in enumerate(self.loop.operations[-1].args): @@ -216,6 +219,20 @@ v_second = v self.put(builder, [v_first, v_second]) +class BinaryOvfOperation(BinaryOperation): + def produce_into(self, builder, r): + BinaryOperation.produce_into(self, builder, r) + exc = builder.cpu.get_exception() + if exc: # OverflowError + builder.cpu.clear_exception() + exc_box = ConstInt(exc) + res_box = BoxPtr() + op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], res_box) + else: + op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) + op.suboperations = [ResOperation(rop.FAIL, [], None)] + builder.loop.operations.append(op) + class GuardOperation(AbstractOperation): def gen_guard(self, builder, r): v = builder.get_bool_var(r) @@ -292,6 +309,21 @@ OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True)) OPERATIONS.append(BooleanUnaryOperation(rop.BOOL_NOT, boolres=True)) +for _op in [rop.INT_ADD_OVF, + rop.INT_SUB_OVF, + rop.INT_MUL_OVF, + ]: + OPERATIONS.append(BinaryOvfOperation(_op)) + +OPERATIONS.append(BinaryOvfOperation(rop.INT_FLOORDIV_OVF, -1, 1)) +OPERATIONS.append(BinaryOvfOperation(rop.INT_MOD_OVF, -1, 1)) +OPERATIONS.append(BinaryOvfOperation(rop.INT_LSHIFT_OVF, LONG_BIT-1)) + +for _op in [rop.INT_NEG_OVF, + rop.INT_ABS_OVF, + ]: + pass #OPERATIONS.append(UnaryOvfOperation(_op)) + OperationBuilder.OPERATIONS = OPERATIONS # ____________________________________________________________ @@ -395,7 +427,8 @@ self.expected = {} for v in endvars: self.expected[v] = v.value - #builder.print_loop() + if demo_conftest.option.output: + builder.print_loop() def clear_state(self): for v, S, fields in self.prebuilt_ptr_consts: @@ -409,21 +442,23 @@ def run_loop(self): cpu = self.builder.cpu self.clear_state() + assert not cpu.get_exception() for i, v in enumerate(self.values): cpu.set_future_value_int(i, v) op = cpu.execute_operations(self.loop) assert op is self.should_fail_by - if (self.guard_op is not None and - self.guard_op.is_guard_exception()): - if cpu.get_exception(): - cpu.clear_exception() for i, v in enumerate(op.args): value = cpu.get_latest_value_int(i) assert value == self.expected[v], ( "Got %d, expected %d" % (value, self.expected[v]) ) + if (self.guard_op is not None and + self.guard_op.is_guard_exception()): + cpu.clear_exception() + else: + assert not cpu.get_exception() def build_bridge(self): def exc_handling(guard_op): From antocuni at codespeak.net Wed May 6 14:18:16 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 14:18:16 +0200 (CEST) Subject: [pypy-svn] r65089 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090506121816.42F0A1684B4@codespeak.net> Author: antocuni Date: Wed May 6 14:18:14 2009 New Revision: 65089 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Log: add support for oostring of unsigneds 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 Wed May 6 14:18:14 2009 @@ -241,6 +241,9 @@ def _ll_1_oostring_char_foldable(ch): return ootype.oostring(ch, -1) + def _ll_1_oostring_unsigned_foldable(n): + return ootype.oostring(n, -1) + def _ll_1_oostring_string_foldable(s): return ootype.oostring(s, -1) From antocuni at codespeak.net Wed May 6 14:18:48 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 14:18:48 +0200 (CEST) Subject: [pypy-svn] r65090 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090506121848.7D6FC169E3E@codespeak.net> Author: antocuni Date: Wed May 6 14:18:47 2009 New Revision: 65090 Added: pypy/branch/pyjitpl5/pypy/jit/tl/conftest.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: add py.test option --ootype to make pypyjit.py ootype friendly Added: pypy/branch/pyjitpl5/pypy/jit/tl/conftest.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/tl/conftest.py Wed May 6 14:18:47 2009 @@ -0,0 +1,5 @@ +class ConftestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypyjit.py options") + group.addoption('--ootype', action="store_true", dest="ootype", default=False, + help="use ootype") 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 Wed May 6 14:18:47 2009 @@ -9,12 +9,18 @@ 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 -from pypy.rpython.annlowlevel import llhelper, llstr, hlstr +from pypy.rpython.annlowlevel import llhelper, llstr, oostr, hlstr from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.interpreter.pycode import PyCode from pypy.translator.goal import unixcheckpoint +if py.test.config.option.ootype: + BACKEND = 'cli' +else: + BACKEND = 'c' + config = get_pypy_config(translating=True) config.translation.backendopt.inline_threshold = 0 set_opt_level(config, level='1') @@ -26,11 +32,19 @@ config.objspace.usemodules._sre = False config.translation.rweakref = False # XXX set_pypy_opt_level(config, level='0') -config.objspace.std.multimethods = 'mrd' -multimethod.Installer = multimethod.InstallerVersion2 config.objspace.std.builtinshortcut = True config.objspace.opcodes.CALL_LIKELY_BUILTIN = True config.objspace.std.withrangelist = True + +if BACKEND == 'c': + config.objspace.std.multimethods = 'mrd' + multimethod.Installer = multimethod.InstallerVersion2 +elif BACKEND == 'cli': + config.objspace.std.multimethods = 'doubledispatch' + multimethod.Installer = multimethod.InstallerVersion1 + config.translation.backend = 'cli' +else: + assert False print config import sys, pdb @@ -58,8 +72,13 @@ code = ec.compiler.compile(source, '?', 'exec', 0) return llstr(space.str_w(dumps(space, code, space.wrap(2)))) -FPTR = lltype.Ptr(lltype.FuncType([], lltype.Ptr(STR))) -read_code_ptr = llhelper(FPTR, read_code) +if BACKEND == 'c': + FPTR = lltype.Ptr(lltype.FuncType([], lltype.Ptr(STR))) + read_code_ptr = llhelper(FPTR, read_code) +else: + llstr = oostr + FUNC = ootype.StaticMethod([], ootype.String) + read_code_ptr = llhelper(FUNC, read_code) def entry_point(): from pypy.module.marshal.interp_marshal import loads @@ -75,6 +94,7 @@ try: interp, graph = get_interpreter(entry_point, [], backendopt=True, config=config, + type_system=config.translation.type_system, policy=PyPyAnnotatorPolicy(space)) except Exception, e: print '%s: %s' % (e.__class__, e) @@ -85,8 +105,13 @@ # print a message, and restart unixcheckpoint.restartable_point(auto='run') - from pypy.jit.tl.pypyjit_child import run_child - run_child(globals(), locals()) + from pypy.jit.tl.pypyjit_child import run_child, run_child_ootype + if BACKEND == 'c': + run_child(globals(), locals()) + elif BACKEND == 'cli': + run_child_ootype(globals(), locals()) + else: + assert False if __name__ == '__main__': 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 May 6 14:18:47 2009 @@ -42,3 +42,17 @@ warmspot.jittify_and_run(interp, graph, [], policy=policy, listops=True, CPUClass=LLtypeCPU, optimizer=Optimizer) + + +def run_child_ootype(glob, loc): + import sys, pdb + interp = loc['interp'] + graph = loc['graph'] + + print 'warmspot.jittify_and_run() started...' + from pypy.jit.backend.llgraph.runner import OOtypeCPU + policy = PyPyJitPolicy(interp.typer.annotator.translator) + option.view = True + warmspot.jittify_and_run(interp, graph, [], policy=policy, + listops=True, CPUClass=OOtypeCPU, + optimizer=Optimizer) From antocuni at codespeak.net Wed May 6 14:19:53 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 14:19:53 +0200 (CEST) Subject: [pypy-svn] r65091 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090506121953.1D91E169E90@codespeak.net> Author: antocuni Date: Wed May 6 14:19:52 2009 New Revision: 65091 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Log: add a note how to run it 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 Wed May 6 14:19:52 2009 @@ -1,5 +1,8 @@ """ A file that invokes translation of PyPy with the JIT enabled. + +Run it with py.test -s --pdb pypyjit.py [--ootype] + """ import autopath From arigo at codespeak.net Wed May 6 14:20:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 14:20:41 +0200 (CEST) Subject: [pypy-svn] r65092 - in pypy/branch/pyjitpl5/pypy/jit/backend: llgraph test Message-ID: <20090506122041.4695A169E91@codespeak.net> Author: arigo Date: Wed May 6 14:20:40 2009 New Revision: 65092 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: * Support in the llgraph backend simple exceptions without a rtyper. * Support for the remaining INT_xxx_OVF operations in test_random.py. (using real multiple inheritance, argh!) 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 May 6 14:20:40 2009 @@ -887,15 +887,26 @@ global _last_exception _last_exception = None +_pseudo_exceptions = {} + def _set_error(Class): global _last_exception - llframe = _llinterp.frame_class(None, None, _llinterp) - try: - llframe.make_llexception(Class()) - except LLException, e: - _last_exception = e + if _llinterp.typer is not None: + llframe = _llinterp.frame_class(None, None, _llinterp) + try: + llframe.make_llexception(Class()) + except LLException, e: + _last_exception = e + else: + assert 0, "should have raised" else: - assert 0, "should have raised" + # for tests, a random emulated ll_inst will do + if Class not in _pseudo_exceptions: + ll_inst = lltype.malloc(rclass.OBJECT) + ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE, + immortal=True) + _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst) + _last_exception = _pseudo_exceptions[Class] def set_overflow_error(): _set_error(OverflowError) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Wed May 6 14:20:40 2009 @@ -176,7 +176,7 @@ class CannotProduceOperation(Exception): pass -class AbstractOperation: +class AbstractOperation(object): def __init__(self, opnum, boolres=False): self.opnum = opnum self.boolres = boolres @@ -219,9 +219,9 @@ v_second = v self.put(builder, [v_first, v_second]) -class BinaryOvfOperation(BinaryOperation): +class AbstractOvfOperation(AbstractOperation): def produce_into(self, builder, r): - BinaryOperation.produce_into(self, builder, r) + super(AbstractOvfOperation, self).produce_into(builder, r) exc = builder.cpu.get_exception() if exc: # OverflowError builder.cpu.clear_exception() @@ -233,6 +233,12 @@ op.suboperations = [ResOperation(rop.FAIL, [], None)] builder.loop.operations.append(op) +class BinaryOvfOperation(AbstractOvfOperation, BinaryOperation): + pass + +class UnaryOvfOperation(AbstractOvfOperation, UnaryOperation): + pass + class GuardOperation(AbstractOperation): def gen_guard(self, builder, r): v = builder.get_bool_var(r) @@ -322,7 +328,7 @@ for _op in [rop.INT_NEG_OVF, rop.INT_ABS_OVF, ]: - pass #OPERATIONS.append(UnaryOvfOperation(_op)) + OPERATIONS.append(UnaryOvfOperation(_op)) OperationBuilder.OPERATIONS = OPERATIONS From antocuni at codespeak.net Wed May 6 14:37:37 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 14:37:37 +0200 (CEST) Subject: [pypy-svn] r65093 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090506123737.D7966169E24@codespeak.net> Author: antocuni Date: Wed May 6 14:37:36 2009 New Revision: 65093 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: don't forget to cast also the newvalue 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 May 6 14:37:36 2009 @@ -734,8 +734,9 @@ op_getarrayitem_gc_pure = op_getarrayitem_gc - def op_setarrayitem_gc(self, typedescr, obj, index, newvalue): + def op_setarrayitem_gc(self, typedescr, obj, index, objnewvalue): array = ootype.cast_from_object(typedescr.ARRAY, obj) + newvalue = ootype.cast_from_object(typedescr.TYPE, objnewvalue) array.ll_setitem_fast(index, newvalue) def op_arraylen_gc(self, typedescr, obj): From arigo at codespeak.net Wed May 6 14:39:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 14:39:56 +0200 (CEST) Subject: [pypy-svn] r65094 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090506123956.43C66169E4C@codespeak.net> Author: arigo Date: Wed May 6 14:39:55 2009 New Revision: 65094 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py Log: Test and fix. 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 Wed May 6 14:39:55 2009 @@ -1045,7 +1045,7 @@ self.eventually_free_var(tmpvar) def consider_int_abs_ovf(self, op, guard_op): - argloc = self.force_allocate_reg(op.args[0], []) + argloc = self.make_sure_var_in_reg(op.args[0], []) tmpvar = TempBox() tmploc = self.force_allocate_reg(tmpvar, [op.args[0]]) resloc = self.force_allocate_reg(op.result, [op.args[0], tmpvar]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py Wed May 6 14:39:55 2009 @@ -283,3 +283,47 @@ assert cpu.get_latest_value_int(18) == 1 assert cpu.get_latest_value_int(19) == -2147483648 assert cpu.get_latest_value_int(20) == 49 + +def test_bug_2(): + v1 = BoxInt() + v2 = BoxInt() + v3 = BoxInt() + v4 = BoxInt() + v5 = BoxInt() + v6 = BoxInt() + v7 = BoxInt() + v8 = BoxInt() + v9 = BoxInt() + v10 = BoxInt() + v11 = BoxInt() + v12 = BoxInt() + v13 = BoxInt() + v14 = BoxInt() + tmp21 = BoxInt() + loop = TreeLoop('test') + loop.inputargs = [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10] + loop.operations = [ + ResOperation(rop.INT_IS_TRUE, [v4], tmp21), + ResOperation(rop.BOOL_NOT, [tmp21], v11), + ResOperation(rop.INT_NEG, [v6], v12), + ResOperation(rop.UINT_LT, [v10, v10], v13), + ResOperation(rop.INT_ABS_OVF, [v5], v14), + ResOperation(rop.GUARD_NO_EXCEPTION, [], None), + ResOperation(rop.FAIL, [v11, v14], None), + ] + loop.operations[-2].suboperations = [ResOperation(rop.FAIL, [], None)] + cpu = CPU(None, None) + cpu.compile_operations(loop) + cpu.set_future_value_int(0, 5) + cpu.set_future_value_int(1, -3) + cpu.set_future_value_int(2, -84) + cpu.set_future_value_int(3, 2) + cpu.set_future_value_int(4, -12) + cpu.set_future_value_int(5, -3) + cpu.set_future_value_int(6, 15) + cpu.set_future_value_int(7, -17) + cpu.set_future_value_int(8, -23) + cpu.set_future_value_int(9, 6) + cpu.execute_operations(loop) + assert cpu.get_latest_value_int(0) == 0 + assert cpu.get_latest_value_int(1) == 12 From antocuni at codespeak.net Wed May 6 14:54:29 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 14:54:29 +0200 (CEST) Subject: [pypy-svn] r65095 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem lltypesystem/test ootypesystem test Message-ID: <20090506125429.7364516855D@codespeak.net> Author: antocuni Date: Wed May 6 14:54:28 2009 New Revision: 65095 Added: pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py - copied unchanged from r65092, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py - copied, changed from r65079, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_rvirtualizable2.py Removed: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_rvirtualizable2.py Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py pypy/branch/pyjitpl5/pypy/rpython/rclass.py Log: (in-progress) port rvirtualizable2.py to ootype, part 1: move rvirtualizable2.py and the logic to select it one level up, and write a proper unit test 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 May 6 14:54:28 2009 @@ -19,7 +19,6 @@ from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel -from pypy.rlib.objectmodel import UnboxedValue from pypy.rlib.rarithmetic import intmask # @@ -606,41 +605,6 @@ return hop.gendirectcall(ll_isinstance, v_obj, v_cls) -def buildinstancerepr(rtyper, classdef, gcflavor='gc'): - 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: - # the UnboxedValue class and its parent classes need a - # special repr for their instances - if len(unboxed) != 1: - raise TyperError("%r has several UnboxedValue subclasses" % ( - classdef,)) - assert gcflavor == 'gc' - from pypy.rpython.lltypesystem import rtagged - return rtagged.TaggedInstanceRepr(rtyper, classdef, unboxed[0]) - class __extend__(pairtype(InstanceRepr, InstanceRepr)): def convert_from_to((r_ins1, r_ins2), v, llops): Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py Wed May 6 14:54:28 2009 @@ -524,8 +524,6 @@ if '_hash_cache_' in self.lowleveltype._allfields(): result._hash_cache_ = hash(value) -buildinstancerepr = InstanceRepr - class __extend__(pairtype(InstanceRepr, InstanceRepr)): def convert_from_to((r_ins1, r_ins2), v, llops): Modified: pypy/branch/pyjitpl5/pypy/rpython/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rclass.py Wed May 6 14:54:28 2009 @@ -22,13 +22,55 @@ try: result = rtyper.instance_reprs[classdef, flavor] except KeyError: - result = rtyper.type_system.rclass.buildinstancerepr( - rtyper, classdef, gcflavor=flavor) + result = buildinstancerepr(rtyper, classdef, gcflavor=flavor) rtyper.instance_reprs[classdef, flavor] = result rtyper.add_pendingsetup(result) return result + +def buildinstancerepr(rtyper, classdef, gcflavor='gc'): + from pypy.rlib.objectmodel import UnboxedValue + from pypy.objspace.flow.model import Constant + + 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 rtyper.type_system.name == 'lltypesystem' + assert len(unboxed) == 0 + assert gcflavor == 'gc' + from pypy.rpython.lltypesystem import rvirtualizable + return rvirtualizable.VirtualizableInstanceRepr(rtyper, classdef) + elif virtualizable2: + assert rtyper.type_system.name == 'lltypesystem' + assert len(unboxed) == 0 + assert gcflavor == 'gc' + from pypy.rpython import rvirtualizable2 + return rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) + elif len(unboxed) == 0: + return rtyper.type_system.rclass.InstanceRepr(rtyper, classdef, gcflavor) + else: + assert rtyper.type_system.name == 'lltypesystem' + # the UnboxedValue class and its parent classes need a + # special repr for their instances + if len(unboxed) != 1: + raise TyperError("%r has several UnboxedValue subclasses" % ( + classdef,)) + assert gcflavor == 'gc' + from pypy.rpython.lltypesystem import rtagged + return rtagged.TaggedInstanceRepr(rtyper, classdef, unboxed[0]) + + class MissingRTypeAttribute(TyperError): pass Copied: pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py (from r65079, pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_rvirtualizable2.py) ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py Wed May 6 14:54:28 2009 @@ -1,6 +1,6 @@ import py from pypy.rpython.lltypesystem import lltype -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin class V(object): @@ -9,12 +9,31 @@ def __init__(self, v): self.v = v -def test_simple(): - def f(v): - vinst = V(v) - return vinst, vinst.v - res = interpret(f, [42]) - assert res.item1 == 42 - res = lltype.normalizeptr(res.item0) - assert res.inst_v == 42 - assert not res.vable_rti +class BaseTest(BaseRtypingTest): + def test_generate_promote_virtualizable(self): + def fn(n): + vinst = V(n) + return vinst.v + _, _, graph = self.gengraph(fn, [int]) + block = graph.startblock + op_getfield = block.operations[-1] + op_promote = block.operations[-2] + assert op_getfield.opname in ('getfield', 'oogetfield') + v_inst = op_getfield.args[0] + assert op_promote.opname == 'promote_virtualizable' + assert op_promote.args[0] is v_inst + +class TestLLtype(LLRtypeMixin, BaseTest): + + def test_simple(self): + def f(v): + vinst = V(v) + return vinst, vinst.v + res = self.interpret(f, [42]) + assert res.item1 == 42 + res = lltype.normalizeptr(res.item0) + assert res.inst_v == 42 + assert not res.vable_rti + +## class TestOOtype(OORtypeMixin, BaseTest): +## pass From arigo at codespeak.net Wed May 6 16:03:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 16:03:26 +0200 (CEST) Subject: [pypy-svn] r65096 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/test backend/x86 metainterp Message-ID: <20090506140326.3A528169E8F@codespeak.net> Author: arigo Date: Wed May 6 16:03:25 2009 New Revision: 65096 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Log: Remove INT_ABS_OVF, INT_MOD_OVF and INT_FLOORDIV_OVF. These operations are too obscure to implement. Instead they can be done by the front-end. 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 May 6 16:03:25 2009 @@ -70,13 +70,10 @@ 'int_invert' : (('int',), 'int'), 'int_abs' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), - 'int_mod_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), - 'int_floordiv_ovf': (('int', 'int'), 'int'), 'int_neg_ovf' : (('int',), 'int'), 'int_lshift_ovf' : (('int', 'int'), 'int'), - 'int_abs_ovf' : (('int',), 'int'), 'bool_not' : (('bool',), 'bool'), 'uint_add' : (('int', 'int'), 'int'), 'uint_sub' : (('int', 'int'), 'int'), Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Wed May 6 16:03:25 2009 @@ -168,26 +168,11 @@ (rop.INT_NEG_OVF, [(-sys.maxint, 0, sys.maxint), (sys.maxint, 0, -sys.maxint), (minint, 0, boom)]), - (rop.INT_ABS_OVF, [(-sys.maxint, 0, sys.maxint), - (sys.maxint, 0, sys.maxint), - (minint, 0, boom)]), - (rop.INT_MOD_OVF, [(11, 3, 2), - (-11, 3, -2), - (11, -3, 2), - (-11, -3, -2), - (minint, -1, boom)]), (rop.INT_LSHIFT_OVF, [(0x1f87611, 6, 0x7e1d8440), (-0x1f87611, 6, -0x7e1d8440), (sys.maxint//8+1, 3, boom), (minint//2-1, 1, boom), (0, 345, 0)]), - (rop.INT_FLOORDIV_OVF, [(110, 3, 36), - (-110, 3, -36), - (110, -3, -36), - (-110, -3, 36), - (-110, -1, 110), - (minint, 1, minint), - (minint, -1, boom)]), ]: v1 = BoxInt(testcases[0][0]) v2 = BoxInt(testcases[0][1]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Wed May 6 16:03:25 2009 @@ -321,12 +321,9 @@ ]: OPERATIONS.append(BinaryOvfOperation(_op)) -OPERATIONS.append(BinaryOvfOperation(rop.INT_FLOORDIV_OVF, -1, 1)) -OPERATIONS.append(BinaryOvfOperation(rop.INT_MOD_OVF, -1, 1)) OPERATIONS.append(BinaryOvfOperation(rop.INT_LSHIFT_OVF, LONG_BIT-1)) for _op in [rop.INT_NEG_OVF, - rop.INT_ABS_OVF, ]: OPERATIONS.append(UnaryOvfOperation(_op)) 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 Wed May 6 16:03:25 2009 @@ -355,7 +355,12 @@ def _binaryop_ovf(asmop, can_swap=False): def genop_binary_ovf(self, op, guard_op, addr, arglocs, result_loc): getattr(self.mc, asmop)(arglocs[0], arglocs[1]) - self.mc.JO(rel32(addr)) + if guard_op.opnum == rop.GUARD_NO_EXCEPTION: + self.mc.JO(rel32(addr)) + elif guard_op.opnum == rop.GUARD_EXCEPTION: + self.mc.JNO(rel32(addr)) + else: + raise AssertionError return genop_binary_ovf def _cmpop(cond, rev_cond): @@ -415,7 +420,12 @@ def genop_guard_int_neg_ovf(self, op, guard_op, addr, arglocs, result_loc): self.mc.NEG(result_loc) - self.mc.JO(rel32(addr)) + if guard_op.opnum == rop.GUARD_NO_EXCEPTION: + self.mc.JO(rel32(addr)) + elif guard_op.opnum == rop.GUARD_EXCEPTION: + self.mc.JNO(rel32(addr)) + else: + raise AssertionError genop_int_lt = _cmpop("L", "G") genop_int_le = _cmpop("LE", "GE") @@ -476,9 +486,18 @@ self.mc.MOV(tmploc, loc) self.mc.SHL(tmploc, loc2) self.mc.SAR(tmploc, loc2) - self.mc.CMP(tmploc, loc) - self.mc.JNE(rel32(addr)) - self.mc.SHL(loc, loc2) + if guard_op.opnum == rop.GUARD_NO_EXCEPTION: + self.mc.CMP(tmploc, loc) + self.mc.JNE(rel32(addr)) + self.mc.SHL(loc, loc2) + elif guard_op.opnum == rop.GUARD_EXCEPTION: + # xxx even more inefficient + self.mc.SUB(tmploc, loc) + self.mc.SHL(loc, loc2) + self.mc.CMP(tmploc, imm8(0)) + self.mc.JE(rel32(addr)) + else: + raise AssertionError def genop_int_is_true(self, op, arglocs, resloc): argloc = arglocs[0] @@ -497,12 +516,6 @@ self.mc.SBB(resloc, argloc) self.mc.SBB(tmploc, tmploc) self.mc.XOR(resloc, tmploc) - # in case of overflow, the result is negative again (-sys.maxint-1) - # and the L flag is set. - - def genop_guard_int_abs_ovf(self, op, guard_op, addr, arglocs, resloc): - self.genop_int_abs(op, arglocs, resloc) - self.mc.JL(rel32(addr)) def genop_guard_oononnull(self, op, guard_op, addr, arglocs, resloc): loc = arglocs[0] @@ -534,17 +547,7 @@ self.mc.CDQ() self.mc.IDIV(ecx) - def genop_guard_int_mod_ovf(self, op, guard_op, addr, arglocs, result_loc): - # detect the combination "eax=-sys.maxint-1, ecx=-1" - self.mc.LEA(edx, mem(eax, sys.maxint)) # edx=-1 if eax=-sys.maxint-1 - self.mc.AND(edx, ecx) # edx=-1 only in the case above - self.mc.CMP(edx, imm(-1)) - self.mc.JE(rel32(addr)) - self.mc.CDQ() - self.mc.IDIV(ecx) - genop_int_floordiv = genop_int_mod - genop_guard_int_floordiv_ovf = genop_guard_int_mod_ovf def genop_new_with_vtable(self, op, arglocs, result_loc): assert result_loc is eax 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 Wed May 6 16:03:25 2009 @@ -281,7 +281,9 @@ if not canfold: # detect overflow ops if op.is_ovf(): - assert operations[i + 1].opnum == rop.GUARD_NO_EXCEPTION + num = operations[i + 1].opnum + assert (num == rop.GUARD_NO_EXCEPTION or + num == rop.GUARD_EXCEPTION) nothing = oplist[op.opnum](self, op, operations[i + 1]) i += 1 elif self.can_optimize_cmp_op(op, i, operations): @@ -797,26 +799,10 @@ self._consider_int_div_or_mod(op, edx, eax) self.Perform(op, [eax, ecx], edx) - def consider_int_mod_ovf(self, op, guard_op): - self._consider_int_div_or_mod(op, edx, eax) - self.position += 1 - regalloc = self.regalloc_for_guard(guard_op) - self.perform_with_guard(op, guard_op, regalloc, [eax, ecx], edx, - overflow=True) - self.eventually_free_vars(guard_op.inputargs) - def consider_int_floordiv(self, op, ignored): self._consider_int_div_or_mod(op, eax, edx) self.Perform(op, [eax, ecx], eax) - def consider_int_floordiv_ovf(self, op, guard_op): - self._consider_int_div_or_mod(op, eax, edx) - self.position += 1 - regalloc = self.regalloc_for_guard(guard_op) - self.perform_with_guard(op, guard_op, regalloc, [eax, ecx], eax, - overflow=True) - self.eventually_free_vars(guard_op.inputargs) - def _consider_compop(self, op, guard_op): vx = op.args[0] vy = op.args[1] @@ -1044,19 +1030,6 @@ self.eventually_free_var(op.args[0]) self.eventually_free_var(tmpvar) - def consider_int_abs_ovf(self, op, guard_op): - argloc = self.make_sure_var_in_reg(op.args[0], []) - tmpvar = TempBox() - tmploc = self.force_allocate_reg(tmpvar, [op.args[0]]) - resloc = self.force_allocate_reg(op.result, [op.args[0], tmpvar]) - self.position += 1 - regalloc = self.regalloc_for_guard(guard_op) - self.perform_with_guard(op, guard_op, regalloc, [argloc, tmploc], - resloc, overflow=True) - self.eventually_free_vars(guard_op.inputargs) - self.eventually_free_var(op.args[0]) - self.eventually_free_var(tmpvar) - def _consider_nullity(self, op, guard_op): # doesn't need a register in arg if guard_op is not None: 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 May 6 16:03:25 2009 @@ -630,17 +630,35 @@ self.emit('check_zerodivisionerror', self.var_position(op.args[1])) self.default_serialize_op(op, 'int_mod') + def serialize_op_int_mod_ovf(self, op): + self.emit('check_div_overflow', self.var_position(op.args[0]), + self.var_position(op.args[1])) + self.default_serialize_op(op, 'int_mod') + def serialize_op_int_mod_ovf_zer(self, op): self.emit('check_zerodivisionerror', self.var_position(op.args[1])) - self.default_serialize_op(op, 'int_mod_ovf') + self.emit('check_div_overflow', self.var_position(op.args[0]), + self.var_position(op.args[1])) + self.default_serialize_op(op, 'int_mod') def serialize_op_int_floordiv_zer(self, op): self.emit('check_zerodivisionerror', self.var_position(op.args[1])) self.default_serialize_op(op, 'int_floordiv') + def serialize_op_int_floordiv_ovf(self, op): + self.emit('check_div_overflow', self.var_position(op.args[0]), + self.var_position(op.args[1])) + self.default_serialize_op(op, 'int_floordiv') + def serialize_op_int_floordiv_ovf_zer(self, op): self.emit('check_zerodivisionerror', self.var_position(op.args[1])) - self.default_serialize_op(op, 'int_floordiv_ovf') + self.emit('check_div_overflow', self.var_position(op.args[0]), + self.var_position(op.args[1])) + self.default_serialize_op(op, 'int_floordiv') + + def serialize_op_int_abs_ovf(self, op): + self.emit('int_neg_ovf', [self.var_position(op.args[0])]) + self.default_serialize_op(op, 'int_abs') def serialize_op_hint(self, op): hints = op.args[1].value Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Wed May 6 16:03:25 2009 @@ -218,30 +218,6 @@ cpu.clear_exception() return BoxInt(z) -def do_int_abs_ovf(cpu, args, descr=None): - x = args[0].getint() - try: - z = ovfcheck(abs(x)) - except OverflowError: - cpu.set_overflow_error() - z = 0 - else: - cpu.clear_exception() - return BoxInt(z) - -def do_int_mod_ovf(cpu, args, descr=None): - x = args[0].getint() - y = args[1].getint() - try: - ovfcheck(x % y) - except OverflowError: - cpu.set_overflow_error() - z = 0 - else: - cpu.clear_exception() - z = llop.int_mod(lltype.Signed, x, y) - return BoxInt(z) - def do_int_lshift_ovf(cpu, args, descr=None): x = args[0].getint() y = args[1].getint() @@ -252,19 +228,6 @@ z = 0 return BoxInt(z) -def do_int_floordiv_ovf(cpu, args, descr=None): - x = args[0].getint() - y = args[1].getint() - try: - ovfcheck(x // y) - except OverflowError: - cpu.set_overflow_error() - z = 0 - else: - cpu.clear_exception() - z = llop.int_floordiv(lltype.Signed, x, y) - return BoxInt(z) - # ____________________________________________________________ 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 May 6 16:03:25 2009 @@ -267,8 +267,8 @@ self.execute(rop.%s, [b1, b2]) ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', 'int_mod_ovf', - 'int_lshift_ovf', 'int_floordiv_ovf']: + for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', + 'int_lshift_ovf']: exec py.code.Source(''' @arguments("box", "box") def opimpl_%s(self, b1, b2): @@ -285,7 +285,7 @@ self.execute(rop.%s, [b]) ''' % (_opimpl, _opimpl.upper())).compile() - for _opimpl in ['int_neg_ovf', 'int_abs_ovf', + for _opimpl in ['int_neg_ovf', ]: exec py.code.Source(''' @arguments("box") @@ -419,6 +419,24 @@ self.metainterp.cpu.set_zero_division_error() return self.metainterp.handle_exception() + @arguments("orgpc", "box", "box") + def opimpl_check_div_overflow(self, pc, box1, box2): + # detect the combination "box1 = -sys.maxint-1, box2 = -1". + import sys + tmp1 = self.metainterp.execute_and_record( # combination to detect: + rop.INT_ADD, [box1, ConstInt(sys.maxint)]) # tmp1=-1, box2=-1 + tmp2 = self.metainterp.execute_and_record( + rop.INT_AND, [tmp1, box2]) # tmp2=-1 + tmp3 = self.metainterp.execute_and_record( + rop.INT_EQ, [tmp2, ConstInt(-1)]) # tmp3? + tmp4 = self.implement_guard_value(pc, tmp3) # tmp4? + if not tmp4.getint(): + return False + else: + # division overflow! + self.metainterp.cpu.set_overflow_error() + return self.metainterp.handle_exception() + @arguments("box") def opimpl_ptr_nonzero(self, box): self.execute(rop.OONONNULL, [box]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Wed May 6 16:03:25 2009 @@ -185,11 +185,8 @@ INT_ADD_OVF = 152 INT_SUB_OVF = 153 INT_MUL_OVF = 154 - INT_NEG_OVF = 155 - INT_MOD_OVF = 156 + INT_NEG_OVF = 155 # can only overflow in: -(-sys.maxint-1) INT_LSHIFT_OVF = 157 - INT_FLOORDIV_OVF = 158 - INT_ABS_OVF = 159 _OVF_LAST = 160 _CANRAISE_LAST = 160 # ----- end of can_raise operations ----- _LAST = 160 # for the backend to add more internal operations From jandem at codespeak.net Wed May 6 16:11:45 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Wed, 6 May 2009 16:11:45 +0200 (CEST) Subject: [pypy-svn] r65097 - pypy/trunk/pypy/rpython Message-ID: <20090506141145.1A10F169E94@codespeak.net> Author: jandem Date: Wed May 6 16:11:44 2009 New Revision: 65097 Modified: pypy/trunk/pypy/rpython/rstr.py Log: fix copy/paste error in rstr find and count Modified: pypy/trunk/pypy/rpython/rstr.py ============================================================================== --- pypy/trunk/pypy/rpython/rstr.py (original) +++ pypy/trunk/pypy/rpython/rstr.py Wed May 6 16:11:44 2009 @@ -122,7 +122,7 @@ v_start = hop.inputconst(Signed, 0) if hop.nb_args > 3: v_end = hop.inputarg(Signed, arg=3) - if not hop.args_s[2].nonneg: + if not hop.args_s[3].nonneg: raise TyperError("str.find() end must be proven non-negative") else: v_end = hop.gendirectcall(self.ll.ll_strlen, v_str) @@ -149,7 +149,7 @@ v_start = hop.inputconst(Signed, 0) if hop.nb_args > 3: v_end = hop.inputarg(Signed, arg=3) - if not hop.args_s[2].nonneg: + if not hop.args_s[3].nonneg: raise TyperError("str.count() end must be proven non-negative") else: v_end = hop.gendirectcall(self.ll.ll_strlen, v_str) From antocuni at codespeak.net Wed May 6 16:12:05 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 16:12:05 +0200 (CEST) Subject: [pypy-svn] r65098 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem ootypesystem Message-ID: <20090506141205.5B9F6169E94@codespeak.net> Author: antocuni Date: Wed May 6 16:12:04 2009 New Revision: 65098 Added: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py (contents, props changed) pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py pypy/branch/pyjitpl5/pypy/rpython/rclass.py pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/typesystem.py Log: (in-progress) add lltype and ootype specific versions of rvirtualizable2.py. TestOOtype still fails Added: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Wed May 6 16:12:04 2009 @@ -0,0 +1,60 @@ +from pypy.rpython.rmodel import inputconst +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR +from pypy.rpython.lltypesystem.rclass import InstanceRepr +from pypy.rpython.rvirtualizable2 import AbstractVirtualizableAccessor +from pypy.rpython.rvirtualizable2 import AbstractVirtualizable2InstanceRepr + + +class VirtualizableAccessor(AbstractVirtualizableAccessor): + + def prepare_getsets(self): + self.getsets = {} + STRUCT = self.TYPE + for fieldname in self.redirected_fields: + FIELDTYPE = getattr(STRUCT, fieldname) + GETTER = lltype.FuncType([lltype.Ptr(STRUCT)], FIELDTYPE) + SETTER = lltype.FuncType([lltype.Ptr(STRUCT), FIELDTYPE], + lltype.Void) + VABLE_GETSET = lltype.Struct('vable_getset', + ('get', lltype.Ptr(GETTER)), + ('set', lltype.Ptr(SETTER)), + hints={'immutable': True}) + getset = lltype.malloc(VABLE_GETSET, flavor='raw', zero=False) + # as long as no valid pointer has been put in the structure + # by the JIT, accessing the fields should raise, in order + # to prevent constant-folding + py.test.raises(lltype.UninitializedMemoryAccess, "getset.get") + py.test.raises(lltype.UninitializedMemoryAccess, "getset.set") + self.getsets[fieldname] = getset + setattr(self, 'getset_' + fieldname, getset) + + +class Virtualizable2InstanceRepr(AbstractVirtualizable2InstanceRepr, InstanceRepr): + + VirtualizableAccessor = VirtualizableAccessor + op_getfield = 'getfield' + op_setfield = 'setfield' + + def _setup_instance_repr(self): + llfields = [] + if self.top_of_virtualizable_hierarchy: + llfields.append(('vable_base', llmemory.Address)) + llfields.append(('vable_rti', VABLERTIPTR)) + InstanceRepr._setup_repr(self, llfields, + hints = {'virtualizable2': True, + 'virtuals' : self.virtuals}, + adtmeths = {'access': self.accessor}) + + def gencast(self, llops, vinst): + return llops.genop('cast_pointer', [vinst], resulttype=self) + + def set_vable(self, llops, vinst, force_cast=False): + if self.top_of_virtualizable_hierarchy: + if force_cast: + vinst = llops.genop('cast_pointer', [vinst], resulttype=self) + cname = inputconst(lltype.Void, 'vable_rti') + vvalue = inputconst(VABLERTIPTR, lltype.nullptr(VABLERTIPTR.TO)) + llops.genop('setfield', [vinst, cname, vvalue]) + else: + self.rbase.set_vable(llops, vinst, force_cast=True) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py Wed May 6 16:12:04 2009 @@ -190,7 +190,7 @@ self.object_type = self.lowleveltype self.gcflavor = gcflavor - def _setup_repr(self): + def _setup_repr(self, hints=None): if self.classdef is None: self.allfields = {} self.allmethods = {} Added: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py Wed May 6 16:12:04 2009 @@ -0,0 +1,29 @@ +from pypy.rpython.rmodel import inputconst +from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem.rclass import InstanceRepr +from pypy.rpython.rvirtualizable2 import AbstractVirtualizableAccessor +from pypy.rpython.rvirtualizable2 import AbstractVirtualizable2InstanceRepr + + +class VirtualizableAccessor(AbstractVirtualizableAccessor): + + def prepare_getsets(self): + self.getsets = {} # TODO + + +class Virtualizable2InstanceRepr(AbstractVirtualizable2InstanceRepr, InstanceRepr): + + VirtualizableAccessor = VirtualizableAccessor + op_getfield = 'oogetfield' + op_setfield = 'oosetfield' + + def _setup_instance_repr(self): + InstanceRepr._setup_repr(self, hints = {'virtualizable2': True, + 'virtuals' : self.virtuals}) + + def gencast(self, llops, vinst): + raise NotImplementedError + #return llops.genop('cast_pointer', [vinst], resulttype=self) + + def set_vable(self, llops, vinst, force_cast=False): + pass # TODO Modified: pypy/branch/pyjitpl5/pypy/rpython/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rclass.py Wed May 6 16:12:04 2009 @@ -52,11 +52,9 @@ from pypy.rpython.lltypesystem import rvirtualizable return rvirtualizable.VirtualizableInstanceRepr(rtyper, classdef) elif virtualizable2: - assert rtyper.type_system.name == 'lltypesystem' assert len(unboxed) == 0 assert gcflavor == 'gc' - from pypy.rpython import rvirtualizable2 - return rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) + return rtyper.type_system.rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) elif len(unboxed) == 0: return rtyper.type_system.rclass.InstanceRepr(rtyper, classdef, gcflavor) else: Modified: pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py Wed May 6 16:12:04 2009 @@ -1,14 +1,13 @@ import py from pypy.rpython.rmodel import inputconst -from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.lltypesystem.rclass import InstanceRepr -from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.rclass import AbstractInstanceRepr -class VirtualizableAccessor(object): +class AbstractVirtualizableAccessor(object): - def initialize(self, STRUCT, redirected_fields, PARENT=None): - self.STRUCT = STRUCT + def initialize(self, TYPE, redirected_fields, PARENT=None): + self.TYPE = TYPE self.redirected_fields = redirected_fields self.subaccessors = [] if PARENT is None: @@ -18,7 +17,7 @@ self.parent.subaccessors.append(self) def __repr__(self): - return '' % getattr(self, 'STRUCT', '?') + return '' % getattr(self, 'TYPE', '?') def __getattr__(self, name): if name.startswith('getset') and 'getsets' not in self.__dict__: @@ -29,34 +28,23 @@ self.__class__.__name__, name)) def prepare_getsets(self): - self.getsets = {} - STRUCT = self.STRUCT - for fieldname in self.redirected_fields: - FIELDTYPE = getattr(STRUCT, fieldname) - GETTER = lltype.FuncType([lltype.Ptr(STRUCT)], FIELDTYPE) - SETTER = lltype.FuncType([lltype.Ptr(STRUCT), FIELDTYPE], - lltype.Void) - VABLE_GETSET = lltype.Struct('vable_getset', - ('get', lltype.Ptr(GETTER)), - ('set', lltype.Ptr(SETTER)), - hints={'immutable': True}) - getset = lltype.malloc(VABLE_GETSET, flavor='raw', zero=False) - # as long as no valid pointer has been put in the structure - # by the JIT, accessing the fields should raise, in order - # to prevent constant-folding - py.test.raises(lltype.UninitializedMemoryAccess, "getset.get") - py.test.raises(lltype.UninitializedMemoryAccess, "getset.set") - self.getsets[fieldname] = getset - setattr(self, 'getset_' + fieldname, getset) + raise NotImplementedError def _freeze_(self): return True -class Virtualizable2InstanceRepr(InstanceRepr): +class AbstractVirtualizable2InstanceRepr(AbstractInstanceRepr): + + VirtualizableAccessor = AbstractVirtualizableAccessor + op_getfield = None + op_setfield = None + + def _super(self): + return super(AbstractVirtualizable2InstanceRepr, self) def __init__(self, rtyper, classdef): - InstanceRepr.__init__(self, rtyper, classdef) + self._super().__init__(rtyper, classdef) classdesc = classdef.classdesc if '_virtualizable2_' in classdesc.classdict: basedesc = classdesc.basedesc @@ -68,17 +56,19 @@ self.virtuals = tuple(classdesc.classdict['_always_virtual_'].value) except KeyError: self.virtuals = () - self.accessor = VirtualizableAccessor() + self.accessor = self.VirtualizableAccessor() + + def _setup_instance_repr(self): + raise NotImplementedError + + def gencast(self, llops, vinst): + raise NotImplementedError + + def set_vable(self, llops, vinst, force_cast=False): + raise NotImplementedError def _setup_repr(self): - llfields = [] - if self.top_of_virtualizable_hierarchy: - llfields.append(('vable_base', llmemory.Address)) - llfields.append(('vable_rti', VABLERTIPTR)) - InstanceRepr._setup_repr(self, llfields, - hints = {'virtualizable2': True, - 'virtuals' : self.virtuals}, - adtmeths = {'access': self.accessor}) + self._setup_instance_repr() my_redirected_fields = [] for _, (mangled_name, _) in self.fields.items(): my_redirected_fields.append(mangled_name) @@ -89,18 +79,9 @@ self.accessor.initialize(self.object_type, my_redirected_fields, self.rbase.lowleveltype.TO) - def set_vable(self, llops, vinst, force_cast=False): - if self.top_of_virtualizable_hierarchy: - if force_cast: - vinst = llops.genop('cast_pointer', [vinst], resulttype=self) - cname = inputconst(lltype.Void, 'vable_rti') - vvalue = inputconst(VABLERTIPTR, lltype.nullptr(VABLERTIPTR.TO)) - llops.genop('setfield', [vinst, cname, vvalue]) - else: - self.rbase.set_vable(llops, vinst, force_cast=True) def new_instance(self, llops, classcallhop=None): - vptr = InstanceRepr.new_instance(self, llops, classcallhop) + vptr = self._super().new_instance(llops, classcallhop) self.set_vable(llops, vptr) return vptr @@ -110,12 +91,12 @@ mangled_name, r = self.fields[attr] if mangled_name in self.my_redirected_fields: if force_cast: - vinst = llops.genop('cast_pointer', [vinst], - resulttype=self) + vinst = self.gencast(llops, vinst) c_name = inputconst(lltype.Void, mangled_name) llops.genop('promote_virtualizable', [vinst, c_name]) - return llops.genop('getfield', [vinst, c_name], resulttype=r) - return InstanceRepr.getfield(self, vinst, attr, llops, force_cast) + return llops.genop(self.op_getfield, [vinst, c_name], + resulttype=r) + return self._super().getfield(vinst, attr, llops, force_cast) def setfield(self, vinst, attr, vvalue, llops, force_cast=False, flags={}): @@ -124,10 +105,9 @@ mangled_name, r = self.fields[attr] if mangled_name in self.my_redirected_fields: if force_cast: - vinst = llops.genop('cast_pointer', [vinst], - resulttype=self) + vinst = self.gencast(llops, vinst) c_name = inputconst(lltype.Void, mangled_name) llops.genop('promote_virtualizable', [vinst, c_name]) - llops.genop('setfield', [vinst, c_name, vvalue]) + llops.genop(self.op_setfield, [vinst, c_name, vvalue]) return - InstanceRepr.setfield(self, vinst, attr, vvalue, llops, force_cast) + self._super().setfield(vinst, attr, vvalue, llops, force_cast) Modified: pypy/branch/pyjitpl5/pypy/rpython/typesystem.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/typesystem.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/typesystem.py Wed May 6 16:12:04 2009 @@ -22,7 +22,8 @@ return None if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist', 'rslice', 'rdict', 'rrange', 'rstr', 'rgeneric', - 'll_str', 'rbuilder', 'exceptiondata'): + 'll_str', 'rbuilder', 'rvirtualizable2', + 'exceptiondata'): mod = load(name) if mod is not None: setattr(self, name, mod) From antocuni at codespeak.net Wed May 6 16:15:42 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 16:15:42 +0200 (CEST) Subject: [pypy-svn] r65099 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090506141542.0D1A3169E8C@codespeak.net> Author: antocuni Date: Wed May 6 16:15:41 2009 New Revision: 65099 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: bah, r65093 was broken, revert it for now. print '\n'.join(['You should always run tests before committing'] * 100) 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 May 6 16:15:41 2009 @@ -733,8 +733,8 @@ def op_setarrayitem_gc(self, typedescr, obj, index, objnewvalue): array = ootype.cast_from_object(typedescr.ARRAY, obj) - newvalue = ootype.cast_from_object(typedescr.TYPE, objnewvalue) - array.ll_setitem_fast(index, newvalue) + #newvalue = ootype.cast_from_object(typedescr.TYPE, objnewvalue) + array.ll_setitem_fast(index, objnewvalue) def op_arraylen_gc(self, typedescr, obj): array = ootype.cast_from_object(typedescr.ARRAY, obj) From antocuni at codespeak.net Wed May 6 16:16:27 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 16:16:27 +0200 (CEST) Subject: [pypy-svn] r65100 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090506141627.A4306169E8C@codespeak.net> Author: antocuni Date: Wed May 6 16:16:27 2009 New Revision: 65100 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: skip these tests for now, I'll re-enable them later 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 May 6 16:16:27 2009 @@ -148,8 +148,9 @@ res = self.meta_interp(main, [0, 20], optimizer=Optimizer) assert res == 0 -class TestOOtype(ToyLanguageTests, OOJitMixin): - pass +## ootype virtualizable in-progress! +## class TestOOtype(ToyLanguageTests, OOJitMixin): +## pass class TestLLtype(ToyLanguageTests, LLJitMixin): pass From arigo at codespeak.net Wed May 6 16:16:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 16:16:30 +0200 (CEST) Subject: [pypy-svn] r65101 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090506141630.07404169E9B@codespeak.net> Author: arigo Date: Wed May 6 16:16:30 2009 New Revision: 65101 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Fix test_random: the overflowed value should not be used any more. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Wed May 6 16:16:30 2009 @@ -221,6 +221,7 @@ class AbstractOvfOperation(AbstractOperation): def produce_into(self, builder, r): + original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) exc = builder.cpu.get_exception() if exc: # OverflowError @@ -228,6 +229,8 @@ exc_box = ConstInt(exc) res_box = BoxPtr() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], res_box) + # the overflowed result should not be used any more + builder.intvars[:] = original_intvars else: op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) op.suboperations = [ResOperation(rop.FAIL, [], None)] @@ -454,8 +457,9 @@ for i, v in enumerate(op.args): value = cpu.get_latest_value_int(i) assert value == self.expected[v], ( - "Got %d, expected %d" % (value, - self.expected[v]) + "Got %d, expected %d for value #%d" % (value, + self.expected[v], + i) ) if (self.guard_op is not None and self.guard_op.is_guard_exception()): From arigo at codespeak.net Wed May 6 16:22:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 16:22:44 +0200 (CEST) Subject: [pypy-svn] r65102 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090506142244.BE157169E8C@codespeak.net> Author: arigo Date: Wed May 6 16:22:42 2009 New Revision: 65102 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Fix again test_random to generate correct code with overflow. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Wed May 6 16:22:42 2009 @@ -327,6 +327,7 @@ # 1. non raising call and guard_no_exception class CallOperation(BaseCallOperation): def produce_into(self, builder, r): + fail_subset = builder.subset_of_intvars(r) subset, f = self.non_raising_func_code(builder, r) if len(subset) == 0: RES = lltype.Void @@ -339,7 +340,7 @@ descr = builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT) self.put(builder, args, descr) op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) - op.suboperations = [ResOperation(rop.FAIL, [], None)] + op.suboperations = [ResOperation(rop.FAIL, fail_subset, None)] builder.loop.operations.append(op) # 5. Non raising-call and GUARD_EXCEPTION @@ -371,6 +372,7 @@ class RaisingCallOperation(BaseCallOperation): def produce_into(self, builder, r): + fail_subset = builder.subset_of_intvars(r) subset, f, exc = self.raising_func_code(builder, r) TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void) ptr = llhelper(lltype.Ptr(TP), f) @@ -382,7 +384,7 @@ assert builder.cpu.get_exception() builder.cpu.clear_exception() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], BoxPtr()) - op.suboperations = [ResOperation(rop.FAIL, [], None)] + op.suboperations = [ResOperation(rop.FAIL, fail_subset, None)] builder.loop.operations.append(op) # 4. raising call and guard_no_exception Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Wed May 6 16:22:42 2009 @@ -221,6 +221,7 @@ class AbstractOvfOperation(AbstractOperation): def produce_into(self, builder, r): + fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) exc = builder.cpu.get_exception() @@ -229,11 +230,14 @@ exc_box = ConstInt(exc) res_box = BoxPtr() op = ResOperation(rop.GUARD_EXCEPTION, [exc_box], res_box) - # the overflowed result should not be used any more + # the overflowed result should not be used any more, but can + # be used on the failure path: recompute fail_subset including + # the result, and then remove it from builder.intvars. + fail_subset = builder.subset_of_intvars(r) builder.intvars[:] = original_intvars else: op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) - op.suboperations = [ResOperation(rop.FAIL, [], None)] + op.suboperations = [ResOperation(rop.FAIL, fail_subset, None)] builder.loop.operations.append(op) class BinaryOvfOperation(AbstractOvfOperation, BinaryOperation): From arigo at codespeak.net Wed May 6 16:40:47 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 16:40:47 +0200 (CEST) Subject: [pypy-svn] r65103 - in pypy/branch/pyjitpl5/pypy: rpython/lltypesystem translator/c/test Message-ID: <20090506144047.6F861169E8F@codespeak.net> Author: arigo Date: Wed May 6 16:40:46 2009 New Revision: 65103 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py Log: 'cast_adr_to_int' must not be canfold=True. Otherwise, we get code compiled with a random integer constant. See new test. 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 May 6 16:40:46 2009 @@ -378,7 +378,7 @@ 'adr_call': LLOp(canraise=(Exception,)), 'cast_ptr_to_adr': LLOp(sideeffects=False), 'cast_adr_to_ptr': LLOp(canfold=True), - 'cast_adr_to_int': LLOp(canfold=True), + 'cast_adr_to_int': LLOp(sideeffects=False), 'cast_int_to_adr': LLOp(canfold=True), # not implemented in llinterp # __________ used by the JIT ________ Modified: pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/test/test_lladdresses.py Wed May 6 16:40:46 2009 @@ -174,3 +174,20 @@ fn = compile(f, [int], gcpolicy='boehm') assert fn(3) == 123 assert fn(-3) == -42 + +def test_cast_adr_to_int(): + S = lltype.Struct("S", ("x", lltype.Signed)) + s = lltype.malloc(S, immortal=True) + adr = cast_ptr_to_adr(s) + def f(n): + i = cast_adr_to_int(adr) + if n > 10: + adr2 = adr + else: + adr2 = NULL + print "hello world" # prevent constant-folding + j = cast_adr_to_int(adr2) + return i - j + fc = compile(f, [int]) + res = fc(42) + assert res == 0 From arigo at codespeak.net Wed May 6 16:46:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 16:46:49 +0200 (CEST) Subject: [pypy-svn] r65104 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090506144649.C0877169E9D@codespeak.net> Author: arigo Date: Wed May 6 16:46:49 2009 New Revision: 65104 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/run_all_tests.py Log: Update. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/run_all_tests.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/run_all_tests.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/run_all_tests.py Wed May 6 16:46:49 2009 @@ -47,14 +47,22 @@ f.seek(start) lines = f.readlines() f.close() - if '---ending 2---' in lines[-1]: + i = -1 + while (lines[i].startswith('leaving with Return:') or + lines[i].startswith('TOTAL:') or + lines[i].startswith('Tracing:') or + lines[i].startswith('Backend:') or + lines[i].startswith('Running asm:') or + lines[i].startswith('Blackhole:')): + i -= 1 + if '---ending 2---' in lines[i]: print >> sys.stderr, 'ok' - elif (lines[-1].startswith('ImportError:') or - lines[-1].startswith('TestSkipped:') or - lines[-1].startswith('ResourceDenied:')): - print >> sys.stderr, lines[-1].rstrip() + elif (lines[i].startswith('ImportError:') or + lines[i].startswith('TestSkipped:') or + lines[i].startswith('ResourceDenied:')): + print >> sys.stderr, lines[i].rstrip() else: print >> sys.stderr, "failed! The last line of the output is:" - print >> sys.stderr, lines[-1].rstrip() + print >> sys.stderr, lines[i].rstrip() break #time.sleep(1) From jandem at codespeak.net Wed May 6 16:53:38 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Wed, 6 May 2009 16:53:38 +0200 (CEST) Subject: [pypy-svn] r65105 - pypy/trunk/pypy/rpython/test Message-ID: <20090506145338.84C25169E83@codespeak.net> Author: jandem Date: Wed May 6 16:53:38 2009 New Revision: 65105 Modified: pypy/trunk/pypy/rpython/test/test_rstr.py Log: add tests for commit 65097 Modified: pypy/trunk/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rstr.py (original) +++ pypy/trunk/pypy/rpython/test/test_rstr.py Wed May 6 16:53:38 2009 @@ -271,6 +271,17 @@ res = self.interpret(fn, [i, j]) assert res == fn(i, j) + def test_find_TyperError(self): + const = self.const + def f(): + s = const('abc') + s.find(s, 0, -10) + raises(TyperError, self.interpret, f, ()) + def f(): + s = const('abc') + s.find(s, -10) + raises(TyperError, self.interpret, f, ()) + def test_find_empty_string(self): const = self.const def f(i): @@ -715,6 +726,17 @@ res = self.interpret(fn, []) assert res == 1 + def test_count_TyperError(self): + const = self.const + def f(): + s = const('abc') + s.count(s, 0, -10) + raises(TyperError, self.interpret, f, ()) + def f(): + s = const('abc') + s.count(s, -10) + raises(TyperError, self.interpret, f, ()) + def test_getitem_exc(self): const = self.const def f(x): From antocuni at codespeak.net Wed May 6 17:12:58 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 17:12:58 +0200 (CEST) Subject: [pypy-svn] r65106 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20090506151258.6ADEC169EB4@codespeak.net> Author: antocuni Date: Wed May 6 17:12:57 2009 New Revision: 65106 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py Log: complete the implementation of rvirtualizable2 for ootype. test pass Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py Wed May 6 17:12:57 2009 @@ -49,6 +49,15 @@ def gencast(self, llops, vinst): return llops.genop('cast_pointer', [vinst], resulttype=self) + def get_mangled_fields(self): + return [mangled_name for _, (mangled_name, _) in self.fields.items()] + + def get_field(self, attr): + return self.fields[attr] + + def is_in_fields(self, attr): + return attr in self.fields + def set_vable(self, llops, vinst, force_cast=False): if self.top_of_virtualizable_hierarchy: if force_cast: Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py Wed May 6 17:12:57 2009 @@ -191,6 +191,9 @@ self.gcflavor = gcflavor def _setup_repr(self, hints=None): + if hints: + self.lowleveltype._hints.update(hints) + if self.classdef is None: self.allfields = {} self.allmethods = {} @@ -408,12 +411,9 @@ s_inst = hop.args_s[0] attr = hop.args_s[1].const mangled = mangle(attr, self.rtyper.getconfig()) - v_attr = hop.inputconst(ootype.Void, mangled) if mangled in self.allfields: # regular instance attributes - self.lowleveltype._check_field(mangled) - return hop.genop("oogetfield", [v_inst, v_attr], - resulttype = hop.r_result.lowleveltype) + return self.getfield(v_inst, attr, hop.llops) elif mangled in self.allmethods: # special case for methods: represented as their 'self' only # (see MethodsPBCRepr) @@ -452,13 +452,17 @@ self.lowleveltype._check_field(mangled) r_value = self.allfields[mangled] v_inst, _, v_newval = hop.inputargs(self, ootype.Void, r_value) - v_attr = hop.inputconst(ootype.Void, mangled) - return hop.genop('oosetfield', [v_inst, v_attr, v_newval]) + self.setfield(v_inst, attr, v_newval, hop.llops) + + def getfield(self, v_inst, attr, llops): + mangled = mangle(attr, self.rtyper.getconfig()) + v_attr = inputconst(ootype.Void, mangled) + r_value = self.allfields[mangled] + self.lowleveltype._check_field(mangled) + return llops.genop('oogetfield', [v_inst, v_attr], + resulttype = r_value) def setfield(self, vinst, attr, vvalue, llops): - # this method emulates behaviour from the corresponding - # lltypesystem one. It is referenced in some obscure corners - # like rtyping of OSError. mangled_name = mangle(attr, self.rtyper.getconfig()) cname = inputconst(ootype.Void, mangled_name) llops.genop('oosetfield', [vinst, cname, vvalue]) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py Wed May 6 17:12:57 2009 @@ -1,6 +1,6 @@ from pypy.rpython.rmodel import inputconst from pypy.rpython.ootypesystem import ootype -from pypy.rpython.ootypesystem.rclass import InstanceRepr +from pypy.rpython.ootypesystem.rclass import InstanceRepr, mangle from pypy.rpython.rvirtualizable2 import AbstractVirtualizableAccessor from pypy.rpython.rvirtualizable2 import AbstractVirtualizable2InstanceRepr @@ -23,7 +23,17 @@ def gencast(self, llops, vinst): raise NotImplementedError - #return llops.genop('cast_pointer', [vinst], resulttype=self) + + def get_mangled_fields(self): + return self.allfields.keys() + + def get_field(self, attr): + mangled = mangle(attr, self.rtyper.getconfig()) + return mangled, self.allfields[mangled] + + def is_in_fields(self, attr): + mangled = mangle(attr, self.rtyper.getconfig()) + return mangled in self.allfields def set_vable(self, llops, vinst, force_cast=False): pass # TODO Modified: pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py Wed May 6 17:12:57 2009 @@ -67,10 +67,19 @@ def set_vable(self, llops, vinst, force_cast=False): raise NotImplementedError + def get_mangled_fields(self): + raise NotImplementedError + + def get_field(self, attr): + raise NotImplementedError + + def is_in_fields(self, attr): + raise NotImplementedError + def _setup_repr(self): self._setup_instance_repr() my_redirected_fields = [] - for _, (mangled_name, _) in self.fields.items(): + for mangled_name in self.get_mangled_fields(): my_redirected_fields.append(mangled_name) self.my_redirected_fields = dict.fromkeys(my_redirected_fields) if self.top_of_virtualizable_hierarchy: @@ -87,8 +96,8 @@ def getfield(self, vinst, attr, llops, force_cast=False, flags={}): """Read the given attribute (or __class__ for the type) of 'vinst'.""" - if not flags.get('access_directly') and attr in self.fields: - mangled_name, r = self.fields[attr] + if not flags.get('access_directly') and self.is_in_fields(attr): + mangled_name, r = self.get_field(attr) if mangled_name in self.my_redirected_fields: if force_cast: vinst = self.gencast(llops, vinst) @@ -101,8 +110,8 @@ def setfield(self, vinst, attr, vvalue, llops, force_cast=False, flags={}): """Write the given attribute (or __class__ for the type) of 'vinst'.""" - if not flags.get('access_directly') and attr in self.fields: - mangled_name, r = self.fields[attr] + if not flags.get('access_directly') and self.is_in_fields(attr): + mangled_name, r = self.get_field(attr) if mangled_name in self.my_redirected_fields: if force_cast: vinst = self.gencast(llops, vinst) Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_rvirtualizable2.py Wed May 6 17:12:57 2009 @@ -22,9 +22,15 @@ v_inst = op_getfield.args[0] assert op_promote.opname == 'promote_virtualizable' assert op_promote.args[0] is v_inst + TYPE = self.gettype(v_inst) + assert TYPE._hints['virtualizable2'] + class TestLLtype(LLRtypeMixin, BaseTest): + def gettype(self, v): + return v.concretetype.TO + def test_simple(self): def f(v): vinst = V(v) @@ -35,5 +41,8 @@ assert res.inst_v == 42 assert not res.vable_rti -## class TestOOtype(OORtypeMixin, BaseTest): -## pass +class TestOOtype(OORtypeMixin, BaseTest): + + def gettype(self, v): + return v.concretetype + From jandem at codespeak.net Wed May 6 17:37:25 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Wed, 6 May 2009 17:37:25 +0200 (CEST) Subject: [pypy-svn] r65107 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090506153725.E1F82168041@codespeak.net> Author: jandem Date: Wed May 6 17:37:24 2009 New Revision: 65107 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: fix translation of JS-interpreter Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Wed May 6 17:37:24 2009 @@ -232,7 +232,7 @@ elif (i + 5 < lgt and strval[i + 1] == 'u' and _ishex(strval[i + 2]) and _ishex(strval[i + 3]) and _ishex(strval[i + 4]) and _ishex(strval[i + 5])): - ch = unichr(int(strval[i+2:i+6], 16)) + ch = chr(int(strval[i+2:i+6], 16)) i += 5 i += 1 res.append(ch) @@ -375,7 +375,7 @@ temp = [] for arg in args: i = arg.ToInt32(ctx) % 65536 # XXX should be uint16 - temp.append(unichr(i)) + temp.append(chr(i)) return W_String(''.join(temp)) class W_CharAt(W_NewBuiltin): @@ -422,7 +422,8 @@ pos = 0 else: pos = args[1].ToInteger(ctx) - pos = min(max(pos, 0), size) + pos = int(min(max(pos, 0), size)) + assert pos >= 0 return W_IntNumber(string.find(substr, pos)) class W_LastIndexOf(W_NewBuiltin): @@ -441,9 +442,11 @@ else: pos = args[1].ToInteger(ctx) size = len(string) - pos = min(max(pos, 0), size) + pos = int(min(max(pos, 0), size)) subsize = len(substr) - return W_IntNumber(string.rfind(substr, 0, pos+subsize)) + endpos = pos+subsize + assert endpos >= 0 + return W_IntNumber(string.rfind(substr, 0, endpos)) class W_Substring(W_NewBuiltin): length = 2 @@ -722,8 +725,8 @@ w_math.Put(ctx, 'E', W_FloatNumber(math.e), flags=allon) w_math.Put(ctx, 'LN2', W_FloatNumber(math.log(2)), flags=allon) w_math.Put(ctx, 'LN10', W_FloatNumber(math.log(10)), flags=allon) - w_math.Put(ctx, 'LOG2E', W_FloatNumber(math.log(math.e, 2)), flags=allon) - w_math.Put(ctx, 'LOG10E', W_FloatNumber(math.log(math.e, 10)), flags=allon) + #w_math.Put(ctx, 'LOG2E', W_FloatNumber(math.log(math.e, 2)), flags=allon) + #w_math.Put(ctx, 'LOG10E', W_FloatNumber(math.log(math.e, 10)), flags=allon) w_math.Put(ctx, 'PI', W_FloatNumber(math.pi), flags=allon) w_math.Put(ctx, 'SQRT1_2', W_FloatNumber(math.sqrt(0.5)), flags=allon) w_math.Put(ctx, 'SQRT2', W_FloatNumber(math.sqrt(2)), flags=allon) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Wed May 6 17:37:24 2009 @@ -111,7 +111,6 @@ class W_PrimitiveObject(W_Root): - length = -1 def __init__(self, ctx=None, Prototype=None, Class='Object', Value=w_Undefined, callfunc=None): self.propdict = {} @@ -126,9 +125,6 @@ else: self.Scope = None self.Value = Value - - if self.length != -1: - self.Put(ctx, 'length', W_IntNumber(self.length), flags = DE|DD|RO) def Call(self, ctx, args=[], this=None): if self.callfunc is None: # XXX Not sure if I should raise it here @@ -260,6 +256,7 @@ return self.Get(ctx, 'valueOf').Call(ctx, args=[], this=self).ToNumber(ctx) class W_NewBuiltin(W_PrimitiveObject): + length = -1 def __init__(self, ctx, Prototype=None, Class='function', Value=w_Undefined, callfunc=None): if Prototype is None: @@ -267,6 +264,10 @@ Prototype = proto W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) + + if self.length != -1: + self.Put(ctx, 'length', W_IntNumber(self.length), flags = DE|DD|RO) + def Call(self, ctx, args=[], this = None): raise NotImplementedError From antocuni at codespeak.net Wed May 6 17:40:22 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 17:40:22 +0200 (CEST) Subject: [pypy-svn] r65108 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090506154022.75A62169E56@codespeak.net> Author: antocuni Date: Wed May 6 17:40:21 2009 New Revision: 65108 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Log: port jit support for virtualizables to ootype. Some tests are still failing 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 May 6 17:40:21 2009 @@ -11,7 +11,7 @@ from pypy.tool.udir import udir from pypy.translator.simplify import get_funcobj, get_functype from pypy.translator.backendopt.canraise import RaiseAnalyzer -from pypy.jit.metainterp.typesystem import deref, arrayItem +from pypy.jit.metainterp.typesystem import deref, arrayItem, fieldType import py, sys from pypy.tool.ansi_print import ansi_log @@ -1152,9 +1152,9 @@ pass # for now def serialize_op_promote_virtualizable(self, op): - STRUCTTYPE = op.args[0].concretetype.TO + STRUCTTYPE = deref(op.args[0].concretetype) argname = op.args[1].value - FIELDTYPE = getattr(STRUCTTYPE, argname) + FIELDTYPE = fieldType(STRUCTTYPE, argname) if FIELDTYPE != lltype.Void: TOPSTRUCT = heaptracker.cast_vable_type(STRUCTTYPE) metainterp_sd = self.codewriter.metainterp_sd 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 May 6 17:40:21 2009 @@ -28,7 +28,13 @@ STRUCT = cast_vable_type(T.TO) return lltype.cast_pointer(lltype.Ptr(STRUCT), p) -def cast_vable_type(STRUCT): +def cast_vable_type(STRUCT_OR_INST): + if isinstance(STRUCT_OR_INST, ootype.Instance): + return cast_vable_type_instance(STRUCT_OR_INST) + else: + return cast_vable_type_struct(STRUCT_OR_INST) + +def cast_vable_type_struct(STRUCT): assert STRUCT._hints.get('virtualizable2'), \ "not a virtualizable2: %r" % (STRUCT,) while True: @@ -38,6 +44,17 @@ STRUCT = PARENT return STRUCT +def cast_vable_type_instance(INSTANCE): + assert INSTANCE._hints.get('virtualizable2'), \ + "not a virtualizable2: %r" % (INSTANCE,) + while True: + PARENT = INSTANCE._superclass + if PARENT is None or not PARENT._hints.get('virtualizable2'): + break + INSTANCE = PARENT + return INSTANCE + + def get_vtable_for_gcstruct(cpu, GCSTRUCT): # xxx hack: from a GcStruct representing an instance's # lowleveltype, return the corresponding vtable pointer. 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 May 6 17:40:21 2009 @@ -608,10 +608,20 @@ self.check_loops(getfield_gc=0, setfield_gc=0, call=0) -##class TestOOtype(ExplicitVirtualizableTests, -## ImplicitVirtualizableTests, -## OOJitMixin): -## pass +class TestOOtype(ExplicitVirtualizableTests, + ImplicitVirtualizableTests, + OOJitMixin): + + def skip(self): + py.test.skip('in-progress') + + test_virtual_on_virtualizable = skip + test_no_virtual_on_virtualizable = skip + test_virtualizable_hierarchy = skip + test_non_virtual_on_always_virtual = skip + test_external_pass = skip + test_pass_always_virtual_to_bridge = skip + class TestLLtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, 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 May 6 17:40:21 2009 @@ -1,6 +1,8 @@ from pypy.jit.metainterp import history +from pypy.jit.metainterp.typesystem import llhelper, oohelper from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype 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 @@ -10,11 +12,20 @@ def __init__(self, cpu, TOPSTRUCT, STRUCTTYPE): "NOT_RPYTHON" - self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for - name in TOPSTRUCT._hints['virtuals']] + if cpu.is_oo: + prefix = 'o' + else: + prefix = 'inst_' + self.virtuals = [cpu.fielddescrof(STRUCTTYPE, prefix+name) + for name in TOPSTRUCT._hints['virtuals']] self.fields = self.catch_all_fields(cpu, STRUCTTYPE) def catch_all_fields(self, cpu, S): + if isinstance(S, ootype.OOType): + return self.catch_all_fields_ootype(cpu, S) + return self.catch_all_fields_lltype(cpu, S) + + def catch_all_fields_lltype(self, cpu, S): lst = [] p = S while True: @@ -26,3 +37,6 @@ return [cpu.fielddescrof(S, name) for name in lst if name.startswith('inst_') and hasattr(S, name)] + def catch_all_fields_ootype(self, cpu, S): + lst = S._allfields().keys() + return [cpu.fielddescrof(S, name) for name in lst] From antocuni at codespeak.net Wed May 6 17:49:16 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 17:49:16 +0200 (CEST) Subject: [pypy-svn] r65109 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp/test Message-ID: <20090506154916.03C76169EAC@codespeak.net> Author: antocuni Date: Wed May 6 17:49:15 2009 New Revision: 65109 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: fix more tests 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 May 6 17:49:15 2009 @@ -93,6 +93,7 @@ 'ooisnull' : (('ptr',), 'bool'), 'oois' : (('ptr', 'ptr'), 'bool'), 'ooisnot' : (('ptr', 'ptr'), 'bool'), + 'instanceof' : (('ptr',), 'bool'), 'setfield_gc' : (('ptr', 'intorptr'), None), 'getfield_gc' : (('ptr',), 'intorptr'), 'getfield_gc_pure': (('ptr',), 'intorptr'), @@ -768,6 +769,10 @@ if ootype.classof(value) is not expected_class: raise GuardFailed + def op_instanceof(self, typedescr, obj): + inst = ootype.cast_from_object(ootype.ROOT, obj) + return ootype.instanceof(inst, typedescr.TYPE) + def _cast_exception(self, exception): return ootype.cast_from_object(ootype.Class, exception) 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 May 6 17:49:15 2009 @@ -615,10 +615,7 @@ def skip(self): py.test.skip('in-progress') - test_virtual_on_virtualizable = skip - test_no_virtual_on_virtualizable = skip test_virtualizable_hierarchy = skip - test_non_virtual_on_always_virtual = skip test_external_pass = skip test_pass_always_virtual_to_bridge = skip From arigo at codespeak.net Wed May 6 17:53:08 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 17:53:08 +0200 (CEST) Subject: [pypy-svn] r65110 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/test backend/x86 backend/x86/test metainterp metainterp/test Message-ID: <20090506155308.81A70169EB6@codespeak.net> Author: arigo Date: Wed May 6 17:53:07 2009 New Revision: 65110 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py 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_regalloc2.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: * The operation int_abs_ovf() is actually not generated any more, I think. At least a pypy-c translates without seeing it. * Kill rop.INT_ABS too. Replace it with logic in the front-end only. 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 May 6 17:53:07 2009 @@ -68,7 +68,6 @@ 'int_is_true' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), 'int_invert' : (('int',), 'int'), - 'int_abs' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Wed May 6 17:53:07 2009 @@ -145,7 +145,6 @@ (rop.INT_IS_TRUE, [(0, 0), (1, 1), (2, 1), (-1, 1), (minint, 1)]), (rop.INT_NEG, [(0, 0), (123, -123), (-23127, 23127)]), (rop.INT_INVERT, [(0, ~0), (-1, ~(-1)), (123, ~123)]), - (rop.INT_ABS, [(0, 0), (123, 123), (-23127, 23127)]), ]: for x, y in testcases: res = self.execute_operation(opnum, [BoxInt(x)], @@ -202,7 +201,7 @@ ] ops[1].suboperations = [ResOperation(rop.FAIL, [v_res], None)] # - if opnum in (rop.INT_NEG_OVF, rop.INT_ABS_OVF): + if opnum == rop.INT_NEG_OVF: del ops[0].args[1] loop = TreeLoop('name') loop.operations = ops Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Wed May 6 17:53:07 2009 @@ -315,7 +315,6 @@ for _op in [rop.INT_NEG, rop.INT_INVERT, - rop.INT_ABS, ]: OPERATIONS.append(UnaryOperation(_op)) 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 Wed May 6 17:53:07 2009 @@ -505,18 +505,6 @@ self.mc.MOV(resloc, imm8(0)) self.mc.SETNZ(lower_byte(resloc)) - def genop_int_abs(self, op, arglocs, resloc): - argloc = arglocs[0] - tmploc = arglocs[1] - assert resloc != argloc and resloc != tmploc - self.mc.MOV(resloc, argloc) - # ABS-computing code from Psyco, found by exhaustive search - # on *all* short sequences of operations :-) - self.mc.ADD(resloc, resloc) - self.mc.SBB(resloc, argloc) - self.mc.SBB(tmploc, tmploc) - self.mc.XOR(resloc, tmploc) - def genop_guard_oononnull(self, op, guard_op, addr, arglocs, resloc): loc = arglocs[0] self.mc.TEST(loc, loc) 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 Wed May 6 17:53:07 2009 @@ -1021,15 +1021,6 @@ self.eventually_free_var(op.args[0]) self.Perform(op, [argloc], resloc) - def consider_int_abs(self, op, ignored): - argloc = self.make_sure_var_in_reg(op.args[0], []) - tmpvar = TempBox() - tmploc = self.force_allocate_reg(tmpvar, [op.args[0]]) - resloc = self.force_allocate_reg(op.result, [op.args[0], tmpvar]) - self.Perform(op, [argloc, tmploc], resloc) - self.eventually_free_var(op.args[0]) - self.eventually_free_var(tmpvar) - def _consider_nullity(self, op, guard_op): # doesn't need a register in arg if guard_op is not None: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py Wed May 6 17:53:07 2009 @@ -117,7 +117,7 @@ ResOperation(rop.INT_OR, [ConstInt(-4), v25], v26), ResOperation(rop.INT_INVERT, [v8], v27), ResOperation(rop.INT_SUB, [ConstInt(-113), v11], v28), - ResOperation(rop.INT_ABS, [v7], v29), + ResOperation(rop.INT_NEG, [v7], v29), ResOperation(rop.INT_NEG, [v24], v30), ResOperation(rop.INT_FLOORDIV, [v3, ConstInt(53)], v31), ResOperation(rop.INT_MUL, [v28, v27], v32), @@ -224,7 +224,7 @@ ResOperation(rop.UINT_RSHIFT, [v14, tmp42], v18), ResOperation(rop.INT_AND, [v14, ConstInt(31)], tmp43), ResOperation(rop.INT_LSHIFT, [ConstInt(7), tmp43], v19), - ResOperation(rop.INT_ABS, [v19], v20), + ResOperation(rop.INT_NEG, [v19], v20), ResOperation(rop.INT_MOD, [v3, ConstInt(1)], v21), ResOperation(rop.UINT_GE, [v15, v1], v22), ResOperation(rop.INT_AND, [v16, ConstInt(31)], tmp44), @@ -236,17 +236,17 @@ ResOperation(rop.INT_EQ, [v9, v15], v27), ResOperation(rop.INT_GE, [ConstInt(0), v6], v28), ResOperation(rop.INT_NEG, [v15], v29), - ResOperation(rop.INT_ABS, [v22], v30), + ResOperation(rop.INT_NEG, [v22], v30), ResOperation(rop.INT_ADD, [v7, v16], v31), ResOperation(rop.UINT_LT, [v19, v19], v32), ResOperation(rop.INT_ADD, [v2, ConstInt(1)], v33), - ResOperation(rop.INT_ABS, [v5], v34), + ResOperation(rop.INT_NEG, [v5], v34), ResOperation(rop.INT_ADD, [v17, v24], v35), ResOperation(rop.UINT_LT, [ConstInt(2), v16], v36), - ResOperation(rop.INT_ABS, [v9], v37), + ResOperation(rop.INT_NEG, [v9], v37), ResOperation(rop.INT_GT, [v4, v11], v38), ResOperation(rop.INT_LT, [v27, v22], v39), - ResOperation(rop.INT_ABS, [v27], v40), + ResOperation(rop.INT_NEG, [v27], v40), ResOperation(rop.FAIL, [v40, v10, v36, v26, v13, v30, v21, v33, v18, v25, v31, v32, v28, v29, v35, v38, v20, v39, v34, v23, v37], None), ] cpu = CPU(None, None) @@ -267,7 +267,7 @@ assert cpu.get_latest_value_int(2) == 1 assert cpu.get_latest_value_int(3) == 131072 assert cpu.get_latest_value_int(4) == 20 - assert cpu.get_latest_value_int(5) == 1 + assert cpu.get_latest_value_int(5) == -1 assert cpu.get_latest_value_int(6) == 0 assert cpu.get_latest_value_int(7) == -19 assert cpu.get_latest_value_int(8) == 6 @@ -278,52 +278,8 @@ assert cpu.get_latest_value_int(13) == 2 assert cpu.get_latest_value_int(14) == 2 assert cpu.get_latest_value_int(15) == 1 - assert cpu.get_latest_value_int(16) == 57344 + assert cpu.get_latest_value_int(16) == -57344 assert cpu.get_latest_value_int(17) == 1 - assert cpu.get_latest_value_int(18) == 1 + assert cpu.get_latest_value_int(18) == -1 assert cpu.get_latest_value_int(19) == -2147483648 - assert cpu.get_latest_value_int(20) == 49 - -def test_bug_2(): - v1 = BoxInt() - v2 = BoxInt() - v3 = BoxInt() - v4 = BoxInt() - v5 = BoxInt() - v6 = BoxInt() - v7 = BoxInt() - v8 = BoxInt() - v9 = BoxInt() - v10 = BoxInt() - v11 = BoxInt() - v12 = BoxInt() - v13 = BoxInt() - v14 = BoxInt() - tmp21 = BoxInt() - loop = TreeLoop('test') - loop.inputargs = [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10] - loop.operations = [ - ResOperation(rop.INT_IS_TRUE, [v4], tmp21), - ResOperation(rop.BOOL_NOT, [tmp21], v11), - ResOperation(rop.INT_NEG, [v6], v12), - ResOperation(rop.UINT_LT, [v10, v10], v13), - ResOperation(rop.INT_ABS_OVF, [v5], v14), - ResOperation(rop.GUARD_NO_EXCEPTION, [], None), - ResOperation(rop.FAIL, [v11, v14], None), - ] - loop.operations[-2].suboperations = [ResOperation(rop.FAIL, [], None)] - cpu = CPU(None, None) - cpu.compile_operations(loop) - cpu.set_future_value_int(0, 5) - cpu.set_future_value_int(1, -3) - cpu.set_future_value_int(2, -84) - cpu.set_future_value_int(3, 2) - cpu.set_future_value_int(4, -12) - cpu.set_future_value_int(5, -3) - cpu.set_future_value_int(6, 15) - cpu.set_future_value_int(7, -17) - cpu.set_future_value_int(8, -23) - cpu.set_future_value_int(9, 6) - cpu.execute_operations(loop) - assert cpu.get_latest_value_int(0) == 0 - assert cpu.get_latest_value_int(1) == 12 + assert cpu.get_latest_value_int(20) == -49 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 May 6 17:53:07 2009 @@ -656,10 +656,6 @@ self.var_position(op.args[1])) self.default_serialize_op(op, 'int_floordiv') - def serialize_op_int_abs_ovf(self, op): - self.emit('int_neg_ovf', [self.var_position(op.args[0])]) - self.default_serialize_op(op, 'int_abs') - 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/executor.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/executor.py Wed May 6 17:53:07 2009 @@ -53,9 +53,6 @@ v = r_uint(args[0].getint()) >> r_uint(args[1].getint()) return ConstInt(intmask(v)) -def do_int_abs(cpu, args, descr=None): - return ConstInt(intmask(abs(args[0].getint()))) - # ---------- def do_int_lt(cpu, args, descr=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 Wed May 6 17:53:07 2009 @@ -277,7 +277,6 @@ for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', 'cast_ptr_to_int', 'cast_int_to_ptr', - 'int_abs', ]: exec py.code.Source(''' @arguments("box") @@ -437,6 +436,16 @@ self.metainterp.cpu.set_overflow_error() return self.metainterp.handle_exception() + @arguments("orgpc", "box") + def opimpl_int_abs(self, pc, box): + nonneg = self.metainterp.execute_and_record( + rop.INT_GE, [box, ConstInt(0)]) + nonneg = self.implement_guard_value(pc, nonneg) + if nonneg.getint(): + self.make_result_box(box) + else: + self.execute(rop.INT_NEG, [box]) + @arguments("box") def opimpl_ptr_nonzero(self, box): self.execute(rop.OONONNULL, [box]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Wed May 6 17:53:07 2009 @@ -137,7 +137,6 @@ INT_NEG = 61 INT_INVERT = 62 BOOL_NOT = 63 - INT_ABS = 65 # OONONNULL = 70 OOISNULL = 71 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 May 6 17:53:07 2009 @@ -408,6 +408,14 @@ res = self.meta_interp(f, [20, 1, 2]) assert res == 0 + def test_abs(self): + def f(x): + return abs(x) + res = self.interp_operations(f, [-17]) + assert res == 17 + res = self.interp_operations(f, [4141]) + assert res == 4141 + def test_print(self): myjitdriver = JitDriver(greens = [], reds = ['n']) def f(n): From antocuni at codespeak.net Wed May 6 17:54:30 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 17:54:30 +0200 (CEST) Subject: [pypy-svn] r65111 - in pypy/branch/pyjitpl5/pypy: jit/metainterp/test rpython rpython/ootypesystem Message-ID: <20090506155430.5E0C61683B8@codespeak.net> Author: antocuni Date: Wed May 6 17:54:29 2009 New Revision: 65111 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py Log: smooth some more ootype/lltype differences, and let two more tests to pass 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 May 6 17:54:29 2009 @@ -615,8 +615,6 @@ def skip(self): py.test.skip('in-progress') - test_virtualizable_hierarchy = skip - test_external_pass = skip test_pass_always_virtual_to_bridge = skip Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py Wed May 6 17:54:29 2009 @@ -7,6 +7,9 @@ class VirtualizableAccessor(AbstractVirtualizableAccessor): + def initialize(self, TYPE, redirected_fields, PARENT=None): + pass # TODO + def prepare_getsets(self): self.getsets = {} # TODO Modified: pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rvirtualizable2.py Wed May 6 17:54:29 2009 @@ -85,9 +85,9 @@ if self.top_of_virtualizable_hierarchy: self.accessor.initialize(self.object_type, my_redirected_fields) else: + BASE = self.rtyper.type_system.derefType(self.rbase.lowleveltype) self.accessor.initialize(self.object_type, my_redirected_fields, - self.rbase.lowleveltype.TO) - + BASE) def new_instance(self, llops, classcallhop=None): vptr = self._super().new_instance(llops, classcallhop) From antocuni at codespeak.net Wed May 6 18:05:17 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 18:05:17 +0200 (CEST) Subject: [pypy-svn] r65112 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp/test Message-ID: <20090506160517.2E84E169ED1@codespeak.net> Author: antocuni Date: Wed May 6 18:05:16 2009 New Revision: 65112 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: cool, last 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 Wed May 6 18:05:16 2009 @@ -655,6 +655,10 @@ def sort_key(self): return self._keys.getkey((self.TYPE, self.fieldname)) + def equals(self, other): + return self.TYPE == other.TYPE and \ + self.fieldname == other.fieldname + # ____________________________________________________________ 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 May 6 18:05:16 2009 @@ -611,12 +611,7 @@ class TestOOtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, OOJitMixin): - - def skip(self): - py.test.skip('in-progress') - - test_pass_always_virtual_to_bridge = skip - + pass class TestLLtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, From arigo at codespeak.net Wed May 6 18:06:19 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 18:06:19 +0200 (CEST) Subject: [pypy-svn] r65113 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem Message-ID: <20090506160619.5A516169ED8@codespeak.net> Author: arigo Date: Wed May 6 18:06:18 2009 New Revision: 65113 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/opimpl.py Log: Kill from llinterp operations that no longer exist. Move op_cast_adr_to_int to llinterp. This makes test_lloperation happy again. Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Wed May 6 18:06:18 2009 @@ -800,6 +800,10 @@ checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) + def op_cast_adr_to_int(self, adr): + checkadr(addr) + return llmemory.cast_adr_to_int(adr) + def op_weakref_create(self, v_obj): def objgetter(): # special support for gcwrapper.py return self.getval(v_obj) @@ -1010,14 +1014,6 @@ except OverflowError: self.make_llexception() - def op_int_lshift_ovf_val(self, x, y): - assert isinstance(x, int) - assert isinstance(y, int) - try: - return ovfcheck_lshift(x, y) - except (OverflowError, ValueError): - self.make_llexception() - def _makefunc2(fn, operator, xtype, ytype=None): import sys d = sys._getframe(1).f_locals @@ -1062,23 +1058,15 @@ _makefunc2('op_int_mod_ovf', '%', 'int') _makefunc2('op_int_mod_zer', '%', 'int') _makefunc2('op_int_mod_ovf_zer', '%', 'int') - _makefunc2('op_int_lshift_val', '<<', 'int') - _makefunc2('op_int_rshift_val', '>>', 'int') _makefunc2('op_uint_floordiv_zer', '//', 'r_uint') _makefunc2('op_uint_mod_zer', '%', 'r_uint') - _makefunc2('op_uint_lshift_val', '<<', 'r_uint') - _makefunc2('op_uint_rshift_val', '>>', 'r_uint') _makefunc2('op_llong_floordiv_zer', '//', 'r_longlong') _makefunc2('op_llong_mod_zer', '%', 'r_longlong') - _makefunc2('op_llong_lshift_val', '<<', 'r_longlong') - _makefunc2('op_llong_rshift_val', '>>', 'r_longlong') _makefunc2('op_ullong_floordiv_zer', '//', 'r_ulonglong') _makefunc2('op_ullong_mod_zer', '%', 'r_ulonglong') - _makefunc2('op_ullong_lshift_val', '<<', 'r_ulonglong') - _makefunc2('op_ullong_rshift_val', '>>', 'r_ulonglong') def op_int_add_nonneg_ovf(self, x, y): if isinstance(y, int): 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 Wed May 6 18:06:18 2009 @@ -301,10 +301,6 @@ return llmemory.cast_adr_to_ptr(adr, TYPE) op_cast_adr_to_ptr.need_result_type = True -def op_cast_adr_to_int(adr): - checkadr(adr) - return llmemory.cast_adr_to_int(adr) - def op_cast_int_to_adr(int): return llmemory.cast_int_to_adr(int) From arigo at codespeak.net Wed May 6 18:08:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 May 2009 18:08:07 +0200 (CEST) Subject: [pypy-svn] r65114 - pypy/branch/pyjitpl5/pypy/rpython Message-ID: <20090506160807.166DE169EEA@codespeak.net> Author: arigo Date: Wed May 6 18:08:06 2009 New Revision: 65114 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Log: Oups! Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Wed May 6 18:08:06 2009 @@ -801,7 +801,7 @@ return llmemory.cast_ptr_to_adr(ptr) def op_cast_adr_to_int(self, adr): - checkadr(addr) + checkadr(adr) return llmemory.cast_adr_to_int(adr) def op_weakref_create(self, v_obj): From antocuni at codespeak.net Wed May 6 20:14:31 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 20:14:31 +0200 (CEST) Subject: [pypy-svn] r65115 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090506181431.D3156169EC5@codespeak.net> Author: antocuni Date: Wed May 6 20:14:30 2009 New Revision: 65115 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: this test passes again 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 May 6 20:14:30 2009 @@ -148,9 +148,8 @@ res = self.meta_interp(main, [0, 20], optimizer=Optimizer) assert res == 0 -## ootype virtualizable in-progress! -## class TestOOtype(ToyLanguageTests, OOJitMixin): -## pass +class TestOOtype(ToyLanguageTests, OOJitMixin): + pass class TestLLtype(ToyLanguageTests, LLJitMixin): pass From antocuni at codespeak.net Wed May 6 20:15:01 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 20:15:01 +0200 (CEST) Subject: [pypy-svn] r65116 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090506181501.E75C9169EB2@codespeak.net> Author: antocuni Date: Wed May 6 20:15:01 2009 New Revision: 65116 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: fix or skip new test_basic tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Wed May 6 20:15:01 2009 @@ -323,6 +323,9 @@ cls = ootype.cast_from_object(ootype.Class, op.args[0].getobj()) raise NotImplementedError # XXX finish me + def emit_op_ooidentityhash(self, op): + raise NotImplementedError + def emit_op_call(self, op): raise NotImplementedError Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Wed May 6 20:15:01 2009 @@ -107,6 +107,11 @@ res = ootype.runtimenew(classobj) return BoxObj(ootype.cast_to_object(res)) + def do_instanceof(self, args, typedescr): + assert isinstance(typedescr, TypeDescr) + assert len(args) == 1 + return typedescr.instanceof(args[0]) + def do_getfield_gc(self, args, fielddescr): assert isinstance(fielddescr, FieldDescr) return fielddescr.getfield(args[0]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Wed May 6 20:15:01 2009 @@ -28,6 +28,9 @@ test_bridge_from_interpreter_3 = skip test_instantiate_classes = skip test_zerodivisionerror = skip + test_isinstance = skip + test_oois = skip + test_oostring_instance = skip test_stopatxpolicy = _skip test_bridge_from_interpreter = _skip From antocuni at codespeak.net Wed May 6 20:19:42 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 20:19:42 +0200 (CEST) Subject: [pypy-svn] r65117 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090506181942.B91CA169ED8@codespeak.net> Author: antocuni Date: Wed May 6 20:19:40 2009 New Revision: 65117 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Log: fix import, and skip a test that now fails Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Wed May 6 20:19:40 2009 @@ -1,6 +1,6 @@ import py from pypy.jit.backend.cli.runner import CliCPU -from pypy.jit.backend.test.runner import OOtypeBackendTest +from pypy.jit.backend.test.runner_test import OOtypeBackendTest class FakeStats(object): pass @@ -25,3 +25,6 @@ test_passing_guard_class = skip # GUARD_CLASS test_failing_guard_class = skip # GUARD_CLASS + + def test_ovf_operations(self): + py.test.skip('fixme') From antocuni at codespeak.net Wed May 6 20:28:36 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 20:28:36 +0200 (CEST) Subject: [pypy-svn] r65118 - pypy/branch/pyjitpl5/pypy/rpython Message-ID: <20090506182836.8BCC1169E86@codespeak.net> Author: antocuni Date: Wed May 6 20:28:34 2009 New Revision: 65118 Modified: pypy/branch/pyjitpl5/pypy/rpython/rclass.py Log: don't crash if we try to use an UnboxedValue on ootype, but just ignore it. This fixes jit/backend/cli/test_zrpy_basic.py Modified: pypy/branch/pyjitpl5/pypy/rpython/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rclass.py Wed May 6 20:28:34 2009 @@ -55,10 +55,7 @@ assert len(unboxed) == 0 assert gcflavor == 'gc' return rtyper.type_system.rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) - elif len(unboxed) == 0: - return rtyper.type_system.rclass.InstanceRepr(rtyper, classdef, gcflavor) - else: - assert rtyper.type_system.name == 'lltypesystem' + elif len(unboxed) > 0 and rtyper.type_system.name == 'lltypesystem': # the UnboxedValue class and its parent classes need a # special repr for their instances if len(unboxed) != 1: @@ -67,6 +64,8 @@ assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rtagged return rtagged.TaggedInstanceRepr(rtyper, classdef, unboxed[0]) + else: + return rtyper.type_system.rclass.InstanceRepr(rtyper, classdef, gcflavor) class MissingRTypeAttribute(TyperError): From jandem at codespeak.net Wed May 6 20:43:45 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Wed, 6 May 2009 20:43:45 +0200 (CEST) Subject: [pypy-svn] r65119 - in pypy/branch/js-refactoring/pypy: lang/js translator/goal Message-ID: <20090506184345.0FA7F169EB4@codespeak.net> Author: jandem Date: Wed May 6 20:43:44 2009 New Revision: 65119 Added: pypy/branch/js-refactoring/pypy/lang/js/console.py Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/translator/goal/targetjsstandalone.py Log: Add translatable, interactive console. Work-in-progress, but the basics work. Added: pypy/branch/js-refactoring/pypy/lang/js/console.py ============================================================================== --- (empty file) +++ pypy/branch/js-refactoring/pypy/lang/js/console.py Wed May 6 20:43:44 2009 @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +import autopath +import os, sys +from pypy.lang.js.interpreter import load_source, Interpreter, load_file +from pypy.lang.js.jsparser import parse, ParseError +from pypy.lang.js.jsobj import W_Builtin, W_String, ThrowException, w_Undefined +from pypy.rlib.streamio import open_file_as_stream + +def printmessage(msg): + if msg is None: + return + os.write(1, msg) + +def readline(): + result = [] + while 1: + s = os.read(0, 1) + result.append(s) + if s == '\n': + break + + if s == '': + if len(result) > 1: + break + raise SystemExit + return ''.join(result) + +class JSConsole(object): + prompt_ok = 'js> ' + prompt_more = '... ' + + def __init__(self): + self.interpreter = Interpreter() + + def runsource(self, source, filename=''): + try: + ast = load_source(source, filename) + except ParseError, exc: + if exc.source_pos.i == len(source): + # more input needed + return True + else: + # syntax error + self.showsyntaxerror(filename, exc) + return False + + # execute it + self.runcode(ast) + return False + + def runcode(self, ast): + """Run the javascript code in the AST. All exceptions raised + by javascript code must be caught and handled here. When an + exception occurs, self.showtraceback() is called to display a + traceback. + """ + try: + res = self.interpreter.run(ast, interactive=True) + if res is not None and res != w_Undefined: + try: + printmessage(res.ToString(self.interpreter.global_context)) + except ThrowException, exc: + printmessage(exc.exception.ToString(self.interpreter.global_context)) + printmessage('\n') + except SystemExit: + raise + #except ThrowException, exc: + # self.showtraceback(exc) + + def showsyntaxerror(self, filename, exc): + pass + + def interact(self): + printmessage('PyPy JavaScript Interpreter\n') + printmessage(self.prompt_ok) + + lines = [] + + while True: + try: + line = readline() + except SystemExit, e: + printmessage('\n') + return + + lines.append(line) + + source = ''.join(lines) + need_more = self.runsource(source) + + if need_more: + printmessage(self.prompt_more) + else: + printmessage(self.prompt_ok) + lines = [] + +if __name__ == '__main__': + console = JSConsole() + console.interact() Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Wed May 6 20:43:44 2009 @@ -725,8 +725,9 @@ w_math.Put(ctx, 'E', W_FloatNumber(math.e), flags=allon) w_math.Put(ctx, 'LN2', W_FloatNumber(math.log(2)), flags=allon) w_math.Put(ctx, 'LN10', W_FloatNumber(math.log(10)), flags=allon) - #w_math.Put(ctx, 'LOG2E', W_FloatNumber(math.log(math.e, 2)), flags=allon) - #w_math.Put(ctx, 'LOG10E', W_FloatNumber(math.log(math.e, 10)), flags=allon) + log2e = math.log(math.e) / math.log(2) # rpython supports log with one argument only + w_math.Put(ctx, 'LOG2E', W_FloatNumber(log2e), flags=allon) + w_math.Put(ctx, 'LOG10E', W_FloatNumber(math.log10(math.e)), flags=allon) w_math.Put(ctx, 'PI', W_FloatNumber(math.pi), flags=allon) w_math.Put(ctx, 'SQRT1_2', W_FloatNumber(math.sqrt(0.5)), flags=allon) w_math.Put(ctx, 'SQRT2', W_FloatNumber(math.sqrt(2)), flags=allon) Modified: pypy/branch/js-refactoring/pypy/translator/goal/targetjsstandalone.py ============================================================================== --- pypy/branch/js-refactoring/pypy/translator/goal/targetjsstandalone.py (original) +++ pypy/branch/js-refactoring/pypy/translator/goal/targetjsstandalone.py Wed May 6 20:43:44 2009 @@ -6,6 +6,7 @@ import sys from pypy.lang.js.interpreter import * +from pypy.lang.js.console import JSConsole # __________ Entry point __________ @@ -15,6 +16,12 @@ def entry_point(argv): i = 1 + + if len(argv) == 1: + console = JSConsole() + console.interact() + return 0 + interp = Interpreter() while i < len(argv): arg = argv[i] From antocuni at codespeak.net Wed May 6 20:44:51 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 May 2009 20:44:51 +0200 (CEST) Subject: [pypy-svn] r65120 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090506184451.CDCC5169EBE@codespeak.net> Author: antocuni Date: Wed May 6 20:44:50 2009 New Revision: 65120 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (contents, props changed) Log: more translated tests Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/__init__.py ============================================================================== Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Wed May 6 20:44:50 2009 @@ -0,0 +1,22 @@ +import py +from pypy.jit.backend.cli.test.test_zrpy_basic import CliTranslatedJitMixin +from pypy.jit.metainterp.test import test_send + + +class TestSend(CliTranslatedJitMixin, test_send.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_send.py + + def skip(self): + py.test.skip('in-progress') + + test_red_builtin_send = skip + test_send_to_single_target_method = skip + test_oosend_base = skip + test_three_receivers = skip + test_oosend_different_initial_class = skip + test_indirect_call_unknown_object_1 = skip + test_three_cases = skip + test_three_classes = skip + test_recursive_call_to_portal_from_blackhole = skip + test_residual_oosend = skip From antocuni at codespeak.net Thu May 7 00:23:31 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 00:23:31 +0200 (CEST) Subject: [pypy-svn] r65121 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090506222331.4F9F5169E8F@codespeak.net> Author: antocuni Date: Thu May 7 00:23:28 2009 New Revision: 65121 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: implement emit_op_call and emit_op_oosend, and test_red_builtin_oosend passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 7 00:23:28 2009 @@ -8,6 +8,7 @@ from pypy.jit.metainterp.history import (AbstractValue, Const, ConstInt, ConstObj) from pypy.jit.metainterp.resoperation import rop, opname +from pypy.jit.backend.cli import runner from pypy.jit.backend.cli.methodfactory import get_method_wrapper System = CLR.System @@ -327,14 +328,41 @@ raise NotImplementedError def emit_op_call(self, op): - raise NotImplementedError + calldescr = op.descr + assert isinstance(calldescr, runner.StaticMethDescr) + delegate_type = dotnet.class2type(calldescr.funcclass) + meth_invoke = delegate_type.GetMethod('Invoke') + av_sm, args_av = op.args[0], op.args[1:] + av_sm.load(self) + self.il.Emit(OpCodes.Castclass, delegate_type) + for av_arg in args_av: + av_arg.load(self) + self.il.EmitCall(OpCodes.Callvirt, meth_invoke, None) + if calldescr.has_result: + self.store_result(op) emit_op_call_pure = emit_op_call + def emit_op_oosend(self, op): + methdescr = op.descr + assert isinstance(methdescr, runner.MethDescr) + clitype = dotnet.class2type(methdescr.selfclass) + methinfo = clitype.GetMethod(str(methdescr.methname)) + av_sm, args_av = op.args[0], op.args[1:] + av_sm.load(self) + self.il.Emit(OpCodes.Castclass, clitype) + for av_arg in args_av: + av_arg.load(self) + self.il.Emit(OpCodes.Callvirt, methinfo) + if methdescr.has_result: + self.store_result(op) + + emit_op_oosend_pure = emit_op_oosend + + def not_implemented(self, op): raise NotImplementedError - emit_op_oosend = not_implemented emit_op_guard_exception = not_implemented emit_op_cast_int_to_ptr = not_implemented emit_op_guard_nonvirtualized = not_implemented @@ -348,7 +376,6 @@ emit_op_strgetitem = not_implemented emit_op_getfield_raw = not_implemented emit_op_setfield_gc = not_implemented - emit_op_oosend_pure = not_implemented emit_op_getarrayitem_gc_pure = not_implemented emit_op_arraylen_gc = not_implemented emit_op_unicodesetitem = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 7 00:23:28 2009 @@ -6,7 +6,6 @@ from pypy.jit.backend import model from pypy.jit.backend.minimal.runner import cached_method from pypy.jit.backend.llgraph.runner import TypeDescr, FieldDescr -from pypy.jit.backend.cli.method import Method from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -51,6 +50,7 @@ # ---------------------- def compile_operations(self, loop): + from pypy.jit.backend.cli.method import Method meth = Method(self, loop.name, loop) loop._cli_meth = meth @@ -147,6 +147,7 @@ return boxresult(RESULT, res) self.callfunc = callfunc self.funcclass = dotnet.classof(FUNC) + self.has_result = (FUNC.RESULT != ootype.Void) class MethDescr(AbstractMethDescr): @@ -166,7 +167,10 @@ if METH.RESULT is not ootype.Void: return boxresult(METH.RESULT, res) self.callmeth = callmeth + self.selfclass = ootype.runtimeClass(SELFTYPE) + self.methname = methname + self.has_result = (METH.RESULT != ootype.Void) CPU = CliCPU Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Thu May 7 00:23:28 2009 @@ -10,7 +10,6 @@ def skip(self): py.test.skip('in-progress') - test_red_builtin_send = skip test_send_to_single_target_method = skip test_oosend_base = skip test_three_receivers = skip From antocuni at codespeak.net Thu May 7 10:44:58 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 10:44:58 +0200 (CEST) Subject: [pypy-svn] r65123 - in pypy/branch/pyjitpl5/pypy/jit/backend: cli cli/test llgraph test Message-ID: <20090507084458.6B132169EC0@codespeak.net> Author: antocuni Date: Thu May 7 10:44:55 2009 New Revision: 65123 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py Log: - refactor emit_op_call and emit_op_oosend to share common logic - implement emit_op_getfield_gc, to make test_send_to_single_target_method passing Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 7 10:44:55 2009 @@ -328,36 +328,44 @@ raise NotImplementedError def emit_op_call(self, op): - calldescr = op.descr - assert isinstance(calldescr, runner.StaticMethDescr) - delegate_type = dotnet.class2type(calldescr.funcclass) - meth_invoke = delegate_type.GetMethod('Invoke') - av_sm, args_av = op.args[0], op.args[1:] - av_sm.load(self) - self.il.Emit(OpCodes.Castclass, delegate_type) - for av_arg in args_av: - av_arg.load(self) - self.il.EmitCall(OpCodes.Callvirt, meth_invoke, None) - if calldescr.has_result: - self.store_result(op) + descr = op.descr + assert isinstance(descr, runner.StaticMethDescr) + delegate_type = descr.get_delegate_clitype() + meth_invoke = descr.get_meth_info() + self._emit_call(op, delegate_type, meth_invoke, descr.has_result) emit_op_call_pure = emit_op_call def emit_op_oosend(self, op): - methdescr = op.descr - assert isinstance(methdescr, runner.MethDescr) - clitype = dotnet.class2type(methdescr.selfclass) - methinfo = clitype.GetMethod(str(methdescr.methname)) + descr = op.descr + assert isinstance(descr, runner.MethDescr) + clitype = descr.get_self_clitype() + methinfo = descr.get_meth_info() + self._emit_call(op, clitype, methinfo, descr.has_result) + + emit_op_oosend_pure = emit_op_oosend + + def _emit_call(self, op, clitype, methinfo, has_result): av_sm, args_av = op.args[0], op.args[1:] av_sm.load(self) self.il.Emit(OpCodes.Castclass, clitype) for av_arg in args_av: av_arg.load(self) self.il.Emit(OpCodes.Callvirt, methinfo) - if methdescr.has_result: + if has_result: self.store_result(op) - emit_op_oosend_pure = emit_op_oosend + def emit_op_getfield_gc(self, op): + descr = op.descr + assert isinstance(descr, runner.FieldDescr) + clitype = descr.get_self_clitype() + fieldinfo = descr.get_field_info() + op.args[0].load(self) + self.il.Emit(OpCodes.Castclass, clitype) + self.il.Emit(OpCodes.Ldfld, fieldinfo) + self.store_result(op) + + emit_op_getfield_gc_pure = emit_op_getfield_gc def not_implemented(self, op): @@ -380,9 +388,7 @@ emit_op_arraylen_gc = not_implemented emit_op_unicodesetitem = not_implemented emit_op_getfield_raw_pure = not_implemented - emit_op_getfield_gc_pure = not_implemented emit_op_getarrayitem_gc = not_implemented - emit_op_getfield_gc = not_implemented emit_op_strlen = not_implemented emit_op_newstr = not_implemented emit_op_strsetitem = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 7 10:44:55 2009 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model from pypy.jit.backend.minimal.runner import cached_method -from pypy.jit.backend.llgraph.runner import TypeDescr, FieldDescr +from pypy.jit.backend.llgraph.runner import TypeDescr, KeyManager from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -133,6 +133,8 @@ # ---------------------------------------------------------------------- +key_manager = KeyManager() + class StaticMethDescr(AbstractDescr): @@ -149,6 +151,13 @@ self.funcclass = dotnet.classof(FUNC) self.has_result = (FUNC.RESULT != ootype.Void) + def get_delegate_clitype(self): + return dotnet.class2type(self.funcclass) + + def get_meth_info(self): + clitype = self.get_delegate_clitype() + return clitype.GetMethod('Invoke') + class MethDescr(AbstractMethDescr): @@ -169,9 +178,54 @@ self.callmeth = callmeth self.selfclass = ootype.runtimeClass(SELFTYPE) self.methname = methname - self.has_result = (METH.RESULT != ootype.Void) + def get_self_clitype(self): + return dotnet.class2type(self.selfclass) + + def get_meth_info(self): + clitype = self.get_self_clitype() + return clitype.GetMethod(str(self.methname)) + + +class FieldDescr(AbstractDescr): + + getfield = None + _keys = KeyManager() + + def __init__(self, TYPE, fieldname): + from pypy.jit.backend.llgraph.runner import boxresult + _, T = TYPE._lookup_field(fieldname) + def getfield(objbox): + obj = ootype.cast_from_object(TYPE, objbox.getobj()) + value = getattr(obj, fieldname) + return boxresult(T, value) + def setfield(objbox, valuebox): + obj = ootype.cast_from_object(TYPE, objbox.getobj()) + value = unwrap(T, valuebox) + setattr(obj, fieldname, value) + + self.getfield = getfield + self.setfield = setfield + self.selfclass = ootype.runtimeClass(TYPE) + self.fieldname = fieldname + self.key = key_manager.getkey((TYPE, fieldname)) + + def sort_key(self): + return self.key + + def equals(self, other): + assert isinstance(other, FieldDescr) + return self.key == other.key + + def get_self_clitype(self): + return dotnet.class2type(self.selfclass) + + def get_field_info(self): + clitype = self.get_self_clitype() + return clitype.GetField(str(self.fieldname)) + + CPU = CliCPU import pypy.jit.metainterp.executor Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Thu May 7 10:44:55 2009 @@ -10,7 +10,6 @@ def skip(self): py.test.skip('in-progress') - test_send_to_single_target_method = skip test_oosend_base = skip test_three_receivers = skip test_oosend_different_initial_class = skip 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 May 7 10:44:55 2009 @@ -539,6 +539,9 @@ self.keys[key] = n return n + def _freeze_(self): + raise Exception("KeyManager is not supposed to be turned into a pbc") + descr_cache = {} class OODescr(history.AbstractDescr): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py Thu May 7 10:44:55 2009 @@ -14,7 +14,8 @@ def _compile_and_run(self, t, entry_point, entry_point_graph, args): raise NotImplementedError - def meta_interp(self, function, args, repeat=1, **kwds): # XXX ignored + # XXX backendopt is ignored + def meta_interp(self, function, args, repeat=1, backendopt=None, **kwds): # XXX ignored from pypy.jit.metainterp.warmspot import WarmRunnerDesc from pypy.annotation.listdef import s_list_of_strings from pypy.annotation import model as annmodel From antocuni at codespeak.net Thu May 7 11:08:11 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 11:08:11 +0200 (CEST) Subject: [pypy-svn] r65124 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090507090811.34EB91683D5@codespeak.net> Author: antocuni Date: Thu May 7 11:08:10 2009 New Revision: 65124 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: implement emit_op_new_with_vtable and emit_op_setfield_gc: test_oosend_base passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 7 11:08:10 2009 @@ -320,9 +320,13 @@ self.il.Emit(OpCodes.Br, self.il_loop_start) def emit_op_new_with_vtable(self, op): - assert isinstance(op.args[0], ConstObj) - cls = ootype.cast_from_object(ootype.Class, op.args[0].getobj()) - raise NotImplementedError # XXX finish me + assert isinstance(op.args[0], ConstObj) # ignored, using the descr instead + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + clitype = descr.get_clitype() + ctor_info = descr.get_constructor_info() + self.il.Emit(OpCodes.Newobj, ctor_info) + self.store_result(op) def emit_op_ooidentityhash(self, op): raise NotImplementedError @@ -367,6 +371,16 @@ emit_op_getfield_gc_pure = emit_op_getfield_gc + def emit_op_setfield_gc(self, op): + descr = op.descr + assert isinstance(descr, runner.FieldDescr) + clitype = descr.get_self_clitype() + fieldinfo = descr.get_field_info() + op.args[0].load(self) + self.il.Emit(OpCodes.Castclass, clitype) + op.args[1].load(self) + self.il.Emit(OpCodes.Stfld, fieldinfo) + def not_implemented(self, op): raise NotImplementedError @@ -383,7 +397,6 @@ emit_op_unicodegetitem = not_implemented emit_op_strgetitem = not_implemented emit_op_getfield_raw = not_implemented - emit_op_setfield_gc = not_implemented emit_op_getarrayitem_gc_pure = not_implemented emit_op_arraylen_gc = not_implemented emit_op_unicodesetitem = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 7 11:08:10 2009 @@ -5,7 +5,7 @@ from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model from pypy.jit.backend.minimal.runner import cached_method -from pypy.jit.backend.llgraph.runner import TypeDescr, KeyManager +from pypy.jit.backend.llgraph.runner import KeyManager from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -136,6 +136,45 @@ key_manager = KeyManager() +class TypeDescr(AbstractDescr): + + def __init__(self, TYPE): + from pypy.jit.backend.llgraph.runner import boxresult + def create(): + return boxresult(TYPE, ootype.new(TYPE)) + def create_array(lengthbox): + n = lengthbox.getint() + return boxresult(ARRAY, ootype.oonewarray(ARRAY, n)) + def getarrayitem(arraybox, ibox): + array = ootype.cast_from_object(ARRAY, arraybox.getobj()) + i = ibox.getint() + return boxresult(TYPE, array.ll_getitem_fast(i)) + def setarrayitem(arraybox, ibox, valuebox): + array = ootype.cast_from_object(ARRAY, arraybox.getobj()) + i = ibox.getint() + value = unwrap(TYPE, valuebox) + array.ll_setitem_fast(i, value) + def getarraylength(arraybox): + array = ootype.cast_from_object(ARRAY, arraybox.getobj()) + return boxresult(ootype.Signed, array.ll_length()) + def instanceof(box): + obj = ootype.cast_from_object(ootype.ROOT, box.getobj()) + return history.BoxInt(ootype.instanceof(obj, TYPE)) + self.create = create + self.create_array = create_array + self.getarrayitem = getarrayitem + self.setarrayitem = setarrayitem + self.getarraylength = getarraylength + self.instanceof = instanceof + self.ooclass = ootype.runtimeClass(TYPE) + + def get_clitype(self): + return dotnet.class2type(self.ooclass) + + def get_constructor_info(self): + clitype = self.get_clitype() + return clitype.GetConstructor(dotnet.new_array(System.Type, 0)) + class StaticMethDescr(AbstractDescr): def __init__(self, FUNC, ARGS, RESULT): @@ -195,6 +234,7 @@ def __init__(self, TYPE, fieldname): from pypy.jit.backend.llgraph.runner import boxresult + from pypy.jit.metainterp.warmspot import unwrap _, T = TYPE._lookup_field(fieldname) def getfield(objbox): obj = ootype.cast_from_object(TYPE, objbox.getobj()) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Thu May 7 11:08:10 2009 @@ -10,7 +10,6 @@ def skip(self): py.test.skip('in-progress') - test_oosend_base = skip test_three_receivers = skip test_oosend_different_initial_class = skip test_indirect_call_unknown_object_1 = skip From jandem at codespeak.net Thu May 7 11:38:45 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Thu, 7 May 2009 11:38:45 +0200 (CEST) Subject: [pypy-svn] r65125 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090507093845.4CEB1169F1C@codespeak.net> Author: jandem Date: Thu May 7 11:38:42 2009 New Revision: 65125 Modified: pypy/branch/js-refactoring/pypy/lang/js/console.py Log: JS console: show traceback/exception, add load() and quit() Modified: pypy/branch/js-refactoring/pypy/lang/js/console.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/console.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/console.py Thu May 7 11:38:42 2009 @@ -4,13 +4,12 @@ import os, sys from pypy.lang.js.interpreter import load_source, Interpreter, load_file from pypy.lang.js.jsparser import parse, ParseError -from pypy.lang.js.jsobj import W_Builtin, W_String, ThrowException, w_Undefined +from pypy.lang.js.jsobj import W_NewBuiltin, W_String, ThrowException, w_Undefined from pypy.rlib.streamio import open_file_as_stream def printmessage(msg): - if msg is None: - return - os.write(1, msg) + if msg is not None: + os.write(1, msg) def readline(): result = [] @@ -19,19 +18,46 @@ result.append(s) if s == '\n': break - + if s == '': if len(result) > 1: break raise SystemExit return ''.join(result) +class W_Quit(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + raise SystemExit, 0 + +class W_Load(W_NewBuiltin): + def __init__(self, ctx, interpreter): + W_NewBuiltin.__init__(self, ctx) + self.interpreter = interpreter + + def Call(self, ctx, args=[], this=None): + if len(args) >= 1: + filename = args[0].ToString(self.interpreter.global_context) + try: + assert filename is not None + program = load_file(filename) + except EnvironmentError, e: + msg = W_String("Can't open %s: %s" % (filename, e)) + raise ThrowException(msg) + self.interpreter.run(program) + return w_Undefined + class JSConsole(object): prompt_ok = 'js> ' prompt_more = '... ' def __init__(self): - self.interpreter = Interpreter() + interp = Interpreter() + ctx = interp.global_context + + interp.w_Global.Put(ctx, 'quit', W_Quit(ctx)) + interp.w_Global.Put(ctx, 'load', W_Load(ctx, interp)) + + self.interpreter = interp def runsource(self, source, filename=''): try: @@ -65,16 +91,24 @@ printmessage('\n') except SystemExit: raise - #except ThrowException, exc: - # self.showtraceback(exc) + except ThrowException, exc: + self.showtraceback(exc) + + def showtraceback(self, exc): + printmessage(exc.exception.ToString(self.interpreter.global_context)) + printmessage('\n') def showsyntaxerror(self, filename, exc): - pass + printmessage(' ' * 4 + \ + ' ' * exc.source_pos.columnno + \ + '^\n') + printmessage('Syntax Error\n') def interact(self): printmessage('PyPy JavaScript Interpreter\n') printmessage(self.prompt_ok) + # input for the current statement lines = [] while True: From antocuni at codespeak.net Thu May 7 11:42:36 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 11:42:36 +0200 (CEST) Subject: [pypy-svn] r65126 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090507094236.AB0B8169E3B@codespeak.net> Author: antocuni Date: Thu May 7 11:42:36 2009 New Revision: 65126 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: test_oosend_different_initial_class passed out of the box. Moreover, add few translation fixes, but the tests still fail for other reasons Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 7 11:42:36 2009 @@ -201,6 +201,9 @@ class MethDescr(AbstractMethDescr): callmeth = None + selfclass = ootype.nullruntimeclass + methname = '' + has_result = False def __init__(self, SELFTYPE, methname): from pypy.jit.backend.llgraph.runner import boxresult, make_getargs @@ -224,13 +227,16 @@ def get_meth_info(self): clitype = self.get_self_clitype() - return clitype.GetMethod(str(self.methname)) + return clitype.GetMethod(self.methname+'') class FieldDescr(AbstractDescr): getfield = None - _keys = KeyManager() + setfield = None + selfclass = ootype.nullruntimeclass + fieldname = '' + key = -1 def __init__(self, TYPE, fieldname): from pypy.jit.backend.llgraph.runner import boxresult @@ -263,7 +269,7 @@ def get_field_info(self): clitype = self.get_self_clitype() - return clitype.GetField(str(self.fieldname)) + return clitype.GetField(self.fieldname+'') CPU = CliCPU Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Thu May 7 11:42:36 2009 @@ -7,11 +7,14 @@ # for the individual tests see # ====> ../../../metainterp/test/test_send.py + def skip_loop(self): + py.test.skip('jump across loops not implemented yet') + def skip(self): py.test.skip('in-progress') - test_three_receivers = skip - test_oosend_different_initial_class = skip + test_three_receivers = skip_loop + test_indirect_call_unknown_object_1 = skip test_three_cases = skip test_three_classes = skip From antocuni at codespeak.net Thu May 7 11:47:26 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 11:47:26 +0200 (CEST) Subject: [pypy-svn] r65127 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090507094726.24A06169E7B@codespeak.net> Author: antocuni Date: Thu May 7 11:47:25 2009 New Revision: 65127 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: more rpython fixes. One more test passes, and add comments about why the others fail Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 7 11:47:25 2009 @@ -177,6 +177,10 @@ class StaticMethDescr(AbstractDescr): + callfunc = None + funcclass = ootype.nullruntimeclass + has_result = False + def __init__(self, FUNC, ARGS, RESULT): from pypy.jit.backend.llgraph.runner import boxresult, make_getargs getargs = make_getargs(FUNC.ARGS) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Thu May 7 11:47:25 2009 @@ -14,9 +14,9 @@ py.test.skip('in-progress') test_three_receivers = skip_loop + test_three_classes = skip_loop + test_recursive_call_to_portal_from_blackhole = skip_loop - test_indirect_call_unknown_object_1 = skip - test_three_cases = skip - test_three_classes = skip - test_recursive_call_to_portal_from_blackhole = skip - test_residual_oosend = skip + test_indirect_call_unknown_object_1 = skip # cast_to_object of StaticMethods + test_three_cases = skip # seems an annotator bug :-/ + From jandem at codespeak.net Thu May 7 11:49:34 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Thu, 7 May 2009 11:49:34 +0200 (CEST) Subject: [pypy-svn] r65128 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090507094934.425D0169E7B@codespeak.net> Author: jandem Date: Thu May 7 11:49:33 2009 New Revision: 65128 Modified: pypy/branch/js-refactoring/pypy/lang/js/console.py Log: Make readline() available to JS, to ask for user input. Modified: pypy/branch/js-refactoring/pypy/lang/js/console.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/console.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/console.py Thu May 7 11:49:33 2009 @@ -15,10 +15,10 @@ result = [] while 1: s = os.read(0, 1) - result.append(s) if s == '\n': break - + else: + result.append(s) if s == '': if len(result) > 1: break @@ -46,6 +46,10 @@ self.interpreter.run(program) return w_Undefined +class W_ReadLine(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + return W_String(readline()) + class JSConsole(object): prompt_ok = 'js> ' prompt_more = '... ' @@ -56,6 +60,7 @@ interp.w_Global.Put(ctx, 'quit', W_Quit(ctx)) interp.w_Global.Put(ctx, 'load', W_Load(ctx, interp)) + interp.w_Global.Put(ctx, 'readline', W_ReadLine(ctx)) self.interpreter = interp From arigo at codespeak.net Thu May 7 12:52:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 12:52:35 +0200 (CEST) Subject: [pypy-svn] r65129 - pypy/branch/pyjitpl5/pypy/doc/config Message-ID: <20090507105235.6B15C169E73@codespeak.net> Author: arigo Date: Thu May 7 12:52:34 2009 New Revision: 65129 Added: pypy/branch/pyjitpl5/pypy/doc/config/translation.jit_backend.txt (contents, props changed) Log: Document the option --jit-backend. Added: pypy/branch/pyjitpl5/pypy/doc/config/translation.jit_backend.txt ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/doc/config/translation.jit_backend.txt Thu May 7 12:52:34 2009 @@ -0,0 +1,2 @@ +Choose the backend to use for the JIT. +By default, this is the best backend for the current platform. From arigo at codespeak.net Thu May 7 13:02:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 13:02:46 +0200 (CEST) Subject: [pypy-svn] r65130 - in pypy/branch/pyjitpl5/pypy/jit/backend: llgraph/test test Message-ID: <20090507110246.58E0A169E9C@codespeak.net> Author: arigo Date: Thu May 7 13:02:45 2009 New Revision: 65130 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Log: Fix the test, notably test_ovf_operations_reversed. 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 Thu May 7 13:02:45 2009 @@ -1,5 +1,4 @@ import py -from pypy.translator import translator from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rclass from pypy.rpython.test.test_llinterp import interpret from pypy.rlib.unroll import unrolling_iterable @@ -8,7 +7,7 @@ TreeLoop from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.executor import execute -from pypy.jit.backend.test.runner import LLtypeBackendTest +from pypy.jit.backend.test.runner_test import LLtypeBackendTest NODE = lltype.GcForwardReference() NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed), @@ -20,11 +19,7 @@ class LLGraphTests: def setup_method(self, _): - context = translator.TranslationContext() - context.buildannotator() - typer = context.buildrtyper() - typer.getexceptiondata().make_helpers(typer) - self.cpu = self.cpu_type(typer) + self.cpu = self.cpu_type(None) def eval_llinterp(self, runme, *args, **kwds): expected_class = kwds.pop('expected_class', None) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Thu May 7 13:02:45 2009 @@ -189,10 +189,10 @@ ovferror = self.cpu.get_exception() self.cpu.clear_exception() if self.cpu.is_oo: - v_exc = BoxPtr() + v_exc = BoxObj() c_ovferror = ConstObj(ovferror) else: - v_exc = BoxObj() + v_exc = BoxPtr() c_ovferror = ConstInt(ovferror) ops = [ ResOperation(opnum, [v1, v2], v_res), @@ -218,7 +218,12 @@ if z != boom: assert self.cpu.get_latest_value_int(0) == z ovferror = self.cpu.get_exception() - if ovferror: + if reversed: + # in the 'reversed' case, ovferror should always be + # consumed: either it is not set in the first place, + # or it is set and GUARD_EXCEPTION succeeds. + assert not ovferror + elif ovferror: assert z == boom self.cpu.clear_exception() else: From arigo at codespeak.net Thu May 7 13:06:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 13:06:22 +0200 (CEST) Subject: [pypy-svn] r65131 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090507110622.39A1F169E1C@codespeak.net> Author: arigo Date: Thu May 7 13:06:21 2009 New Revision: 65131 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Log: Skip test_ovf_operations_reversed too. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Thu May 7 13:06:21 2009 @@ -26,5 +26,5 @@ test_passing_guard_class = skip # GUARD_CLASS test_failing_guard_class = skip # GUARD_CLASS - def test_ovf_operations(self): + def test_ovf_operations(self, reversed=False): py.test.skip('fixme') From arigo at codespeak.net Thu May 7 13:13:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 13:13:48 +0200 (CEST) Subject: [pypy-svn] r65132 - in pypy/branch/pyjitpl5/pypy/jit/backend: test x86 Message-ID: <20090507111348.424EF169E49@codespeak.net> Author: arigo Date: Thu May 7 13:13:47 2009 New Revision: 65132 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: Fix, according to test_ovf_operations_reversed. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Thu May 7 13:13:47 2009 @@ -208,6 +208,7 @@ loop.inputargs = [v1, v2] self.cpu.compile_operations(loop) for x, y, z in testcases: + assert not self.cpu.get_exception() self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) op = self.cpu.execute_operations(loop) 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 Thu May 7 13:13:47 2009 @@ -803,7 +803,8 @@ exc = False if ovf: regalloc.position = -1 - self.generate_ovf_set() + if guard_op.opnum == rop.GUARD_NO_EXCEPTION: + self.generate_ovf_set() exc = True if (guard_op.opnum == rop.GUARD_EXCEPTION or guard_op.opnum == rop.GUARD_NO_EXCEPTION): From cfbolz at codespeak.net Thu May 7 14:00:26 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 May 2009 14:00:26 +0200 (CEST) Subject: [pypy-svn] r65133 - in pypy/branch/tagged-pointers-framework/pypy/rpython/memory: gctransform test Message-ID: <20090507120026.12BF2169E53@codespeak.net> Author: cfbolz Date: Thu May 7 14:00:26 2009 New Revision: 65133 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py Log: tests with prebuilt data structures. This finds a bug. The tests still fails on mark-n-sweep, no clue why yet. Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py Thu May 7 14:00:26 2009 @@ -843,7 +843,7 @@ end = gcdata.static_root_nongcend while addr != end: result = addr.address[0] - if result.address[0] != llmemory.NULL: + if self.gc.points_to_valid_gc_object(result): collect_static_in_prebuilt_nongc(gc, result) addr += sizeofaddr if collect_static_in_prebuilt_gc: @@ -851,7 +851,7 @@ end = gcdata.static_root_end while addr != end: result = addr.address[0] - if result.address[0] != llmemory.NULL: + if self.gc.points_to_valid_gc_object(result): collect_static_in_prebuilt_gc(gc, result) addr += sizeofaddr if collect_stack_root: Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Thu May 7 14:00:26 2009 @@ -472,36 +472,20 @@ assert self.interpret(f, []) == 2 - def test_tagged(self): + def test_tagged_simple(self): from pypy.rlib.objectmodel import UnboxedValue - class A(object): - __slots__ = () - def meth(self, x): - raise NotImplementedError - - class B(A): - attrvalue = 66 - def __init__(self, normalint): - self.normalint = normalint - def meth(self, x): - return self.normalint + x + 2 - - class C(A, UnboxedValue): - __slots__ = 'smallint' - def meth(self, x): - return self.smallint + x + 3 class Unrelated(object): pass u = Unrelated() - u.x = C(47) + u.x = UnboxedObject(47) def fn(n): rgc.collect() # check that a prebuilt tagged pointer doesn't explode if n > 0: - x = B(n) + x = BoxedObject(n) else: - x = C(n) + x = UnboxedObject(n) u.x = x # invoke write barrier rgc.collect() return x.meth(100) @@ -510,6 +494,46 @@ res = self.interpret(fn, [-1000]) assert res == -897 + def test_tagged_prebuilt(self): + + class F: + pass + + f = F() + f.l = [UnboxedObject(10)] + def fn(n): + if n > 0: + x = BoxedObject(n) + else: + x = UnboxedObject(n) + f.l.append(x) + rgc.collect() + return f.l[-1].meth(100) + res = self.interpret(fn, [1000]) + assert res == 1102 + res = self.interpret(fn, [-1000]) + assert res == -897 + +from pypy.rlib.objectmodel import UnboxedValue + +class TaggedBase(object): + __slots__ = () + def meth(self, x): + raise NotImplementedError + +class BoxedObject(TaggedBase): + attrvalue = 66 + def __init__(self, normalint): + self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + +class UnboxedObject(TaggedBase, UnboxedValue): + __slots__ = 'smallint' + def meth(self, x): + return self.smallint + x + 3 + + class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py Thu May 7 14:00:26 2009 @@ -526,28 +526,18 @@ assert res == 'y' def test_tagged(self): - from pypy.rlib.objectmodel import UnboxedValue - class A(object): - __slots__ = () - def meth(self, x): - raise NotImplementedError + class Unrelated(object): + pass - class B(A): - attrvalue = 66 - def __init__(self, normalint): - self.normalint = normalint - def meth(self, x): - return self.normalint + x + 2 - - class C(A, UnboxedValue): - __slots__ = 'smallint' - def meth(self, x): - return self.smallint + x + 3 + u = Unrelated() + u.x = UnboxedObject(47) def fn(n): + rgc.collect() # check that a prebuilt tagged pointer doesn't explode if n > 0: - x = B(n) + x = BoxedObject(n) else: - x = C(n) + x = UnboxedObject(n) + u.x = x # invoke write barrier rgc.collect() return x.meth(100) def func(): @@ -556,6 +546,26 @@ res = func([]) assert res == fn(1000) + fn(-1000) +from pypy.rlib.objectmodel import UnboxedValue + +class TaggedBase(object): + __slots__ = () + def meth(self, x): + raise NotImplementedError + +class BoxedObject(TaggedBase): + attrvalue = 66 + def __init__(self, normalint): + self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + +class UnboxedObject(TaggedBase, UnboxedValue): + __slots__ = 'smallint' + def meth(self, x): + return self.smallint + x + 3 + + class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True GC_CANNOT_MALLOC_NONMOVABLE = True From david at codespeak.net Thu May 7 14:47:31 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 7 May 2009 14:47:31 +0200 (CEST) Subject: [pypy-svn] r65134 - pypy/branch/io-lang/pypy/lang/io Message-ID: <20090507124731.091B4169E00@codespeak.net> Author: david Date: Thu May 7 14:47:29 2009 New Revision: 65134 Modified: pypy/branch/io-lang/pypy/lang/io/number.py pypy/branch/io-lang/pypy/lang/io/register.py Log: (cfbolz, david) unwrap spec for registering functions Modified: pypy/branch/io-lang/pypy/lang/io/number.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/number.py (original) +++ pypy/branch/io-lang/pypy/lang/io/number.py Thu May 7 14:47:29 2009 @@ -1,11 +1,10 @@ from pypy.lang.io.register import register_method from pypy.lang.io.model import W_Number - at register_method("Number", '+') -def w_number_add(space, w_target, w_message, w_context): - w_arg = w_message.arguments[0].eval(space, w_context, w_context) - return W_Number(space, w_target.value + w_arg.value) + + at register_method("Number", '+', unwrap_spec=[float, float]) +def w_number_add(space, target, argument): + return W_Number(space, target + argument) - at register_method("Number", '-') -def w_number_minus(space, w_target, w_message, w_context): - w_arg = w_message.arguments[0].eval(space, w_context, w_context) - return W_Number(space, w_target.value - w_arg.value) \ No newline at end of file + at register_method("Number", '-', unwrap_spec=[float, float]) +def w_number_minus(space, target, argument): + return W_Number(space, target - argument) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/register.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/register.py (original) +++ pypy/branch/io-lang/pypy/lang/io/register.py Thu May 7 14:47:29 2009 @@ -1,7 +1,30 @@ +from pypy.lang.io import model cfunction_definitions = {} -def register_method(type_name, slot_name): +def register_method(type_name, slot_name, unwrap_spec=None): def register(function): + if unwrap_spec is None: + wrapper = function + else: + def wrapper(space, w_target, w_message, w_context): + evaled_w = [w_target] + for i in range(len(unwrap_spec)-1): + evaled_w.append( + w_message.arguments[i].eval( + space, w_context, w_context)) + + args = () + for x, typ in zip(evaled_w, unwrap_spec): + if typ is float: + assert isinstance(x, model.W_Number) + args += (x.value, ) + elif typ is object: + args += (x, ) + else: + raise ValueError, 'Unknown unwrap spec' + return function(space, *args) subdict = cfunction_definitions.setdefault(type_name, {}) - subdict[slot_name] = function + subdict[slot_name] = wrapper + return function + return register \ No newline at end of file From arigo at codespeak.net Thu May 7 14:56:05 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 14:56:05 +0200 (CEST) Subject: [pypy-svn] r65135 - pypy/build/doc Message-ID: <20090507125605.1331F169E45@codespeak.net> Author: arigo Date: Thu May 7 14:56:05 2009 New Revision: 65135 Modified: pypy/build/doc/ssh_config Log: Don't use "StrictHostKeyChecking no". It's better to make aliases with "HostKeyAlias". Some versions of ssh disable port forwarding if they see "StrictHostKeyChecking no", for some reason. Modified: pypy/build/doc/ssh_config ============================================================================== --- pypy/build/doc/ssh_config (original) +++ pypy/build/doc/ssh_config Thu May 7 14:56:05 2009 @@ -1,21 +1,21 @@ Host bigdog2 Hostname 8.8.197.72 - StrictHostKeyChecking no + HostKeyAlias bigdog2 Host bigdog6 Hostname 8.8.197.72 Port 2222 - StrictHostKeyChecking no + HostKeyAlias bigdog6 Host bigdog-vm1 Hostname 8.8.197.72 Port 3001 - StrictHostKeyChecking no + HostKeyAlias bigdog-vm1 Host bigdog-vm2 Hostname 8.8.197.72 Port 2226 - StrictHostKeyChecking no + HostKeyAlias bigdog-vm2 Host snake HostName snake.cs.uni-duesseldorf.de From david at codespeak.net Thu May 7 15:20:15 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 7 May 2009 15:20:15 +0200 (CEST) Subject: [pypy-svn] r65136 - pypy/branch/io-lang/pypy/lang/io Message-ID: <20090507132015.CA2EF169E37@codespeak.net> Author: david Date: Thu May 7 15:20:15 2009 New Revision: 65136 Modified: pypy/branch/io-lang/pypy/lang/io/list.py pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/register.py Log: (cfbolz, david) unwrap spec for object and list methods Modified: pypy/branch/io-lang/pypy/lang/io/list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/list.py Thu May 7 15:20:15 2009 @@ -7,9 +7,6 @@ w_target.append(w_items) return w_target - at register_method('List', 'at') -def list_at(space, w_target, w_message, w_context): - assert len(w_message.arguments) > 0 - w_item = w_message.arguments[0].eval(space, w_target, w_context) - assert isinstance(w_item, W_Number) - return w_target[w_item.value] \ No newline at end of file + at register_method('List', 'at', unwrap_spec=[object, int]) +def list_at(space, target, argument): + return target[argument] \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Thu May 7 15:20:15 2009 @@ -1,20 +1,15 @@ from pypy.lang.io.register import register_method from pypy.lang.io.model import W_ImmutableSequence, W_Block - at register_method('Object', 'setSlot') -def w_object_set_slot(space, w_target, w_message, w_context): - w_name = w_message.arguments[0].eval(space, w_context, w_context) - w_value = w_message.arguments[1].eval(space, w_context, w_context) - assert isinstance(w_name, W_ImmutableSequence) - w_target.slots[w_name.value] = w_value + at register_method('Object', 'setSlot', unwrap_spec=[object, str, object]) +def w_object_set_slot(space, w_target, name, w_value): + w_target.slots[name] = w_value return w_value - at register_method('Object', 'getSlot') -def w_object_get_slot(space, w_target, w_message, w_context): - w_name = w_message.arguments[0].eval(space, w_context, w_context) - assert isinstance(w_name, W_ImmutableSequence) + at register_method('Object', 'getSlot', unwrap_spec=[object, str]) +def w_object_get_slot(space, w_target, name): try: - return w_target.slots[w_name.value] + return w_target.slots[name] except KeyError: return space.w_nil @@ -32,9 +27,8 @@ names = [x.name for x in w_arguments] return space.w_block.clone_and_init(space, names, w_body, False) - at register_method('Object', 'clone') -def w_object_clone(space, w_target, w_message, w_context): - assert w_message.name == 'clone' + at register_method('Object', 'clone', unwrap_spec=[object]) +def w_object_clone(space, w_target): return w_target.clone() @register_method('Object', 'list') Modified: pypy/branch/io-lang/pypy/lang/io/register.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/register.py (original) +++ pypy/branch/io-lang/pypy/lang/io/register.py Thu May 7 15:20:15 2009 @@ -17,9 +17,15 @@ if typ is float: assert isinstance(x, model.W_Number) args += (x.value, ) + elif typ is int: + assert isinstance(x, model.W_Number) + args += (int(x.value), ) elif typ is object: args += (x, ) + elif typ is str: + args += (x.value, ) else: + raise ValueError, 'Unknown unwrap spec' return function(space, *args) subdict = cfunction_definitions.setdefault(type_name, {}) From david at codespeak.net Thu May 7 15:49:48 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 7 May 2009 15:49:48 +0200 (CEST) Subject: [pypy-svn] r65137 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090507134948.241311684C8@codespeak.net> Author: david Date: Thu May 7 15:49:47 2009 New Revision: 65137 Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/test/test_model.py Log: (cfbolz, david) loop detection in lookup Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Thu May 7 15:49:47 2009 @@ -12,13 +12,20 @@ def __ne__(self, other): return not self == other - def lookup(self, name): + def lookup(self, name, seen=None): + if seen is None: + seen = {} + else: + if self in seen: + return None + seen[self] = None + try: return self.slots[name] except KeyError: pass - for x in self.protos: - t = x.lookup(name) + for x in self.protos: + t = x.lookup(name, seen) if t is not None: return t Modified: pypy/branch/io-lang/pypy/lang/io/test/test_model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_model.py Thu May 7 15:49:47 2009 @@ -38,4 +38,27 @@ x = W_Number(space, 2) xx = x.clone() assert xx.protos == [x] - assert isinstance(xx, W_Number) \ No newline at end of file + assert isinstance(xx, W_Number) + +def test_lookup_cycles(): + obj = W_Object(None, ) + obj.protos.append(obj) + a = obj.slots['not_fail'] = W_Object(None) + assert obj.lookup("not_fail") is a + assert obj.lookup('fail') is None + +def test_lookup_cycling_complex(): + space = ObjSpace() + a = W_Object(None, ) + b = W_Object(None, ) + c = W_Object(None, ) + a.protos += [a, c] + c.protos += [b] + b.protos += [b] + a.slots['a'] = W_Number(space, 1) + b.slots['b'] = W_Number(space, 2) + c.slots['c'] = W_Number(space, 3) + assert a.lookup('fail') is None + assert a.lookup('a').value == 1 + assert a.lookup('b').value == 2 + assert a.lookup('c').value == 3 \ No newline at end of file From david at codespeak.net Thu May 7 16:04:40 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 7 May 2009 16:04:40 +0200 (CEST) Subject: [pypy-svn] r65138 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090507140440.DE2B016856B@codespeak.net> Author: david Date: Thu May 7 16:04:40 2009 New Revision: 65138 Modified: pypy/branch/io-lang/pypy/lang/io/objspace.py pypy/branch/io-lang/pypy/lang/io/test/test_model.py Log: (cfbolz, david) made the object model more like the real io object model (e.g. cyclic) Modified: pypy/branch/io-lang/pypy/lang/io/objspace.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/objspace.py (original) +++ pypy/branch/io-lang/pypy/lang/io/objspace.py Thu May 7 16:04:40 2009 @@ -10,7 +10,8 @@ class ObjSpace(object): """docstring for ObjSpace""" def __init__(self): - self.init_w_object() + self.w_object = W_Object(self) + self.w_lobby = W_Object(self) self.w_protos = W_Object(self) self.w_core = W_Object(self) @@ -21,11 +22,9 @@ self.w_block = W_Block(self, [], W_Message(self, 'nil', []), False, [self.w_object]) self.w_list = W_List(self, [self.w_object]) + self.init_w_object() - self.w_core.protos.append(self.w_object) - - self.w_protos.protos.append(self.w_core) - self.w_protos.slots['Core'] = self.w_core + self.init_w_protos() self.init_w_list() @@ -37,6 +36,11 @@ self.init_w_core() + + def init_w_protos(self): + self.w_protos.protos.append(self.w_core) + self.w_protos.slots['Core'] = self.w_core + def init_w_block(self): for key, function in cfunction_definitions['Block'].items(): self.w_block.slots[key] = W_CFunction(self, function) @@ -46,6 +50,7 @@ self.w_list.slots[key] = W_CFunction(self, function) def init_w_core(self): + self.w_core.protos.append(self.w_object) self.w_core.slots['Locals'] = self.w_locals self.w_core.slots['Block'] = self.w_block self.w_core.slots['Object'] = self.w_object @@ -64,10 +69,12 @@ def init_w_lobby(self): self.w_lobby.protos.append(self.w_protos) + self.w_object.protos.append(self.w_lobby) self.w_lobby.slots['Lobby'] = self.w_lobby self.w_lobby.slots['Protos'] = self.w_protos def init_w_object(self): - self.w_object = W_Object(self) + + for key, function in cfunction_definitions['Object'].items(): self.w_object.slots[key] = W_CFunction(self, function) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_model.py Thu May 7 16:04:40 2009 @@ -61,4 +61,8 @@ assert a.lookup('fail') is None assert a.lookup('a').value == 1 assert a.lookup('b').value == 2 - assert a.lookup('c').value == 3 \ No newline at end of file + assert a.lookup('c').value == 3 + +def test_lookup_cycle_builtins(): + space = ObjSpace() + assert space.w_object.lookup('Lobby') is space.w_lobby \ No newline at end of file From antocuni at codespeak.net Thu May 7 18:39:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 18:39:08 +0200 (CEST) Subject: [pypy-svn] r65142 - in pypy/extradoc/talk/pycon-italy-2009: . status Message-ID: <20090507163908.143DA16853E@codespeak.net> Author: antocuni Date: Thu May 7 18:39:07 2009 New Revision: 65142 Added: pypy/extradoc/talk/pycon-italy-2009/ pypy/extradoc/talk/pycon-italy-2009/status/ - copied from r65139, pypy/extradoc/talk/pycon2009/status/ pypy/extradoc/talk/pycon-italy-2009/status/logo_disi.png (contents, props changed) Modified: pypy/extradoc/talk/pycon-italy-2009/status/author.latex pypy/extradoc/talk/pycon-italy-2009/status/status.pdf pypy/extradoc/talk/pycon-italy-2009/status/status.txt pypy/extradoc/talk/pycon-italy-2009/status/title.latex Log: first version of my talk at pycon italy, mostly stolen from pycon2009 status talk Modified: pypy/extradoc/talk/pycon-italy-2009/status/author.latex ============================================================================== --- pypy/extradoc/talk/pycon2009/status/author.latex (original) +++ pypy/extradoc/talk/pycon-italy-2009/status/author.latex Thu May 7 18:39:07 2009 @@ -1,8 +1,7 @@ \definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} -\title[PyPy status talk]{PyPy status talk} -\author[H. Krekel, M. Fijalkowski]{Holger Krekel \and Maciej Fijalkowski\\ -Merlinux GmbH} +\title[PyPy 1.1]{PyPy 1.1 - Present and Future} +\author[Antonio Cuni]{Antonio Cuni\\DISI - Universit? di Genova\\Merlinux GmbH} -\institute[PyCon 2009]{PyCon 2009 - Rosemont} -\date{March 28 2009} +\institute[PyCon Tre]{PyCon Tre 2009 - Firenze} +\date{May 9 2009} Added: pypy/extradoc/talk/pycon-italy-2009/status/logo_disi.png ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon-italy-2009/status/status.txt Thu May 7 18:39:07 2009 @@ -7,11 +7,13 @@ * Why we work on PyPy? +* Details about recent 1.1 release + * What you can run on top of PyPy * How fast is PyPy? -* Details about coming 1.1 release +* Sandboxing * Questions and Answers @@ -35,6 +37,8 @@ * Psyco and Stackless Python hard to maintain +* PyPy: flexible and easy to experiment with + PyPy: generating Python Interpreter ===================================== @@ -61,7 +65,30 @@ * 2007-now - open source project -* some google sponsoring +* some Google sponsoring (thanks Guido :-)) + + +1.1 release +=================================== + +- more than two years of work + +- compatible to Python 2.5.2 + +- well tested on win/linux 32 bit + +- speed improvements over 1.0 + +- running major packages unmodified + +- easy_install/distutils working + +- help e.g. by writing ctypes modules + +- sandboxing + +- support for Maemo devices + Getting Production ready ========================== @@ -89,7 +116,7 @@ * contribution to original ctypes (better errno handling, bugfixes, tests...) -* part of google sponsoring +* part of Google sponsoring * note: a bit slow @@ -180,25 +207,40 @@ Conclusion on Compatibility ============================ -* lessons learned: There is no feature obscure enough for people - not to rely on it. +* lessons learned: *there is no feature obscure enough for people + not to rely on it.* * pypy-c interpreter probably the most compatible to CPython 2.5 * main blocker for running apps will be missing external modules + - greatest way to enter PyPy :-) + Speed - comparison with CPython =============================== * we're something between 0.8-4x slower than CPython on various benchmarks without JIT -* our JIT is a huge leap ahead +* our JIT will be super-fast (hopefully :-)) * pypy-c has fastest Interpreter startup -Speed - JIT generator -===================== +Speed - JIT generator (1) +========================== + +* not included in 1.1 + +* big refactoring in-progress + +* 5th generation ("... and easy to experiment with") + +* x86 and CLI/.NET backends + +* very easy to port to x86-64 (contributions welcome!) + +Speed - JIT generator (2) +========================== * 20-30x faster on small examples @@ -207,10 +249,24 @@ * a bit of time needed to speed up large python programs -* probably won't make it to 1.1 - * completely separated from the interpreter +* current plan: make it correct, make it fast + +Speed - JIT for CLI/.NET +========================= + +* Originally written for the 2nd JIT generation + +* Can compile small dynamic languages - not full PyPy yet + +* Same speed as C# in numeric benchmarks + +* Up to 40% **faster** than C# for some OO benchmarks + +* Porting to 5th generation in-progress + + Memory - comparison with CPython =================================== @@ -234,9 +290,7 @@ Other backends ============== -* PyPy-CLI runs! Still needs a bit more integration with .NET - -* PyPy-JVM runs, little integration so far +* pypy-cli, pypy-jvm * general speed improvements @@ -247,7 +301,7 @@ pypy-c on small devices =============================== -- cross-compilation +- cross-compilation - startup time @@ -259,25 +313,11 @@ - pypy approach a very good fit! -1.1 release -=================================== - -- compatible to Python 2.5.2 - -- well tested on win/linux 32 bit - -- running major packages unmodified - -- easy_install/distutils working - -- help e.g. by writing ctypes modules - -- hopefully released next month Contact / Q&A ========================== -holger krekel, Maciej Fijalkowski +Antonio Cuni at http://merlinux.eu PyPy: http://codespeak.net/pypy @@ -286,8 +326,10 @@ .. raw:: latex - \begin{figure} - \includegraphics[width=64px,height=64px]{merlinux-logo.jpg} + \begin{figure}[h] + \scalebox{0.8}{\includegraphics[width=80px]{../../img/py-web.png}} + \qquad + \scalebox{0.8}{\includegraphics[width=126px,height=37px]{logo_disi.png}} \qquad - \includegraphics[width=80px]{../../img/py-web.png} + \scalebox{0.8}{\includegraphics[width=64px,height=64px]{merlinux-logo.jpg}} \end{figure} Modified: pypy/extradoc/talk/pycon-italy-2009/status/title.latex ============================================================================== --- pypy/extradoc/talk/pycon2009/status/title.latex (original) +++ pypy/extradoc/talk/pycon-italy-2009/status/title.latex Thu May 7 18:39:07 2009 @@ -1,7 +1,9 @@ \begin{titlepage} \begin{figure}[h] -\includegraphics[width=64px,height=64px]{merlinux-logo.jpg} +\scalebox{0.8}{\includegraphics[width=80px]{../../img/py-web.png}} \qquad -\includegraphics[width=80px]{../../img/py-web.png} +\scalebox{0.8}{\includegraphics[width=126px,height=37px]{logo_disi.png}} +\qquad +\scalebox{0.8}{\includegraphics[width=64px,height=64px]{merlinux-logo.jpg}} \end{figure} \end{titlepage} From fijal at codespeak.net Thu May 7 19:37:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 7 May 2009 19:37:49 +0200 (CEST) Subject: [pypy-svn] r65144 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090507173749.EFDB316855C@codespeak.net> Author: fijal Date: Thu May 7 19:37:47 2009 New Revision: 65144 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: If we use the result of GUARD_EXCEPTION(OverflowError), explode 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 Thu May 7 19:37:47 2009 @@ -16,6 +16,13 @@ REGS = [eax, ecx, edx] WORD = 4 +class ImplementConstantOverflow(Exception): + """ This exception is raised when someone uses the result + of GUARD_EXCEPTION(overflowerror). I think codewriter should + constant fold it as we know what kind of exception it will + be + """ + class TempBox(Box): def __init__(self): pass @@ -281,9 +288,10 @@ if not canfold: # detect overflow ops if op.is_ovf(): - num = operations[i + 1].opnum - assert (num == rop.GUARD_NO_EXCEPTION or - num == rop.GUARD_EXCEPTION) + assert operations[i + 1].is_guard_exception() + if (operations[i + 1].opnum == rop.GUARD_EXCEPTION and + operations[i + 1].result in self.longevity): + raise ImplementConstantOverflow() nothing = oplist[op.opnum](self, op, operations[i + 1]) i += 1 elif self.can_optimize_cmp_op(op, i, operations): From jandem at codespeak.net Thu May 7 20:18:52 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Thu, 7 May 2009 20:18:52 +0200 (CEST) Subject: [pypy-svn] r65145 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090507181852.37E49168512@codespeak.net> Author: jandem Date: Thu May 7 20:18:51 2009 New Revision: 65145 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: fix ObjectObjects tests (one failure because Date is not implemented) and some FunctionObjects tests Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Thu May 7 20:18:51 2009 @@ -243,6 +243,7 @@ return W_String("[object %s]"%this.Class) class W_ValueOf(W_NewBuiltin): + length = 0 def Call(self, ctx, args=[], this=None): return this @@ -583,16 +584,19 @@ w_Function = W_Function(ctx, Class='Function', Prototype=w_ObjPrototype) + w_FncPrototype = W_Function(ctx, Class='Function', Prototype=w_ObjPrototype)#W_Object(Prototype=None, Class='Function') + w_Function.Put(ctx, 'length', W_IntNumber(1), flags = allon) w_Global.Put(ctx, 'Function', w_Function) - w_Object = W_ObjectObject('Object', w_Function) + w_Object = W_ObjectObject('Object', w_FncPrototype) w_Object.Put(ctx, 'prototype', w_ObjPrototype, flags = allon) - w_Object.Put(ctx, 'length', W_IntNumber(1), flags = RO | DD) - w_Global.Put(ctx, 'Object', w_Object) + w_Object.Put(ctx, 'length', W_IntNumber(1), flags = allon) w_Global.Prototype = w_ObjPrototype - w_FncPrototype = w_Function.Call(ctx, this=w_Function) + w_Object.Put(ctx, 'prototype', w_ObjPrototype, flags = allon) + w_Global.Put(ctx, 'Object', w_Object) + w_Function.Put(ctx, 'prototype', w_FncPrototype, flags = allon) w_Function.Put(ctx, 'constructor', w_Function, flags=allon) @@ -600,7 +604,7 @@ put_values(ctx, w_ObjPrototype, { 'constructor': w_Object, - '__proto__': w_FncPrototype, + '__proto__': w_Null, 'toString': toString, 'toLocaleString': toString, 'valueOf': W_ValueOf(ctx), @@ -617,6 +621,7 @@ 'apply': W_Apply(ctx), 'call': W_Call(ctx), 'arguments': w_Null, + 'valueOf': W_ValueOf(ctx), }) w_Boolean = W_BooleanObject('Boolean', w_FncPrototype) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Thu May 7 20:18:51 2009 @@ -27,19 +27,19 @@ try: while i < len(opcodes): opcode = opcodes[i] - if we_are_translated(): - #this is an optimization strategy for translated code - #on top of cpython it destroys the performance - #besides, this code might be completely wrong - for name, op in opcode_unrolling: - opcode = hint(opcode, deepfreeze=True) - if isinstance(opcode, op): - result = opcode.eval(ctx, stack) - assert result is None - break - else: - result = opcode.eval(ctx, stack) - assert result is None + #if we_are_translated(): + # #this is an optimization strategy for translated code + # #on top of cpython it destroys the performance + # #besides, this code might be completely wrong + # for name, op in opcode_unrolling: + # opcode = hint(opcode, deepfreeze=True) + # if isinstance(opcode, op): + # result = opcode.eval(ctx, stack) + # assert result is None + # break + #else: + result = opcode.eval(ctx, stack) + assert result is None if isinstance(opcode, BaseJump): i = opcode.do_jump(stack, i) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Thu May 7 20:18:51 2009 @@ -669,6 +669,7 @@ proto = ctx.get_global().Get(ctx, prototypename).Get(ctx, 'prototype') obj = W_Object(ctx, callfunc = callfunc,Prototype=proto, Class = proto.Class, Value = Value) + obj.Put(ctx, '__proto__', proto, DE|DD|RO) return obj def isnull_or_undefined(obj): From benjamin at codespeak.net Thu May 7 21:06:53 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 7 May 2009 21:06:53 +0200 (CEST) Subject: [pypy-svn] r65146 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090507190653.09F1A169E00@codespeak.net> Author: benjamin Date: Thu May 7 21:06:50 2009 New Revision: 65146 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: add NEWSTR and NEWUNICODE Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Thu May 7 21:06:50 2009 @@ -1,5 +1,5 @@ import py -from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rffi, rstr from pypy.jit.backend.test import test_random from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import ConstInt, ConstPtr, ConstAddr, BoxPtr,\ @@ -282,6 +282,18 @@ descr = self.array_descr(builder, A) self.put(builder, [v], descr) +class NewSeqOperation(test_random.AbstractOperation): + def produce_into(self, builder, r): + v_length = r.choice(builder.intvars) + if not (0 <= v_length.value < 500): + v_length = ConstInt((r.random_integer() // 5) % 500) + v_ptr = builder.do(self.opnum, [v_length]) + if self.opnum == rop.NEWSTR: + seq_type = lltype.Ptr(rstr.STR) + else: + seq_type = lltype.Ptr(rstr.UNICODE) + builder.ptrvars.append((v_ptr, seq_type)) + # there are five options in total: # 1. non raising call and guard_no_exception # 2. raising call and guard_exception @@ -450,6 +462,8 @@ OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC)) OPERATIONS.append(NewArrayOperation(rop.NEW_ARRAY)) OPERATIONS.append(ArrayLenOperation(rop.ARRAYLEN_GC)) + OPERATIONS.append(NewSeqOperation(rop.NEWSTR)) + OPERATIONS.append(NewSeqOperation(rop.NEWUNICODE)) for i in range(2): OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) From arigo at codespeak.net Thu May 7 21:54:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 21:54:27 +0200 (CEST) Subject: [pypy-svn] r65147 - in pypy/trunk/pypy/rpython: . test Message-ID: <20090507195427.B75CF168581@codespeak.net> Author: arigo Date: Thu May 7 21:54:26 2009 New Revision: 65147 Modified: pypy/trunk/pypy/rpython/normalizecalls.py pypy/trunk/pypy/rpython/test/test_normalizecalls.py Log: TotalOrderSymbolics can be compared with regular integers, by forcing their computation. I think it should be fine to force their computation in this case -- the alternative is to raise TypeError("don't do that"). Modified: pypy/trunk/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/trunk/pypy/rpython/normalizecalls.py (original) +++ pypy/trunk/pypy/rpython/normalizecalls.py Thu May 7 21:54:26 2009 @@ -283,7 +283,7 @@ def __cmp__(self, other): if not isinstance(other, TotalOrderSymbolic): - return NotImplemented + return cmp(self.compute_fn(), other) else: return cmp(self.orderwitness, other.orderwitness) Modified: pypy/trunk/pypy/rpython/test/test_normalizecalls.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_normalizecalls.py (original) +++ pypy/trunk/pypy/rpython/test/test_normalizecalls.py Thu May 7 21:54:26 2009 @@ -1,10 +1,24 @@ +import py from pypy.annotation import model as annmodel from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem import lltype +from pypy.rpython.normalizecalls import TotalOrderSymbolic, MAX +def test_TotalOrderSymbolic(): + lst = [] + t1 = TotalOrderSymbolic([3, 4], lst) + t2 = TotalOrderSymbolic([3, 4, 2], lst) + t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst) + t4 = TotalOrderSymbolic([3, 4, MAX], lst) + assert t1 < t2 < t3 < t4 + assert t1.value is t2.value is t3.value is t4.value is None + assert 1 <= t3 + assert t3.value == 2 + assert t1 <= 5 + assert t1.value == 0 # ____________________________________________________________ From arigo at codespeak.net Thu May 7 22:04:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 22:04:37 +0200 (CEST) Subject: [pypy-svn] r65148 - in pypy/branch/pyjitpl5/pypy/rpython: . test Message-ID: <20090507200437.9B95C16856F@codespeak.net> Author: arigo Date: Thu May 7 22:04:37 2009 New Revision: 65148 Modified: pypy/branch/pyjitpl5/pypy/rpython/normalizecalls.py pypy/branch/pyjitpl5/pypy/rpython/test/test_normalizecalls.py Log: Merge r65147 from the trunk (it was intended for the branch, sorry) Modified: pypy/branch/pyjitpl5/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/normalizecalls.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/normalizecalls.py Thu May 7 22:04:37 2009 @@ -283,7 +283,7 @@ def __cmp__(self, other): if not isinstance(other, TotalOrderSymbolic): - return NotImplemented + return cmp(self.compute_fn(), other) else: return cmp(self.orderwitness, other.orderwitness) Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_normalizecalls.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_normalizecalls.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_normalizecalls.py Thu May 7 22:04:37 2009 @@ -1,10 +1,24 @@ +import py from pypy.annotation import model as annmodel from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem import lltype +from pypy.rpython.normalizecalls import TotalOrderSymbolic, MAX +def test_TotalOrderSymbolic(): + lst = [] + t1 = TotalOrderSymbolic([3, 4], lst) + t2 = TotalOrderSymbolic([3, 4, 2], lst) + t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst) + t4 = TotalOrderSymbolic([3, 4, MAX], lst) + assert t1 < t2 < t3 < t4 + assert t1.value is t2.value is t3.value is t4.value is None + assert 1 <= t3 + assert t3.value == 2 + assert t1 <= 5 + assert t1.value == 0 # ____________________________________________________________ From arigo at codespeak.net Thu May 7 22:22:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 22:22:41 +0200 (CEST) Subject: [pypy-svn] r65149 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090507202241.A3006169DB4@codespeak.net> Author: arigo Date: Thu May 7 22:22:37 2009 New Revision: 65149 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: Try to preserve the exception across a ctypes call. Currently only works for calls done via invoke_via_ctypes(). 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 Thu May 7 22:22:37 2009 @@ -484,6 +484,7 @@ _all_callbacks = {} _all_callbacks_results = [] _callback2obj = {} +_callback_exc_info = None # this is just another hack that passes around references to applevel types # disguised as base_ptr_lltype @@ -548,7 +549,7 @@ 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): + def callback_internal(*cargs): cargs = list(cargs) for v1 in v1voidlist: cargs.insert(v1[0], v1[1]) @@ -568,9 +569,9 @@ except LLException, lle: llinterp._store_exception(lle) return 0 - except: - import pdb - pdb.set_trace() + #except: + # import pdb + # pdb.set_trace() else: try: llres = container._callable(*llargs) @@ -589,14 +590,16 @@ return 0 return res - 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 + def callback(*cargs): + try: + return callback_internal(*cargs) + except: + import sys + #if conftest.option.usepdb: + # import pdb; pdb.post_mortem(sys.exc_traceback) + global _callback_exc_info + _callback_exc_info = sys.exc_info() + raise if isinstance(T.TO.RESULT, lltype.Ptr): TMod = lltype.Ptr(lltype.FuncType(T.TO.ARGS, @@ -911,6 +914,7 @@ if FUNCTYPE.ARGS[i] is lltype.Void: void_arguments.append(i) def invoke_via_ctypes(*argvalues): + global _callback_exc_info cargs = [] for i in range(len(FUNCTYPE.ARGS)): if i not in void_arguments: @@ -918,9 +922,14 @@ if i in container_arguments: cvalue = cvalue.contents cargs.append(cvalue) + _callback_exc_info = None _restore_c_errno() cres = cfunc(*cargs) _save_c_errno() + if _callback_exc_info: + etype, evalue, etb = _callback_exc_info + _callback_exc_info = None + raise etype, evalue, etb return ctypes2lltype(RESULT, cres) return invoke_via_ctypes From arigo at codespeak.net Thu May 7 22:25:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 22:25:03 +0200 (CEST) Subject: [pypy-svn] r65150 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090507202503.25123169DB4@codespeak.net> Author: arigo Date: Thu May 7 22:25:01 2009 New Revision: 65150 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: Fix for the case ctypes2lltype(lltype.Bool, 1). 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 Thu May 7 22:25:01 2009 @@ -733,6 +733,9 @@ llobj = unichr(cobj) elif T is lltype.Signed: llobj = cobj + elif T is lltype.Bool: + assert cobj == True or cobj == False # 0 and 1 work too + llobj = bool(cobj) elif T is lltype.SingleFloat: if isinstance(cobj, ctypes.c_float): cobj = cobj.value From arigo at codespeak.net Thu May 7 22:25:43 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 22:25:43 +0200 (CEST) Subject: [pypy-svn] r65151 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test Message-ID: <20090507202543.B7BA9169DB4@codespeak.net> Author: arigo Date: Thu May 7 22:25:43 2009 New Revision: 65151 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Added a test. 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 Thu May 7 22:25:43 2009 @@ -42,6 +42,8 @@ assert lltype2ctypes(rffi.r_ulong(-1)) == sys.maxint * 2 + 1 res = ctypes2lltype(lltype.Unsigned, sys.maxint * 2 + 1) assert (res, type(res)) == (rffi.r_ulong(-1), rffi.r_ulong) + assert ctypes2lltype(lltype.Bool, 0) is False + assert ctypes2lltype(lltype.Bool, 1) is True res = lltype2ctypes(llmemory.sizeof(lltype.Signed)) assert res == struct.calcsize("l") From arigo at codespeak.net Thu May 7 22:27:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 May 2009 22:27:11 +0200 (CEST) Subject: [pypy-svn] r65152 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090507202711.242B3169DB4@codespeak.net> Author: arigo Date: Thu May 7 22:27:10 2009 New Revision: 65152 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py Log: Works well enough so far. I don't feel like fighting the next issue. 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 Thu May 7 22:27:10 2009 @@ -31,3 +31,8 @@ return n res = self.meta_interp(f, [31], specialize=False) assert res == -4 + + def test_r_dict(self): + # a Struct that belongs to the hash table is not seen as being + # included in the larger Array + py.test.skip("issue with ll2ctypes") From antocuni at codespeak.net Thu May 7 23:21:16 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 23:21:16 +0200 (CEST) Subject: [pypy-svn] r65153 - pypy/extradoc/talk/pycon-italy-2009/status Message-ID: <20090507212116.68F1B16854A@codespeak.net> Author: antocuni Date: Thu May 7 23:21:15 2009 New Revision: 65153 Added: pypy/extradoc/talk/pycon-italy-2009/status/sandbox1.png - copied unchanged from r65137, pypy/extradoc/talk/pycon2009/pypy-sandbox/sandbox1.png Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf pypy/extradoc/talk/pycon-italy-2009/status/status.txt Log: add sandbox slides Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon-italy-2009/status/status.txt Thu May 7 23:21:15 2009 @@ -256,15 +256,89 @@ Speed - JIT for CLI/.NET ========================= -* Originally written for the 2nd JIT generation +* originally written for the 2nd JIT generation -* Can compile small dynamic languages - not full PyPy yet +* can compile small dynamic languages - not full PyPy yet -* Same speed as C# in numeric benchmarks +* same speed as C# in numeric benchmarks -* Up to 40% **faster** than C# for some OO benchmarks +* up to 40% **faster** than C# for some OO benchmarks -* Porting to 5th generation in-progress +* porting to 5th generation in-progress + + +Sandboxing - Definition +========================= + +* ability to run untrusted Python code + +* no way to: + + - interfere with the calling application + + - access system resources (files, etc.) + + - make a DoS by memory exhaustion + + - make a DoS by using 100% CPU + + +Sandboxing - Approaches +========================= + +* bytecode/source verification + +* CPython source modification/monkey patching + +* platform-level security (GAE) + +* restrict python language to something harmless + (zope's restricted python) + + +Sandboxing - Problems +====================== + +* Patchy approach - "*we fix all places that might be + potentially dangerous*" + +* Tradeoffs - either usability suffer or security is + hard to control + +* "Nobody cracked it so far" approach is not + "security by design" + +Sandboxing - PyPy approach +============================ + +.. image:: sandbox1.png + :scale: 50 + :align: center + +* C API implemented by parent process + + - virtual file system + +* Memory limit + +* CPU time limit + + +How to use it today? +======================= + +* translate pypy with --sandbox (takes a while) + +* run using pypy_interact.py + +* demo + +* you win a beer if you break it :-) + +.. raw:: latex + + \small{\url{http://codespeak.net/pypy/dist/pypy/doc/sandbox.html}} + \small{\url{http://codespeak.net/svn/user/getxsick/django-sandbox/}} Memory - comparison with CPython From antocuni at codespeak.net Thu May 7 23:25:10 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 23:25:10 +0200 (CEST) Subject: [pypy-svn] r65154 - pypy/extradoc/talk/pycon-italy-2009/status Message-ID: <20090507212510.08A5F16856C@codespeak.net> Author: antocuni Date: Thu May 7 23:25:08 2009 New Revision: 65154 Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.txt Log: merge two stackless slides Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2009/status/status.txt (original) +++ pypy/extradoc/talk/pycon-italy-2009/status/status.txt Thu May 7 23:25:08 2009 @@ -166,15 +166,6 @@ * http://twistedmatrix.com/ -Stackless -========= - -* We support stackless - -* tasklets, frame pickling, greenlets - -* fully cross-platform - Other software ============== @@ -350,6 +341,8 @@ * PyPy has pluggable Garbage Collection + + Threading / Stackless =================================== @@ -359,6 +352,11 @@ * pypy-c has software threading / stackless + - tasklets, frame pickling, greenlets + + - fully cross-platform + + * no modifications to interpreter involved Other backends From antocuni at codespeak.net Thu May 7 23:27:11 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 May 2009 23:27:11 +0200 (CEST) Subject: [pypy-svn] r65155 - pypy/extradoc/talk/pycon-italy-2009/status Message-ID: <20090507212711.1E9C716856C@codespeak.net> Author: antocuni Date: Thu May 7 23:27:10 2009 New Revision: 65155 Added: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf.info Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf Log: add keyjnote info Modified: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf ============================================================================== Binary files. No diff available. Added: pypy/extradoc/talk/pycon-italy-2009/status/status.pdf.info ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon-italy-2009/status/status.pdf.info Thu May 7 23:27:10 2009 @@ -0,0 +1,11 @@ +AvailableTransitions=[Crossfade] +TransitionDuration = 100 +EstimatedDuration = 60*60 +MinutesOnly = True + +PageProps = { + 1: { + 'reset': FirstTimeOnly, + 'progress': False, + }, +} From benjamin at codespeak.net Fri May 8 00:40:00 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 8 May 2009 00:40:00 +0200 (CEST) Subject: [pypy-svn] r65156 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090507224000.778E5169DFE@codespeak.net> Author: benjamin Date: Fri May 8 00:39:59 2009 New Revision: 65156 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: add getting and setting str/unicode ops Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Fri May 8 00:39:59 2009 @@ -14,6 +14,8 @@ def __init__(self, *args, **kw): test_random.OperationBuilder.__init__(self, *args, **kw) self.vtable_counter = 0 + self.rstrs = [] + self.runicodes = [] self.structure_types = [] self.structure_types_and_vtables = [] @@ -124,6 +126,14 @@ p[i] = rffi.cast(A.OF, r.random_integer()) return p + def get_index(self, length, r): + if length == 0: + raise test_random.CannotProduceOperation + v_index = r.choice(self.intvars) + if not (0 <= v_index.value < length): + v_index = ConstInt(r.random_integer() % length) + return v_index + def field_values(self, p): dic = {} S = lltype.typeOf(p).TO @@ -237,12 +247,7 @@ def field_descr(self, builder, r): v, A = builder.get_arrayptr_var(r) array = v.getptr(lltype.Ptr(A)) - length = len(array) - if length == 0: - raise test_random.CannotProduceOperation - v_index = r.choice(builder.intvars) - if not (0 <= v_index.value < length): - v_index = ConstInt(r.random_integer() % length) + v_index = builder.get_index(len(array), r) descr = self.array_descr(builder, A) return v, A, v_index, descr @@ -270,9 +275,7 @@ class NewArrayOperation(ArrayOperation): def produce_into(self, builder, r): A = builder.get_random_array_type(r) - v_size = r.choice(builder.intvars) - if not (0 <= v_size.value < 300): - v_size = ConstInt((r.random_integer() // 15) % 300) + v_size = builder.get_index(300, r) v_ptr = builder.do(self.opnum, [v_size], self.array_descr(builder, A)) builder.ptrvars.append((v_ptr, A)) @@ -282,17 +285,83 @@ descr = self.array_descr(builder, A) self.put(builder, [v], descr) +class _UnicodeOperation: + builder_cache = "runicodes" + struct = rstr.UNICODE + ptr = lltype.Ptr(struct) + alloc = staticmethod(rstr.mallocunicode) + # XXX This should really be runicode.MAXUNICODE, but then + # lltype.cast_primitive complains. + max = py.std.sys.maxunicode + primitive = lltype.UniChar + set_char = rop.UNICODESETITEM + +class _StrOperation: + builder_cache = "rstrs" + struct = rstr.STR + ptr = lltype.Ptr(struct) + alloc = staticmethod(rstr.mallocstr) + max = 255 + primitive = lltype.Char + set_char = rop.STRSETITEM + class NewSeqOperation(test_random.AbstractOperation): def produce_into(self, builder, r): - v_length = r.choice(builder.intvars) - if not (0 <= v_length.value < 500): - v_length = ConstInt((r.random_integer() // 5) % 500) + v_length = builder.get_index(10, r) v_ptr = builder.do(self.opnum, [v_length]) - if self.opnum == rop.NEWSTR: - seq_type = lltype.Ptr(rstr.STR) + getattr(builder, self.builder_cache).append(v_ptr) + # Initialize the string. Is there a better way to do this? + for i in range(v_length.getint()): + v_index = ConstInt(i) + v_char = ConstInt(r.random_integer() % self.max) + builder.do(self.set_char, [v_ptr, v_index, v_char]) + +class NewStrOperation(NewSeqOperation, _StrOperation): + pass + +class NewUnicodeOperation(NewSeqOperation, _UnicodeOperation): + pass + +class AbstractStringOperation(test_random.AbstractOperation): + def get_string(self, builder, r): + current = getattr(builder, self.builder_cache) + if current and r.random() < .8: + v_string = r.choice(current) + string = v_string.getptr(self.ptr) else: - seq_type = lltype.Ptr(rstr.UNICODE) - builder.ptrvars.append((v_ptr, seq_type)) + string = self.alloc(builder.get_index(500, r).getint()) + v_string = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, string)) + current.append(v_string) + for i in range(len(string.chars)): + char = r.random_integer() % self.max + string.chars[i] = lltype.cast_primitive(self.primitive, char) + return v_string + +class AbstractGetItemOperation(AbstractStringOperation): + def produce_into(self, builder, r): + v_string = self.get_string(builder, r) + v_index = builder.get_index(len(v_string.getptr(self.ptr).chars), r) + v_result = builder.do(self.opnum, [v_string, v_index]) + +class AbstractSetItemOperation(AbstractStringOperation): + def produce_into(self, builder, r): + v_string = self.get_string(builder, r) + v_index = builder.get_index(len(v_string.getptr(self.ptr).chars), r) + v_target = ConstInt(r.random_integer() % self.max) + builder.do(self.opnum, [v_string, v_index, v_target]) + +class StrGetItemOperation(AbstractGetItemOperation, _StrOperation): + pass + +class UnicodeGetItemOperation(AbstractGetItemOperation, _UnicodeOperation): + pass + +class StrSetItemOperation(AbstractSetItemOperation, _StrOperation): + pass + +class UnicodeSetItemOperation(AbstractSetItemOperation, _UnicodeOperation): + pass + # there are five options in total: # 1. non raising call and guard_no_exception @@ -462,8 +531,12 @@ OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC)) OPERATIONS.append(NewArrayOperation(rop.NEW_ARRAY)) OPERATIONS.append(ArrayLenOperation(rop.ARRAYLEN_GC)) - OPERATIONS.append(NewSeqOperation(rop.NEWSTR)) - OPERATIONS.append(NewSeqOperation(rop.NEWUNICODE)) + OPERATIONS.append(NewStrOperation(rop.NEWSTR)) + OPERATIONS.append(NewUnicodeOperation(rop.NEWUNICODE)) + OPERATIONS.append(StrGetItemOperation(rop.STRGETITEM)) + OPERATIONS.append(UnicodeGetItemOperation(rop.UNICODEGETITEM)) + OPERATIONS.append(StrSetItemOperation(rop.STRSETITEM)) + OPERATIONS.append(UnicodeSetItemOperation(rop.UNICODESETITEM)) for i in range(2): OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) From benjamin at codespeak.net Fri May 8 00:46:52 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Fri, 8 May 2009 00:46:52 +0200 (CEST) Subject: [pypy-svn] r65157 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090507224652.771FB169E1B@codespeak.net> Author: benjamin Date: Fri May 8 00:46:50 2009 New Revision: 65157 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Log: add string length operations Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_ll_random.py Fri May 8 00:46:50 2009 @@ -350,6 +350,11 @@ v_target = ConstInt(r.random_integer() % self.max) builder.do(self.opnum, [v_string, v_index, v_target]) +class AbstractStringLenOperation(AbstractStringOperation): + def produce_into(self, builder, r): + v_string = self.get_string(builder, r) + builder.do(self.opnum, [v_string]) + class StrGetItemOperation(AbstractGetItemOperation, _StrOperation): pass @@ -362,6 +367,12 @@ class UnicodeSetItemOperation(AbstractSetItemOperation, _UnicodeOperation): pass +class StrLenOperation(AbstractStringLenOperation, _StrOperation): + pass + +class UnicodeLenOperation(AbstractStringLenOperation, _UnicodeOperation): + pass + # there are five options in total: # 1. non raising call and guard_no_exception @@ -537,6 +548,8 @@ OPERATIONS.append(UnicodeGetItemOperation(rop.UNICODEGETITEM)) OPERATIONS.append(StrSetItemOperation(rop.STRSETITEM)) OPERATIONS.append(UnicodeSetItemOperation(rop.UNICODESETITEM)) + OPERATIONS.append(StrLenOperation(rop.STRLEN)) + OPERATIONS.append(UnicodeLenOperation(rop.UNICODELEN)) for i in range(2): OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS)) From arigo at codespeak.net Fri May 8 14:33:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 14:33:00 +0200 (CEST) Subject: [pypy-svn] r65161 - in pypy/branch/pyjitpl5/pypy/jit/backend: test x86 Message-ID: <20090508123300.A0B92168547@codespeak.net> Author: arigo Date: Fri May 8 14:32:58 2009 New Revision: 65161 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Test and fix: don't clear just the exception type, also clear the exception value! Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner_test.py Fri May 8 14:32:58 2009 @@ -187,6 +187,7 @@ else: self.cpu.set_overflow_error() ovferror = self.cpu.get_exception() + assert self.cpu.get_exc_value() self.cpu.clear_exception() if self.cpu.is_oo: v_exc = BoxObj() @@ -209,6 +210,7 @@ self.cpu.compile_operations(loop) for x, y, z in testcases: assert not self.cpu.get_exception() + assert not self.cpu.get_exc_value() self.cpu.set_future_value_int(0, x) self.cpu.set_future_value_int(1, y) op = self.cpu.execute_operations(loop) @@ -219,6 +221,7 @@ if z != boom: assert self.cpu.get_latest_value_int(0) == z ovferror = self.cpu.get_exception() + assert bool(ovferror) == bool(self.cpu.get_exc_value()) if reversed: # in the 'reversed' case, ovferror should always be # consumed: either it is not set in the first place, Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Fri May 8 14:32:58 2009 @@ -225,6 +225,7 @@ original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) exc = builder.cpu.get_exception() + assert bool(exc) == bool(builder.cpu.get_exc_value()) if exc: # OverflowError builder.cpu.clear_exception() exc_box = ConstInt(exc) @@ -452,6 +453,7 @@ cpu = self.builder.cpu self.clear_state() assert not cpu.get_exception() + assert not cpu.get_exc_value() for i, v in enumerate(self.values): cpu.set_future_value_int(i, v) @@ -466,9 +468,11 @@ ) if (self.guard_op is not None and self.guard_op.is_guard_exception()): + assert cpu.get_exc_value() cpu.clear_exception() else: assert not cpu.get_exception() + assert not cpu.get_exc_value() def build_bridge(self): def exc_handling(guard_op): 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 May 8 14:32:58 2009 @@ -861,6 +861,7 @@ # clean up the original exception, we don't want # to enter more rpython code with exc set self.mc.MOV(heap(self._exception_addr), imm(0)) + self.mc.MOV(addr_add(imm(self._exception_addr), imm(WORD)), imm(0)) @specialize.arg(3) def implement_guard(self, addr, guard_op, emit_jump): 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 Fri May 8 14:32:58 2009 @@ -196,6 +196,7 @@ def clear_exception(self): self.assembler.make_sure_mc_exists() self.assembler._exception_bck[0] = 0 + self.assembler._exception_bck[1] = 0 def set_overflow_error(self): self.assembler.make_sure_mc_exists() From arigo at codespeak.net Fri May 8 15:24:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 15:24:22 +0200 (CEST) Subject: [pypy-svn] r65164 - in pypy/branch/pyjitpl5/pypy/jit: backend/x86 metainterp Message-ID: <20090508132422.C3338168566@codespeak.net> Author: arigo Date: Fri May 8 15:24:19 2009 New Revision: 65164 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Another case in which only the exception type is cleared, not the exception value. 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 May 8 15:24:19 2009 @@ -772,6 +772,7 @@ if resloc is not None: self.mc.MOV(resloc, addr_add(imm(self._exception_addr), imm(WORD))) self.mc.MOV(heap(self._exception_addr), imm(0)) + self.mc.MOV(addr_add(imm(self._exception_addr), imm(WORD)), imm(0)) def genop_guard_guard_false(self, op, ign_1, addr, locs, ign_2): loc = locs[0] 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 May 8 15:24:19 2009 @@ -1338,6 +1338,7 @@ def handle_exception(self): etype = self.cpu.get_exception() evalue = self.cpu.get_exc_value() + assert bool(etype) == bool(evalue) self.cpu.clear_exception() frame = self.framestack[-1] if etype: From arigo at codespeak.net Fri May 8 15:45:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 15:45:13 +0200 (CEST) Subject: [pypy-svn] r65165 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090508134513.992D51684F5@codespeak.net> Author: arigo Date: Fri May 8 15:45:13 2009 New Revision: 65165 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: Skip tests clearly if PythonNet is not available. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Fri May 8 15:45:13 2009 @@ -4,6 +4,9 @@ class CliJitMixin(test_basic.OOJitMixin): CPUClass = CliCPU + def setup_class(cls): + from pypy.translator.cli.support import PythonNet + PythonNet.System # possibly raises Skip class TestBasic(CliJitMixin, test_basic.TestOOtype): # for the individual tests see From arigo at codespeak.net Fri May 8 16:17:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 16:17:22 +0200 (CEST) Subject: [pypy-svn] r65166 - in pypy/trunk/pypy/lib: . app_test Message-ID: <20090508141722.73D2C169E51@codespeak.net> Author: arigo Date: Fri May 8 16:17:21 2009 New Revision: 65166 Modified: pypy/trunk/pypy/lib/app_test/test_struct_extra.py pypy/trunk/pypy/lib/struct.py Log: Copy the updates done in rlib/ieee.py to the pure Python lib/struct.py, to handle NANs and infinity. Modified: pypy/trunk/pypy/lib/app_test/test_struct_extra.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/test_struct_extra.py (original) +++ pypy/trunk/pypy/lib/app_test/test_struct_extra.py Fri May 8 16:17:21 2009 @@ -8,3 +8,17 @@ s = 'ABCD01234567\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00' assert struct.unpack('<4s4H2lH', s) == ('ABCD', 0x3130, 0x3332, 0x3534, 0x3736, 1, 2, 3) + +def test_infinity(): + INFINITY = 1e200 * 1e200 + assert str(struct.unpack("!d", struct.pack("!d", INFINITY))[0]) \ + == str(INFINITY) + assert str(struct.unpack("!d", struct.pack("!d", -INFINITY))[0]) \ + == str(-INFINITY) + +def test_nan(): + INFINITY = 1e200 * 1e200 + NAN = INFINITY / INFINITY + assert str(struct.unpack("!d", '\xff\xf8\x00\x00\x00\x00\x00\x00')[0]) \ + == str(NAN) + assert str(struct.unpack("!d", struct.pack("!d", NAN))[0]) == str(NAN) Modified: pypy/trunk/pypy/lib/struct.py ============================================================================== --- pypy/trunk/pypy/lib/struct.py (original) +++ pypy/trunk/pypy/lib/struct.py Fri May 8 16:17:21 2009 @@ -63,6 +63,9 @@ number = int(-1*(max - number)) return number +INFINITY = 1e200 * 1e200 +NAN = INFINITY / INFINITY + def unpack_float(data,index,size,le): bytes = [ord(b) for b in data[index:index+size]] if len(bytes) != size: @@ -89,7 +92,13 @@ e -= bias e += 1 sign = bytes[-1] & 0x80 - number = math.ldexp(mantissa,e) + if e == bias + 2: + if mantissa == 0.5: + number = INFINITY + else: + return NAN + else: + number = math.ldexp(mantissa,e) if sign : number *= -1 return number @@ -125,19 +134,12 @@ def pack_char(char,size,le): return str(char) -def sane_float(man,e): - # TODO: XXX Implement checks for floats - return True +def isinf(x): + return x != 0.0 and x / 2 == x +def isnan(v): + return v != v*1.0 or (v == 1.0 and v == 2.0) def pack_float(number, size, le): - - if number < 0: - sign = 1 - number *= -1 - elif number == 0.0: - return "\x00" * size - else: - sign = 0 if size == 4: bias = 127 exp = 8 @@ -147,28 +149,44 @@ exp = 11 prec = 52 - man, e = math.frexp(number) + if isnan(number): + sign = 0x80 + man, e = 1.5, bias + 1 + else: + if number < 0: + sign = 0x80 + number *= -1 + elif number == 0.0: + return '\x00' * size + else: + sign = 0x00 + if isinf(number): + man, e = 1.0, bias + 1 + else: + man, e = math.frexp(number) + + result = [] if 0.5 <= man and man < 1.0: man *= 2 e -= 1 - if sane_float(man,e): - man -= 1 - e += bias - mantissa = int(2**prec *(man) +0.5) - res=[] - if mantissa >> prec : - mantissa = 0 - e += 1 - - for i in range(size-2): - res += [ mantissa & 0xff] - mantissa >>= 8 - res += [ (mantissa & (2**(15-exp)-1)) | ((e & (2**(exp-7)-1))<<(15-exp))] - res += [sign << 7 | e >> (exp - 7)] - if le == 'big': - res.reverse() - return ''.join([chr(x) for x in res]) - # TODO: What todo with insane floats/doubles. handle in sanefloat? + man -= 1 + e += bias + power_of_two = 1 << prec + mantissa = int(power_of_two * man + 0.5) + if mantissa >> prec : + mantissa = 0 + e += 1 + + for i in range(size-2): + result.append(chr(mantissa & 0xff)) + mantissa >>= 8 + x = (mantissa & ((1<<(15-exp))-1)) | ((e & ((1<<(exp-7))-1))<<(15-exp)) + result.append(chr(x)) + x = sign | e >> (exp - 7) + result.append(chr(x)) + if le == 'big': + result.reverse() + return ''.join(result) big_endian_format = { 'x':{ 'size' : 1, 'alignment' : 0, 'pack' : None, 'unpack' : None}, From jandem at codespeak.net Fri May 8 19:09:24 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Fri, 8 May 2009 19:09:24 +0200 (CEST) Subject: [pypy-svn] r65168 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090508170924.68CA2168503@codespeak.net> Author: jandem Date: Fri May 8 19:09:23 2009 New Revision: 65168 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Fix a regression in Number tests Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri May 8 19:09:23 2009 @@ -658,7 +658,7 @@ put_values(ctx, w_Number, { 'constructor': w_FncPrototype, 'prototype': w_NumPrototype, - '__proto__': w_empty_fun, + '__proto__': w_FncPrototype, 'length' : W_IntNumber(1), }) w_Number.propdict['prototype'].flags |= RO From jandem at codespeak.net Fri May 8 22:00:36 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Fri, 8 May 2009 22:00:36 +0200 (CEST) Subject: [pypy-svn] r65169 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090508200036.84949169E79@codespeak.net> Author: jandem Date: Fri May 8 22:00:33 2009 New Revision: 65169 Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: Fix float-to-string for large values, fixes some array tests Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri May 8 22:00:33 2009 @@ -1,6 +1,6 @@ # encoding: utf-8 from pypy.rlib.rarithmetic import r_uint, intmask, isnan, isinf,\ - ovfcheck_float_to_int, NAN + ovfcheck_float_to_int, NAN, formatd_overflow from pypy.lang.js.execution import ThrowException, JsTypeError,\ RangeError, ReturnException DE = 1 @@ -488,13 +488,9 @@ else: return '-Infinity' try: - intval = ovfcheck_float_to_int(self.floatval) - if intval == self.floatval: - return str(intval) + res = formatd_overflow('', 10, 'g', self.floatval) except OverflowError: - pass - - res = str(self.floatval) + raise if (res[-3] == '+' or res[-3] == '-') and res[-2] == '0': cut = len(res) - 2 assert cut >= 0 From arigo at codespeak.net Fri May 8 22:29:12 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 22:29:12 +0200 (CEST) Subject: [pypy-svn] r65170 - in pypy/branch/pyjitpl5/pypy: jit/metainterp rpython/lltypesystem Message-ID: <20090508202912.907A9168503@codespeak.net> Author: arigo Date: Fri May 8 22:29:09 2009 New Revision: 65170 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rffi.py Log: Argh. Complain loudly when we try to do anything with a LONGLONG. This was an obscure issue when translating pypy. 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 May 8 22:29:09 2009 @@ -1,6 +1,6 @@ from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.ootypesystem import ootype from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic from pypy.rlib.rarithmetic import intmask @@ -24,6 +24,9 @@ if TYPE is lltype.Void: return "void" elif isinstance(TYPE, lltype.Primitive): + # XXX fix this for oo... + if rffi.sizeof(TYPE) > rffi.sizeof(lltype.Signed): + raise NotImplementedError("type %s is too large" % TYPE) return "int" elif isinstance(TYPE, lltype.Ptr): if TYPE.TO._gckind == 'raw': Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rffi.py Fri May 8 22:29:09 2009 @@ -730,7 +730,7 @@ return size if isinstance(tp, lltype.Ptr): tp = ULONG # XXX! - if tp is lltype.Char: + if tp is lltype.Char or tp is lltype.Bool: return 1 if tp is lltype.UniChar: return r_wchar_t.BITS/8 From arigo at codespeak.net Fri May 8 22:38:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 22:38:30 +0200 (CEST) Subject: [pypy-svn] r65171 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090508203830.3E6C8169E3D@codespeak.net> Author: arigo Date: Fri May 8 22:38:29 2009 New Revision: 65171 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: Kill this function, not used any more. 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 May 8 22:38:29 2009 @@ -38,17 +38,6 @@ else: raise NotImplementedError("type %s not supported" % TYPE) -def getkind_num(cpu, TYPE): - if TYPE is lltype.Void: - return "void" - elif isinstance(TYPE, lltype.Primitive): - return "_%d" % cpu.numof(TYPE) - else: - assert isinstance(TYPE, lltype.Ptr) - if TYPE.TO._gckind == 'raw': - return "_%d" % cpu.numof(TYPE) - return "ptr" - def repr_pointer(box): try: return '*%s' % (box.value._obj.container._TYPE._name,) From fijal at codespeak.net Fri May 8 22:49:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 8 May 2009 22:49:11 +0200 (CEST) Subject: [pypy-svn] r65172 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090508204911.F324A16852C@codespeak.net> Author: fijal Date: Fri May 8 22:49:08 2009 New Revision: 65172 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: complain louder if x86 is not able to handle the call 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 Fri May 8 22:49:08 2009 @@ -605,6 +605,11 @@ return counter, basesize, ptr def calldescrof(self, functype, argtypes, resulttype): + for argtype in argtypes: + if rffi.sizeof(argtype) > WORD: + raise NotImplementedError("bigger than lltype.Signed") + if resulttype is not lltype.Void and rffi.sizeof(resulttype) > WORD: + raise NotImplementedError("bigger than lltype.Signed") if resulttype is lltype.Void: size = 0 else: From arigo at codespeak.net Fri May 8 23:16:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 May 2009 23:16:38 +0200 (CEST) Subject: [pypy-svn] r65173 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090508211638.C94971684ED@codespeak.net> Author: arigo Date: Fri May 8 23:16:38 2009 New Revision: 65173 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Add to policy.py the ability to look if the graph if using an unsupported variable kind, like floats. If so, the graph is simply skipped. 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 May 8 23:16:38 2009 @@ -1,5 +1,5 @@ from pypy.translator.simplify import get_funcobj -from pypy.jit.metainterp import support +from pypy.jit.metainterp import support, history class JitPolicy(object): @@ -16,6 +16,8 @@ return True def look_inside_graph(self, graph): + if contains_unsupported_variable_type(graph): + return False try: func = graph.func except AttributeError: @@ -65,6 +67,23 @@ return 'residual' return 'regular' +def contains_unsupported_variable_type(graph): + getkind = history.getkind + try: + for block in graph.iterblocks(): + for v in block.inputargs: + getkind(v.concretetype) + for op in block.operations: + for v in op.args: + getkind(v.concretetype) + getkind(op.result.concretetype) + except NotImplementedError, e: + history.log.WARNING('%s, ignoring graph' % (e,)) + history.log.WARNING(' %s' % (graph,)) + return True + return False + +# ____________________________________________________________ class StopAtXPolicy(JitPolicy): def __init__(self, *funcs): @@ -90,7 +109,9 @@ def look_inside_graph(self, graph): if graph in self.enabled_graphs: return self.enabled_graphs[graph] - return super(ManualJitPolicy, self).look_inside_graph(graph) + res = super(ManualJitPolicy, self).look_inside_graph(graph) + self.enabled_graphs[graph] = res # cache the result + return res def fill_seen_graphs(self): # subclasses should have their own 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 May 8 23:16:38 2009 @@ -602,6 +602,20 @@ res = self.interp_operations(f, [5]) assert res == f(5) + def test_long_long(self): + from pypy.rlib.rarithmetic import r_longlong, intmask + def g(n, m, o): + # This function should be completely marked as residual by + # codewriter.py on 32-bit platforms. On 64-bit platforms, + # this function should be JITted and the test should pass too. + n = r_longlong(n) + m = r_longlong(m) + return intmask((n*m) // o) + def f(n, m, o): + return g(n, m, o) // 3 + res = self.interp_operations(f, [1000000000, 90, 91]) + assert res == (1000000000 * 90 // 91) // 3 + class TestOOtype(BasicTests, OOJitMixin): From fijal at codespeak.net Sat May 9 03:46:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 May 2009 03:46:27 +0200 (CEST) Subject: [pypy-svn] r65174 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090509014627.F297D169F35@codespeak.net> Author: fijal Date: Sat May 9 03:46:26 2009 New Revision: 65174 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: a bit of paranoia nevert hurt anyone 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 May 9 03:46:26 2009 @@ -587,6 +587,7 @@ assert isinstance(A, lltype.GcArray) basesize, itemsize, ofs_length = symbolic.get_array_token(A, self.translate_support_code) + assert itemsize in [1, 2, WORD] assert ofs_length == 0 if isinstance(A.OF, lltype.Ptr) and A.OF.TO._gckind == 'gc': ptr = True @@ -628,6 +629,7 @@ def fielddescrof(self, S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname, self.translate_support_code) + assert size in [0, 1, WORD] if (isinstance(getattr(S, fieldname), lltype.Ptr) and getattr(S, fieldname).TO._gckind == 'gc'): ptr = True From fijal at codespeak.net Sat May 9 03:47:41 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 May 2009 03:47:41 +0200 (CEST) Subject: [pypy-svn] r65175 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090509014741.6EDF0169F35@codespeak.net> Author: fijal Date: Sat May 9 03:47:40 2009 New Revision: 65175 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: symbolics are fine 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 May 9 03:47:40 2009 @@ -629,7 +629,7 @@ def fielddescrof(self, S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname, self.translate_support_code) - assert size in [0, 1, WORD] + assert isinstance(size, Symbolic) or size in [0, 1, WORD] if (isinstance(getattr(S, fieldname), lltype.Ptr) and getattr(S, fieldname).TO._gckind == 'gc'): ptr = True From fijal at codespeak.net Sat May 9 03:55:55 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 May 2009 03:55:55 +0200 (CEST) Subject: [pypy-svn] r65176 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090509015555.2E871169F3B@codespeak.net> Author: fijal Date: Sat May 9 03:55:54 2009 New Revision: 65176 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Bah. Hack differently. 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 May 9 03:55:54 2009 @@ -587,7 +587,7 @@ assert isinstance(A, lltype.GcArray) basesize, itemsize, ofs_length = symbolic.get_array_token(A, self.translate_support_code) - assert itemsize in [1, 2, WORD] + assert rffi.sizeof(A.OF) in [1, 2, WORD] assert ofs_length == 0 if isinstance(A.OF, lltype.Ptr) and A.OF.TO._gckind == 'gc': ptr = True @@ -629,7 +629,7 @@ def fielddescrof(self, S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname, self.translate_support_code) - assert isinstance(size, Symbolic) or size in [0, 1, WORD] + assert rffi.sizeof(lltype.typeOf(getattr(S, fieldname))) in [1, 2, WORD] if (isinstance(getattr(S, fieldname), lltype.Ptr) and getattr(S, fieldname).TO._gckind == 'gc'): ptr = True From fijal at codespeak.net Sat May 9 03:58:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 May 2009 03:58:17 +0200 (CEST) Subject: [pypy-svn] r65177 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090509015817.81A8D169E3D@codespeak.net> Author: fijal Date: Sat May 9 03:58:16 2009 New Revision: 65177 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: typo 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 May 9 03:58:16 2009 @@ -629,7 +629,7 @@ def fielddescrof(self, S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname, self.translate_support_code) - assert rffi.sizeof(lltype.typeOf(getattr(S, fieldname))) in [1, 2, WORD] + assert rffi.sizeof(getattr(S, fieldname)) in [1, 2, WORD] if (isinstance(getattr(S, fieldname), lltype.Ptr) and getattr(S, fieldname).TO._gckind == 'gc'): ptr = True From jandem at codespeak.net Sat May 9 09:37:29 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Sat, 9 May 2009 09:37:29 +0200 (CEST) Subject: [pypy-svn] r65179 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090509073729.74EDB169F5F@codespeak.net> Author: jandem Date: Sat May 9 09:37:28 2009 New Revision: 65179 Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: Fix array indices. Almost all Array tests pass now, remaining failures are mostly from Array.Sort. Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Sat May 9 09:37:28 2009 @@ -3,6 +3,7 @@ ovfcheck_float_to_int, NAN, formatd_overflow from pypy.lang.js.execution import ThrowException, JsTypeError,\ RangeError, ReturnException +import string DE = 1 DD = 2 RO = 4 @@ -355,7 +356,7 @@ return try: - arrayindex = r_uint(float(P)) + arrayindex = r_uint(to_array_index(P)) except ValueError: return @@ -491,7 +492,8 @@ res = formatd_overflow('', 10, 'g', self.floatval) except OverflowError: raise - if (res[-3] == '+' or res[-3] == '-') and res[-2] == '0': + + if len(res) > 3 and (res[-3] == '+' or res[-3] == '-') and res[-2] == '0': cut = len(res) - 2 assert cut >= 0 res = res[:cut] + res[-1] @@ -673,6 +675,30 @@ return True return False +def to_array_index(s): + '''Convert s to an integer if (and only if) s is a valid array index. + ValueError is raised if conversion is not possible. + ''' + length = len(s) + + if length == 0 or length > 10: # len(str(2 ** 32)) + raise ValueError + + # '0' is only valid if no characters follow it + if s[0] == '0': + if length == 1: + return 0 + else: + raise ValueError + + arrayindex = 0 + for i in range(length): + if s[i] not in string.digits: + raise ValueError + arrayindex = (arrayindex * 10) + (ord(s[i]) - ord('0')) + #XXX: check for overflow? + return arrayindex + w_True = W_Boolean(True) w_False = W_Boolean(False) From arigo at codespeak.net Sat May 9 10:55:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 May 2009 10:55:38 +0200 (CEST) Subject: [pypy-svn] r65180 - pypy/branch/pyjitpl5/pypy/jit/backend/test Message-ID: <20090509085538.9B46D169F24@codespeak.net> Author: arigo Date: Sat May 9 10:55:36 2009 New Revision: 65180 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Log: Fix the test. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py Sat May 9 10:55:36 2009 @@ -468,7 +468,9 @@ ) if (self.guard_op is not None and self.guard_op.is_guard_exception()): - assert cpu.get_exc_value() + if self.guard_op.opnum == rop.GUARD_NO_EXCEPTION: + assert cpu.get_exception() + assert cpu.get_exc_value() cpu.clear_exception() else: assert not cpu.get_exception() From arigo at codespeak.net Sat May 9 10:56:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 May 2009 10:56:00 +0200 (CEST) Subject: [pypy-svn] r65181 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090509085600.BCA4E169F67@codespeak.net> Author: arigo Date: Sat May 9 10:55:58 2009 New Revision: 65181 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: Add a test, passing. 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 May 9 10:55:58 2009 @@ -1,7 +1,7 @@ import py from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver -from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT +from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask from pypy.jit.metainterp.policy import StopAtXPolicy @@ -220,6 +220,37 @@ res = self.meta_interp(f, [53], policy=StopAtXPolicy(check)) assert res == -2 + def test_exception_four_cases(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'm']) + class Error1(Exception): pass + class Error2(Exception): pass + class Error3(Exception): pass + class Error4(Exception): pass + def check(n): + if n % 4 == 0: raise Error1 + if n % 4 == 1: raise Error2 + if n % 4 == 2: raise Error3 + else: raise Error4 + def f(n): + m = 1 + while n > 0: + myjitdriver.can_enter_jit(n=n, m=m) + myjitdriver.jit_merge_point(n=n, m=m) + try: + check(n) + except Error1: + m = intmask(m * 3 + 1) + except Error2: + m = intmask(m * 5 + 1) + except Error3: + m = intmask(m * 7 + 1) + except Error4: + m = intmask(m * 11 + 1) + n -= 1 + return m + res = self.meta_interp(f, [99], policy=StopAtXPolicy(check)) + assert res == f(99) + def test_exception_later(self): myjitdriver = JitDriver(greens = [], reds = ['n']) def check(n): From arigo at codespeak.net Sat May 9 16:17:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 May 2009 16:17:45 +0200 (CEST) Subject: [pypy-svn] r65182 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090509141745.D8692169FBC@codespeak.net> Author: arigo Date: Sat May 9 16:17:44 2009 New Revision: 65182 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py Log: This actually fails on ootype only. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py Sat May 9 16:17:44 2009 @@ -25,7 +25,6 @@ assert res == main(20) def test_simple_recursion_with_exc(self): - py.test.skip("Fails") myjitdriver = JitDriver(greens=[], reds=['n', 'm']) class Error(Exception): pass @@ -80,4 +79,5 @@ pass class TestOOtype(RecursiveTests, OOJitMixin): - pass + def test_simple_recursion_with_exc(self): + py.test.skip("Fails") From arigo at codespeak.net Sat May 9 16:18:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 May 2009 16:18:31 +0200 (CEST) Subject: [pypy-svn] r65183 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090509141831.BB640169FBD@codespeak.net> Author: arigo Date: Sat May 9 16:18:31 2009 New Revision: 65183 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Add a test, and possibly fix another test (don't use global lists). 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 May 9 16:18:31 2009 @@ -471,9 +471,12 @@ def test_bridge_from_interpreter_3(self): # one case for backend - computing of framesize on guard failure mydriver = JitDriver(reds = ['n', 'x', 'y', 'z', 'k'], greens = []) - glob = [1] + class Global: + pass + glob = Global() def f(n): + glob.x = 1 x = 0 y = 0 z = 0 @@ -485,8 +488,8 @@ y += 3 z -= 15 k += 4 - if n == 17 and glob[0]: - glob[0] = 0 + if n == 17 and glob.x: + glob.x = 0 x += n + 1 y += n + 2 z += n + 3 @@ -529,6 +532,26 @@ for n, k in [(20, 0), (20, 1)]: interp.eval_graph(graph, [n, k]) + def test_bridge_leaving_interpreter_5(self): + mydriver = JitDriver(reds = ['n', 'x'], greens = []) + class Global: + pass + glob = Global() + + def f(n): + x = 0 + glob.x = 1 + while n > 0: + mydriver.can_enter_jit(n=n, x=x) + mydriver.jit_merge_point(n=n, x=x) + glob.x += 1 + x += 3 + n -= 1 + glob.x += 100 + return glob.x + x + res = self.meta_interp(f, [20], repeat=7, optimizer=SimpleOptimizer) + assert res == f(20) + def test_instantiate_classes(self): class Base: pass class A(Base): foo = 72 From arigo at codespeak.net Sat May 9 16:55:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 May 2009 16:55:34 +0200 (CEST) Subject: [pypy-svn] r65184 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090509145534.77FC7169FC8@codespeak.net> Author: arigo Date: Sat May 9 16:55:32 2009 New Revision: 65184 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py Log: Test and fix. 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 May 9 16:55:32 2009 @@ -1314,7 +1314,7 @@ if must_compile: guard_op = resumedescr.get_guard_op() suboperations = guard_op.suboperations - if suboperations[-1].opnum != rop.FAIL: + if suboperations[-1] is not guard_failure: must_compile = False log("ignoring old version of the guard") else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py Sat May 9 16:55:32 2009 @@ -2,6 +2,7 @@ from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.jit.metainterp.simple_optimize import Optimizer +from pypy.jit.metainterp.policy import StopAtXPolicy class RecursiveTests: @@ -74,6 +75,26 @@ assert res == main(10) self.check_enter_count_at_most(10) + def test_bug_1(self): + myjitdriver = JitDriver(greens=[], reds=['n', 'i', 'stack']) + def opaque(n, i): + if n == 1 and i == 19: + for j in range(20): + res = f(0) # recurse repeatedly, 20 times + assert res == 0 + def f(n): + stack = [n] + i = 0 + while i < 20: + myjitdriver.can_enter_jit(n=n, i=i, stack=stack) + myjitdriver.jit_merge_point(n=n, i=i, stack=stack) + opaque(n, i) + i += 1 + return stack.pop() + res = self.meta_interp(f, [1], optimizer=Optimizer, repeat=2, + policy=StopAtXPolicy(opaque)) + assert res == 1 + class TestLLtype(RecursiveTests, LLJitMixin): pass From arigo at codespeak.net Sat May 9 17:12:31 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 May 2009 17:12:31 +0200 (CEST) Subject: [pypy-svn] r65185 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090509151231.D18BE169F76@codespeak.net> Author: arigo Date: Sat May 9 17:12:31 2009 New Revision: 65185 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py Log: Fix for the JIT: test_zrpy_recursive.py. Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/llmemory.py Sat May 9 17:12:31 2009 @@ -416,11 +416,14 @@ def __eq__(self, other): if isinstance(other, fakeaddress): - obj1 = self._fixup().ptr - obj2 = other._fixup().ptr - if obj1 is not None: obj1 = obj1._obj - if obj2 is not None: obj2 = obj2._obj - return obj1 == obj2 + try: + obj1 = self._fixup().ptr + obj2 = other._fixup().ptr + if obj1 is not None: obj1 = obj1._obj + if obj2 is not None: obj2 = obj2._obj + return obj1 == obj2 + except lltype.DelayedPointer: + return self.ptr is other.ptr else: return NotImplemented From jandem at codespeak.net Sat May 9 19:01:22 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Sat, 9 May 2009 19:01:22 +0200 (CEST) Subject: [pypy-svn] r65186 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090509170122.C4097169EBA@codespeak.net> Author: jandem Date: Sat May 9 19:01:21 2009 New Revision: 65186 Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: typeof(null) is 'object' Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Sat May 9 19:01:21 2009 @@ -105,7 +105,7 @@ return "null" def type(self): - return 'null' + return 'object' w_Undefined = W_Undefined() w_Null = W_Null() From jandem at codespeak.net Sat May 9 19:12:22 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Sat, 9 May 2009 19:12:22 +0200 (CEST) Subject: [pypy-svn] r65187 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090509171222.CA32B169FBB@codespeak.net> Author: jandem Date: Sat May 9 19:12:22 2009 New Revision: 65187 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py Log: Implement prefix increment/decrement, and fix postfix ops (all related tests pass) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Sat May 9 19:12:22 2009 @@ -654,15 +654,37 @@ class STORE_POSTINCR(BaseStore): def process(self, ctx, name, stack): value = ctx.resolve_identifier(ctx, name) - newval = increment(ctx, value) - stack.append(value) + num = value.ToNumber(ctx) + newval = W_FloatNumber(num + 1) + + stack.append(W_FloatNumber(num)) return newval class STORE_POSTDECR(BaseStore): def process(self, ctx, name, stack): value = ctx.resolve_identifier(ctx, name) - newval = increment(ctx, value, -1) - stack.append(value) + num = value.ToNumber(ctx) + newval = W_FloatNumber(num - 1) + + stack.append(W_FloatNumber(num)) + return newval + +class STORE_PREINCR(BaseStore): + def process(self, ctx, name, stack): + value = ctx.resolve_identifier(ctx, name) + num = value.ToNumber(ctx) + newval = W_FloatNumber(num + 1) + + stack.append(newval) + return newval + +class STORE_PREDECR(BaseStore): + def process(self, ctx, name, stack): + value = ctx.resolve_identifier(ctx, name) + num = value.ToNumber(ctx) + newval = W_FloatNumber(num - 1) + + stack.append(newval) return newval class LABEL(Opcode): From jandem at codespeak.net Sat May 9 19:32:43 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Sat, 9 May 2009 19:32:43 +0200 (CEST) Subject: [pypy-svn] r65188 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090509173243.C6AF7169F76@codespeak.net> Author: jandem Date: Sat May 9 19:32:40 2009 New Revision: 65188 Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: implement bitwise not (~) Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Sat May 9 19:32:40 2009 @@ -468,6 +468,11 @@ def operation(self, ctx, op1, op2): return W_IntNumber(op1|op2) +class BITNOT(BaseUnaryOperation): + def eval(self, ctx, stack): + op = stack.pop().ToInt32(ctx) + stack.append(W_IntNumber(~op)) + class URSH(BaseBinaryBitwiseOp): def eval(self, ctx, stack): op2 = stack.pop().ToUInt32(ctx) Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Sat May 9 19:32:40 2009 @@ -230,10 +230,7 @@ BitwiseXor = create_binary_op('BITXOR') BitwiseOr = create_binary_op('BITOR') -#class BitwiseNot(UnaryOp): -# def eval(self, ctx): -# op1 = self.expr.eval(ctx).GetValue().ToInt32() -# return W_IntNumber(~op1) +BitwiseNot = create_unary_op('BITNOT') class Unconditional(Statement): def __init__(self, pos, target): From arigo at codespeak.net Sun May 10 11:20:01 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 11:20:01 +0200 (CEST) Subject: [pypy-svn] r65189 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090510092001.76141169E0F@codespeak.net> Author: arigo Date: Sun May 10 11:20:00 2009 New Revision: 65189 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/typesystem.py Log: An attempt at cleaning up the temporary values left in long-living BoxPtrs and BoxObjs. 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 Sun May 10 11:20:00 2009 @@ -94,7 +94,7 @@ loop = create_empty_loop(metainterp) loop.greenkey = greenkey loop.inputargs = history.inputargs - if start != 0: + if start > 0: loop.operations = history.operations[start:] else: loop.operations = history.operations 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 May 10 11:20:00 2009 @@ -1146,16 +1146,23 @@ else: # Found! Compile it as a loop. if j > 0: - pass - elif self.extra_rebuild_operations >= 0: - # The history only starts at a bridge, not at the - # full loop header. Complete it as a full loop by - # inserting a copy of the operations from the old - # loop branch before the guard that failed. - lgt = self.extra_rebuild_operations - assert lgt >= 0 - del self.history.operations[:lgt] - compile.prepare_loop_from_bridge(self, self.resumekey) + # clean up, but without shifting the end of the list + # (that would make 'history_guard_index' invalid) + for i in range(start): + self.history.operations[i] = None + else: + assert start == 0 + if self.extra_rebuild_operations >= 0: + # The history only starts at a bridge, not at the + # full loop header. Complete it as a full loop by + # inserting a copy of the operations from the old + # loop branch before the guard that failed. + start = self.extra_rebuild_operations + assert start >= 0 + # clean up, but without shifting the end of the list + for i in range(start): + self.history.operations[i] = None + compile.prepare_loop_from_bridge(self, self.resumekey) loop = self.compile(original_boxes, live_arg_boxes, start) raise GenerateMergePoint(live_arg_boxes, loop) @@ -1163,22 +1170,40 @@ start = len(self.history.operations) self.current_merge_points.append((live_arg_boxes, start)) - def resume_already_compiled(self, live_arg_boxes): - log('followed a path already compiled earlier') - key = self.resumekey - assert isinstance(key, compile.ResumeGuardDescr) - guard_op = key.get_guard_op() - loop = guard_op.suboperations[-1].jump_target - raise GenerateMergePoint(live_arg_boxes, loop) - def designate_target_loop(self, gmp): loop = gmp.target_loop num_green_args = self.staticdata.num_green_args residual_args = self.get_residual_args(loop, gmp.argboxes[num_green_args:]) history.set_future_values(self.cpu, residual_args) + self.clean_up_history() return loop + def clean_up_history(self): + # Clear the BoxPtrs used in self.history, at the end. The + # purpose of this is to clear the boxes that are also used in + # the TreeLoop just produced. After this, there should be no + # reference left to temporary values in long-living BoxPtrs. + # A note about recursion: setting to NULL like this should be + # safe, because ResumeGuardDescr.restore_patched_boxes should + # save and restore all the boxes that are also used by callers. + if self.history.inputargs is not None: + for box in self.history.inputargs: + self.staticdata.ts.clean_box(box) + lists = [self.history.operations] + while lists: + for op in lists.pop(): + if op is None: + continue + if op.result is not None: + self.staticdata.ts.clean_box(op.result) + if op.suboperations is not None: + lists.append(op.suboperations) + if op.optimized is not None: + lists.append(op.optimized.suboperations) + if op.optimized.result is not None: + self.staticdata.ts.clean_box(op.optimized.result) + def prepare_resume_from_failure(self, opnum): if opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now self.framestack[-1].follow_jump() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/typesystem.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/typesystem.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/typesystem.py Sun May 10 11:20:00 2009 @@ -78,6 +78,10 @@ obj = evaluebox.getptr(lltype.Ptr(rclass.OBJECT)) return cast_base_ptr_to_instance(Exception, obj) + def clean_box(self, box): + if isinstance(box, history.BoxPtr): + box.value = lltype.nullptr(llmemory.GCREF.TO) + class OOTypeHelper(TypeSystemHelper): @@ -119,6 +123,10 @@ obj = ootype.cast_from_object(ootype.ROOT, evaluebox.getobj()) return cast_base_ptr_to_instance(Exception, obj) + def clean_box(self, box): + if isinstance(box, history.BoxObj): + box.value = ootype.NULL + llhelper = LLTypeHelper() oohelper = OOTypeHelper() From arigo at codespeak.net Sun May 10 11:43:59 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 11:43:59 +0200 (CEST) Subject: [pypy-svn] r65190 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090510094359.B1AA2168576@codespeak.net> Author: arigo Date: Sun May 10 11:43:57 2009 New Revision: 65190 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Log: Fix test. 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 Sun May 10 11:43:57 2009 @@ -271,7 +271,7 @@ res = self.execute_operation(rop.NEW, [], 'ptr', self.cpu.sizeof(TP)) ofs_s = self.cpu.fielddescrof(TP, 's') - ofs_f = self.cpu.fielddescrof(TP, 'f') + #ofs_f = self.cpu.fielddescrof(TP, 'f') ofs_u = self.cpu.fielddescrof(TP, 'u') ofsc1 = self.cpu.fielddescrof(TP, 'c1') ofsc2 = self.cpu.fielddescrof(TP, 'c2') From arigo at codespeak.net Sun May 10 11:46:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 11:46:23 +0200 (CEST) Subject: [pypy-svn] r65191 - in pypy/branch/pyjitpl5/pypy/jit: backend/cli backend/cli/test tl Message-ID: <20090510094623.97BE116857C@codespeak.net> Author: arigo Date: Sun May 10 11:46:23 2009 New Revision: 65191 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/ (props changed) pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/ (props changed) pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (props changed) pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (props changed) pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (props changed) pypy/branch/pyjitpl5/pypy/jit/tl/run_all_tests.py (props changed) Log: fixeol From arigo at codespeak.net Sun May 10 12:56:51 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 12:56:51 +0200 (CEST) Subject: [pypy-svn] r65192 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp/test Message-ID: <20090510105651.537D8169E11@codespeak.net> Author: arigo Date: Sun May 10 12:56:50 2009 New Revision: 65192 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: A test for clean_up_history(). Passes, with a few extra clean-ups in the llgraph backend. 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 May 10 12:56:50 2009 @@ -820,6 +820,7 @@ frame.env = {} for i in range(len(loop.inputargs)): frame.env[loop.inputargs[i]] = _future_values[i] + del _future_values[:] def set_future_value_int(index, value): del _future_values[index:] @@ -853,6 +854,7 @@ import sys, pdb pdb.post_mortem(sys.exc_info()[2]) raise + del frame.env return result def frame_int_getvalue(frame, num): @@ -861,15 +863,9 @@ def frame_ptr_getvalue(frame, num): frame = _from_opaque(frame) - return frame.fail_args[num] - -def frame_int_getresult(frame): - frame = _from_opaque(frame) - return frame.returned_value - -def frame_ptr_getresult(frame): - frame = _from_opaque(frame) - return frame.returned_value + result = frame.fail_args[num] + frame.fail_args[num] = None + return result _last_exception = None @@ -1228,8 +1224,6 @@ setannotation(frame_execute, annmodel.SomeInteger()) setannotation(frame_int_getvalue, annmodel.SomeInteger()) setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF)) -setannotation(frame_int_getresult, annmodel.SomeInteger()) -setannotation(frame_ptr_getresult, annmodel.SomePtr(llmemory.GCREF)) setannotation(get_exception, annmodel.SomeAddress()) setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF)) 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 Sun May 10 12:56:50 2009 @@ -639,6 +639,33 @@ res = self.interp_operations(f, [1000000000, 90, 91]) assert res == (1000000000 * 90 // 91) // 3 + def test_free_object(self): + import weakref + from pypy.rlib import rgc + from pypy.rpython.lltypesystem.lloperation import llop + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) + class X(object): + pass + def main(n, x): + while n > 0: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + n -= x.foo + def g(n): + x = X() + x.foo = 2 + main(n, x) + x.foo = 5 + return weakref.ref(x) + def f(n): + r = g(n) + rgc.collect(); rgc.collect(); rgc.collect() + return r() is None + # + assert f(30) == 1 + res = self.meta_interp(f, [30]) + assert res == 1 + class TestOOtype(BasicTests, OOJitMixin): From arigo at codespeak.net Sun May 10 13:02:20 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 13:02:20 +0200 (CEST) Subject: [pypy-svn] r65193 - in pypy/branch/pyjitpl5/pypy/jit/backend: minimal/test x86/test Message-ID: <20090510110220.48A87168573@codespeak.net> Author: arigo Date: Sun May 10 13:02:19 2009 New Revision: 65193 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py Log: Skips. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_basic.py Sun May 10 13:02:19 2009 @@ -21,6 +21,7 @@ test_bridge_from_interpreter_3 = _skip test_instantiate_classes = _skip test_zerodivisionerror = _skip + test_free_object = _skip class TestOOtype(OOJitMixin, BasicTests): 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 Sun May 10 13:02:19 2009 @@ -36,3 +36,6 @@ # a Struct that belongs to the hash table is not seen as being # included in the larger Array py.test.skip("issue with ll2ctypes") + + def test_free_object(self): + py.test.skip("issue of freeing, probably with ll2ctypes") From arigo at codespeak.net Sun May 10 13:26:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 13:26:46 +0200 (CEST) Subject: [pypy-svn] r65195 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090510112646.56088169DB2@codespeak.net> Author: arigo Date: Sun May 10 13:26:45 2009 New Revision: 65195 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Don't need self.keepalives when translated, as Boehm currently looks inside fail_boxes. 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 Sun May 10 13:26:45 2009 @@ -287,7 +287,10 @@ def set_future_value_ptr(self, index, ptrvalue): assert index < MAX_FAIL_BOXES, "overflow!" - self.keepalives.append(ptrvalue) + if not we_are_translated(): + self.keepalives.append(ptrvalue) + else: + pass # Boehm looks inside fail_boxes (XXX) intvalue = self.cast_gcref_to_int(ptrvalue) self.assembler.fail_boxes[index] = intvalue @@ -310,7 +313,8 @@ if verbose: print "Entering: %d" % rffi.cast(lltype.Signed, func) res = func() - del self.keepalives[:] + if not we_are_translated(): + del self.keepalives[:] self.reraise_caught_exception() finally: if not self.translate_support_code: From arigo at codespeak.net Sun May 10 13:31:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 13:31:27 +0200 (CEST) Subject: [pypy-svn] r65196 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090510113127.9C3A6169DFA@codespeak.net> Author: arigo Date: Sun May 10 13:31:27 2009 New Revision: 65196 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Log: Another attempt at freeing memory early... 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 Sun May 10 13:31:27 2009 @@ -299,7 +299,10 @@ def get_latest_value_ptr(self, index): intvalue = self.assembler.fail_boxes[index] - return self.cast_int_to_gcref(intvalue) + ptrvalue = self.cast_int_to_gcref(intvalue) + # clear after reading (-1 instead of 0, to crash if still used) + self.assembler.fail_boxes[index] = -1 + return ptrvalue def execute_call(self, loop, func, verbose): # help flow objspace From arigo at codespeak.net Sun May 10 13:47:24 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 13:47:24 +0200 (CEST) Subject: [pypy-svn] r65197 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090510114724.8EFCA169E1E@codespeak.net> Author: arigo Date: Sun May 10 13:47:22 2009 New Revision: 65197 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Log: Yay! With this final hack, a test finally pass. See next checkin for the test... 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 Sun May 10 13:47:22 2009 @@ -264,17 +264,21 @@ self.make_sure_mc_exists() addr = self.mc.tell() self.mc.SUB(esp, imm(framesize * WORD)) + # This uses XCHG to put zeroes in fail_boxes after reading them, + # just in case they are pointers. for i in range(len(arglocs)): loc = arglocs[i] if not isinstance(loc, REG): - self.mc.MOV(ecx, - addr_add(imm(self.fail_box_addr), imm(i*WORD))) + self.mc.XOR(ecx, ecx) + self.mc.XCHG(ecx, + addr_add(imm(self.fail_box_addr), imm(i*WORD))) self.mc.MOV(loc, ecx) for i in range(len(arglocs)): loc = arglocs[i] if isinstance(loc, REG): - self.mc.MOV(loc, - addr_add(imm(self.fail_box_addr), imm(i*WORD))) + self.mc.XOR(loc, loc) + self.mc.XCHG(loc, + addr_add(imm(self.fail_box_addr), imm(i*WORD))) self.mc.JMP(rel32(jumpaddr)) self.mc.done() return addr From arigo at codespeak.net Sun May 10 14:07:28 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 14:07:28 +0200 (CEST) Subject: [pypy-svn] r65198 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090510120728.4EBFD1683F6@codespeak.net> Author: arigo Date: Sun May 10 14:07:27 2009 New Revision: 65198 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (contents, props changed) Log: A test for r65197. Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Sun May 10 14:07:27 2009 @@ -0,0 +1,57 @@ +""" +This is a test that translates a complete JIT to C and runs it. It is +not testing much, expect that it basically works. What it *is* testing, +however, is the correct handling of GC, i.e. if objects are freed as +soon as possible (at least in a simple case). +""" +import weakref +from pypy.rlib import rgc +from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rlib.jit import JitDriver +from pypy.jit.backend.x86.runner import CPU386 + + +myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) + + +class X(object): + pass + +def main(n, x): + while n > 0: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + n -= x.foo +main._dont_inline_ = True + +def g(n): + x = X() + x.foo = 2 + main(n, x) + x.foo = 5 + return weakref.ref(x) +g._dont_inline_ = True + +def f(args): + r = g(3000) + rgc.collect(); rgc.collect(); rgc.collect() + print int(r() is None) + return 0 + + +def test_compile(): + from pypy.translator.translator import TranslationContext + from pypy.jit.metainterp.warmspot import apply_jit + from pypy.translator.c import genc + # + t = TranslationContext() + t.config.translation.jit = True # forces other options as well + t.buildannotator().build_types(f, [int]) + t.buildrtyper().specialize() + apply_jit(t, CPUClass=CPU386) + cbuilder = genc.CStandaloneBuilder(t, f, t.config) + cbuilder.generate_source() + cbuilder.compile() + # + data = cbuilder.cmdexec('') + assert int(data.strip()) == 1 From pedronis at codespeak.net Sun May 10 15:45:47 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 May 2009 15:45:47 +0200 (CEST) Subject: [pypy-svn] r65199 - in pypy/build/bot2/pypybuildbot: . test Message-ID: <20090510134547.87FB016857C@codespeak.net> Author: pedronis Date: Sun May 10 15:45:45 2009 New Revision: 65199 Modified: pypy/build/bot2/pypybuildbot/summary.py pypy/build/bot2/pypybuildbot/test/test_summary.py Log: - have a way to control the display order of branches - don't display builds with rev older than 7 days - don't display builds older than 7 days in non-drilling views Modified: pypy/build/bot2/pypybuildbot/summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/summary.py (original) +++ pypy/build/bot2/pypybuildbot/summary.py Sun May 10 15:45:45 2009 @@ -563,11 +563,12 @@ class Summary(HtmlResource): - def __init__(self, categories=[]): + def __init__(self, categories=[], branch_order_prefixes=[]): HtmlResource.__init__(self) self.putChild('longrepr', LongRepr()) self._defaultBranchCache = {} self.categories = categories + self.branch_order_prefixes = branch_order_prefixes def getTitle(self, request): status = self.getStatus(request) @@ -604,6 +605,13 @@ branch = branch or getProp(build, 'branch') return branch + def _now(self): + return time.time() + + def _age(self, build): + start, _ = build.getTimes() + return (self._now()-start)/(60*60*24) # in days + def recentRuns(self, status, only_recentrevs=None, only_branches=None, only_builder=None, only_builds=None, only_categories=None): @@ -611,6 +619,8 @@ test_branch = make_test(only_branches) test_builder = make_test(only_builder) fixed_builder = bool(only_builder) + prune_old = not (only_builds or only_recentrevs or + only_builder or only_branches) cat_branches = {} @@ -629,6 +639,8 @@ builditer = builderStatus.generateFinishedBuilds(num_builds=5*N) for build in builditer: + if prune_old and self._age(build) > 7: + continue branch = self._get_branch(status, build) if not test_branch(branch): continue @@ -636,14 +648,14 @@ if not test_rev(got_rev): continue - cat_branch = (builderStatus.category, branch) runs, no_revision_builds = cat_branches.setdefault(cat_branch, ({}, [])) if got_rev is None: - no_revision_builds.append(build) + if self._age(build) <= 7: + no_revision_builds.append(build) else: rev = int(got_rev) buildNumber = build.getNumber() @@ -684,11 +696,21 @@ return builds def _cat_branch_key(self, (category, branch)): + branch_key = (0,) + if branch is not None: + for j, prefix in enumerate(self.branch_order_prefixes): + if branch.startswith(prefix): + branch_key = (j+1, branch) + break + else: + branch_key = (len(self.branch_order_prefixes)+1, branch) try: i = self.categories.index(category) - return (0, i, branch) + cat_key = (0, i) except ValueError: - return (1, category, branch) + cat_key = (1, category) + + return cat_key + branch_key def body(self, request): t0 = time.time() Modified: pypy/build/bot2/pypybuildbot/test/test_summary.py ============================================================================== --- pypy/build/bot2/pypybuildbot/test/test_summary.py (original) +++ pypy/build/bot2/pypybuildbot/test/test_summary.py Sun May 10 15:45:45 2009 @@ -5,7 +5,7 @@ from buildbot.process import factory as process_factory from pypybuildbot import summary from StringIO import StringIO -import re +import re, time class TestOutcomes(object): @@ -344,6 +344,7 @@ t = 1000 for rev, reslog in builds: build = status_builder.BuildStatus(builder, n) + build.started = time.time() build.setProperty('got_revision', str(rev), None) step = build.addStepWithName('pytest') step.logs.extend([FakeLog(step, 'pytestLog', reslog), @@ -374,6 +375,7 @@ def test_one_build_no_rev(self): builder = status_builder.BuilderStatus('builder0') build = status_builder.BuildStatus(builder, 0) + build.started = time.time() build.buildFinished() builder.addBuildToCache(build) builder.nextBuildNumber = len(builder.buildCache) @@ -389,6 +391,7 @@ def test_one_build_no_logs(self): builder = status_builder.BuilderStatus('builder0') build = status_builder.BuildStatus(builder, 0) + build.started = time.time() build.setProperty('got_revision', '50000', None) build.buildFinished() builder.addBuildToCache(build) @@ -408,6 +411,7 @@ def test_one_build_no_logs_failure(self): builder = status_builder.BuilderStatus('builder0') build = status_builder.BuildStatus(builder, 0) + build.started = time.time() build.setProperty('got_revision', '50000', None) step = build.addStepWithName('step') step.setText(['step', 'borken']) @@ -589,6 +593,7 @@ def test_many_pytestLogs(self): builder = status_builder.BuilderStatus('builder1') build = status_builder.BuildStatus(builder, 0) + build.started = time.time() build.setProperty('got_revision', '70000', None) step = build.addStepWithName('pytest') step.logs.extend([FakeLog(step, 'pytestLog', "F TEST1")]) @@ -615,6 +620,7 @@ def test_subtle_failures(self): builder = status_builder.BuilderStatus('builder1') build = status_builder.BuildStatus(builder, 0) + build.started = time.time() build.setProperty('got_revision', '70000', None) step = build.addStepWithName('pytest') step.logs.extend([FakeLog(step, 'pytestLog', ". TEST1")]) @@ -631,20 +637,33 @@ assert 'pytest failed slave lost' in out - def test_category_sorting_key(self): - s = summary.Summary(['foo', 'bar']) + def test_category_branch_sorting_key(self): + s = summary.Summary(['foo', 'bar'], + ['trunk', 'release/', 'branch/']) + + res = s._cat_branch_key(('foo', None)) + assert res == (0, 0, 0) res = s._cat_branch_key(('foo', 'trunk')) - assert res == (0, 0, 'trunk') + assert res == (0, 0, 1, 'trunk') res = s._cat_branch_key(('bar', 'trunk')) - assert res == (0, 1, 'trunk') + assert res == (0, 1, 1, 'trunk') res = s._cat_branch_key((None, 'trunk')) - assert res == (1, None, 'trunk') + assert res == (1, None, 1, 'trunk') res = s._cat_branch_key(('dontknow', 'trunk')) - assert res == (1, 'dontknow', 'trunk') + assert res == (1, 'dontknow', 1, 'trunk') + + res = s._cat_branch_key((None, 'branch/foo')) + assert res == (1, None, 3, 'branch/foo') + + res = s._cat_branch_key((None, 'release/1')) + assert res == (1, None, 2, 'release/1') + + res = s._cat_branch_key((None, 'what')) + assert res == (1, None, 4, 'what') def test_builders_with_categories(self): builder1 = status_builder.BuilderStatus('builder_foo') @@ -685,21 +704,30 @@ p1000builder0 = out.find('builder0', p1000) assert p999builder0-p999 == p1000builder0-p1000+1 - def test_build_times(self): + def test_build_times_and_filtering(self): builder1 = status_builder.BuilderStatus('builder1') builder2 = status_builder.BuilderStatus('builder2') add_builds(builder1, [(60000, "F TEST1\n")]) + add_builds(builder2, [(50000, ". TEST2\n")]) add_builds(builder2, [(60000, "F TEST2\n")]) + builder1.getBuild(0).started = 1228258800 # 3 Dec 2008 builder1.getBuild(0).finished = 1228258800 # 3 Dec 2008 - builder2.getBuild(0).finished = 1228431600 # 5 Dec 2008 + builder2.getBuild(1).started = 1228431600 # 5 Dec 2008 + builder2.getBuild(1).finished = 1228431600 # 5 Dec 2008 + + builder2.getBuild(0).started = 1227913200 # 29 Nov 2008 + builder2.getBuild(0).finished = 1227913200 # 29 Nov 2008 s = summary.Summary() + s._now = lambda: 1228604400 # 7 Dec 2008 req = FakeRequest([builder1, builder2]) out = s.body(req) assert '(03 Dec..05 Dec)' in out + # pruning of builds older than 7 days + assert '(29 Nov)' not in out From arigo at codespeak.net Sun May 10 16:29:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 16:29:41 +0200 (CEST) Subject: [pypy-svn] r65200 - pypy/trunk/pypy/lang/prolog/builtin Message-ID: <20090510142941.BD388169E14@codespeak.net> Author: arigo Date: Sun May 10 16:29:40 2009 New Revision: 65200 Modified: pypy/trunk/pypy/lang/prolog/builtin/atomconstruction.py Log: Fix for pypy.lang.test.test_translation. This makes sure stopbefore is annotated "nonneg", as required by the following s.find(). Modified: pypy/trunk/pypy/lang/prolog/builtin/atomconstruction.py ============================================================================== --- pypy/trunk/pypy/lang/prolog/builtin/atomconstruction.py (original) +++ pypy/trunk/pypy/lang/prolog/builtin/atomconstruction.py Sun May 10 16:29:40 2009 @@ -66,10 +66,11 @@ stopbefore = len(s) + 1 else: startbefore = helper.unwrap_int(before) - stopbefore = startbefore + 1 if startbefore < 0: startbefore = 0 stopbefore = len(s) + 1 + else: + stopbefore = startbefore + 1 oldstate = engine.heap.branch() if not isinstance(sub, term.Var): s1 = helper.unwrap_atom(sub) From arigo at codespeak.net Sun May 10 17:02:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 17:02:14 +0200 (CEST) Subject: [pypy-svn] r65201 - pypy/trunk/pypy/translator/c/gcc Message-ID: <20090510150214.57EE916857A@codespeak.net> Author: arigo Date: Sun May 10 17:02:12 2009 New Revision: 65201 Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Log: Derive a name for these symbols from the filename, instead of using a counter. (The latter fails to work with the way the Makefile calls trackgcroot: all files are number 0 in this case.) Modified: pypy/trunk/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/trunk/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/trunk/pypy/translator/c/gcc/trackgcroot.py Sun May 10 17:02:12 2009 @@ -34,7 +34,6 @@ def clear(self): self.gcmaptable = [] self.seen_main = False - self.files_seen = 0 def dump_raw_table(self, output): print >> output, "seen_main = %d" % (self.seen_main,) @@ -130,10 +129,9 @@ if in_function: lines = self.process_function(lines, entrypoint, filename) newfile.writelines(lines) - self.files_seen += 1 def process_function(self, lines, entrypoint, filename): - tracker = FunctionGcRootTracker(lines, filetag = self.files_seen) + tracker = FunctionGcRootTracker(lines, filetag=getidentifier(filename)) tracker.is_main = tracker.funcname == entrypoint if self.verbose: print >> sys.stderr, '[trackgcroot:%s] %s' % (filename, @@ -408,7 +406,7 @@ if label is None: k = call.lineno while 1: - label = '__gcmap_IN%d_%s_%d' % (self.filetag, self.funcname, k) + label = '__gcmap_%s__%s_%d' % (self.filetag, self.funcname, k) if label not in self.labels: break k += 1 @@ -989,6 +987,19 @@ del result[5] return result +def getidentifier(s): + def mapchar(c): + if c.isalnum(): + return c + else: + return '_' + if s.endswith('.s'): + s = s[:-2] + s = ''.join([mapchar(c) for c in s]) + while s.endswith('__'): + s = s[:-1] + return s + if __name__ == '__main__': verbose = 1 From arigo at codespeak.net Sun May 10 17:03:55 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 17:03:55 +0200 (CEST) Subject: [pypy-svn] r65202 - pypy/branch/pyjitpl5/pypy/translator/c/gcc Message-ID: <20090510150355.5CC74169DB6@codespeak.net> Author: arigo Date: Sun May 10 17:03:54 2009 New Revision: 65202 Modified: pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py Log: Merge from the trunk. Fix test failures (which don't fail on the trunk, but only on this branch... I'm not sure why). Modified: pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py Sun May 10 17:03:54 2009 @@ -34,7 +34,6 @@ def clear(self): self.gcmaptable = [] self.seen_main = False - self.files_seen = 0 def dump_raw_table(self, output): print >> output, "seen_main = %d" % (self.seen_main,) @@ -130,10 +129,9 @@ if in_function: lines = self.process_function(lines, entrypoint, filename) newfile.writelines(lines) - self.files_seen += 1 def process_function(self, lines, entrypoint, filename): - tracker = FunctionGcRootTracker(lines, filetag = self.files_seen) + tracker = FunctionGcRootTracker(lines, filetag=getidentifier(filename)) tracker.is_main = tracker.funcname == entrypoint if self.verbose: print >> sys.stderr, '[trackgcroot:%s] %s' % (filename, @@ -408,7 +406,7 @@ if label is None: k = call.lineno while 1: - label = '__gcmap_IN%d_%s_%d' % (self.filetag, self.funcname, k) + label = '__gcmap_%s__%s_%d' % (self.filetag, self.funcname, k) if label not in self.labels: break k += 1 @@ -989,6 +987,19 @@ del result[5] return result +def getidentifier(s): + def mapchar(c): + if c.isalnum(): + return c + else: + return '_' + if s.endswith('.s'): + s = s[:-2] + s = ''.join([mapchar(c) for c in s]) + while s.endswith('__'): + s = s[:-1] + return s + if __name__ == '__main__': verbose = 1 From arigo at codespeak.net Sun May 10 17:05:12 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 17:05:12 +0200 (CEST) Subject: [pypy-svn] r65203 - pypy/branch/pyjitpl5/pypy/translator/js Message-ID: <20090510150512.99F3A169E06@codespeak.net> Author: arigo Date: Sun May 10 17:05:12 2009 New Revision: 65203 Removed: pypy/branch/pyjitpl5/pypy/translator/js/ Log: Kill this directory and its test failures. From pedronis at codespeak.net Sun May 10 17:05:16 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 May 2009 17:05:16 +0200 (CEST) Subject: [pypy-svn] r65204 - pypy/build/bot2/pypybuildbot Message-ID: <20090510150516.35065169E1A@codespeak.net> Author: pedronis Date: Sun May 10 17:05:14 2009 New Revision: 65204 Modified: pypy/build/bot2/pypybuildbot/master.py Log: bump the lru cache size to cope with the current result ets Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sun May 10 17:05:14 2009 @@ -17,6 +17,7 @@ # pypy test summary page summary = load('pypybuildbot.summary') +summary.outcome_set_cache = summary.RevisionOutcomeSetCache(80) status.putChild('summary', summary.Summary(['own', 'applevel', 'lib-python', 'stackless', 'windows', 'maemo', 'other'])) From arigo at codespeak.net Sun May 10 17:36:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 17:36:00 +0200 (CEST) Subject: [pypy-svn] r65205 - pypy/build/bot2/pypybuildbot Message-ID: <20090510153600.5A0AF169E7F@codespeak.net> Author: arigo Date: Sun May 10 17:35:57 2009 New Revision: 65205 Modified: pypy/build/bot2/pypybuildbot/master.py Log: Use a cache size computed from the number of schedulers of BuildmasterConfig. Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sun May 10 17:35:57 2009 @@ -17,7 +17,6 @@ # pypy test summary page summary = load('pypybuildbot.summary') -summary.outcome_set_cache = summary.RevisionOutcomeSetCache(80) status.putChild('summary', summary.Summary(['own', 'applevel', 'lib-python', 'stackless', 'windows', 'maemo', 'other'])) @@ -129,3 +128,6 @@ 'projectURL': 'http://codespeak.net/pypy/', 'projectName': 'PyPy'} +summary.outcome_set_cache = summary.RevisionOutcomeSetCache( + sum([len(_sched.listBuilderNames()) + for _sched in BuildmasterConfig['schedulers']]) * 6) From pedronis at codespeak.net Sun May 10 19:05:13 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 May 2009 19:05:13 +0200 (CEST) Subject: [pypy-svn] r65206 - pypy/build/bot2/pypybuildbot Message-ID: <20090510170513.D94B4169E1E@codespeak.net> Author: pedronis Date: Sun May 10 19:05:12 2009 New Revision: 65206 Modified: pypy/build/bot2/pypybuildbot/master.py Log: compromise, not beatiful but not sure more work on this is worth it, the main issue is really how much memory we can spend for the cache on codespeak Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sun May 10 19:05:12 2009 @@ -128,6 +128,13 @@ 'projectURL': 'http://codespeak.net/pypy/', 'projectName': 'PyPy'} -summary.outcome_set_cache = summary.RevisionOutcomeSetCache( - sum([len(_sched.listBuilderNames()) +CACHESIZE = 80 # cache size for build outcomes + +estimated = (sum([len(_sched.listBuilderNames()) for _sched in BuildmasterConfig['schedulers']]) * 6) + +if estimated > CACHESIZE: + raise ValueError("master.py CACHESIZE (%d) is too small considered" + " a builder*scheduler combinations based estimate (%d)" + % (CACHESIZE, estimated)) +summary.outcome_set_cache.cachesize = CACHESIZE From arigo at codespeak.net Sun May 10 22:01:55 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 22:01:55 +0200 (CEST) Subject: [pypy-svn] r65207 - pypy/branch/pyjitpl5/pypy/translator/llvm Message-ID: <20090510200155.DEBE9168577@codespeak.net> Author: arigo Date: Sun May 10 22:01:54 2009 New Revision: 65207 Removed: pypy/branch/pyjitpl5/pypy/translator/llvm/ Log: Remove llvm here too. From arigo at codespeak.net Sun May 10 22:24:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 May 2009 22:24:26 +0200 (CEST) Subject: [pypy-svn] r65208 - in pypy/branch/pyjitpl5/pypy: jit/backend/x86 rpython rpython/lltypesystem translator/c/src Message-ID: <20090510202426.B114416854F@codespeak.net> Author: arigo Date: Sun May 10 22:24:26 2009 New Revision: 65208 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/translator/c/src/mem.h Log: Kill the old operation 'call_boehm_gc_alloc', introduced for JIT usage before we had rffi.llexternal to invoke Boehm directly. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Sun May 10 22:24:26 2009 @@ -1,33 +1,17 @@ - -from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.objectmodel import we_are_translated -from pypy.translator.c.test.test_genc import compile -from pypy.rpython.annlowlevel import llhelper -from pypy.jit.metainterp.history import log, ConstAddr -import ctypes -import py +from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.translator.tool.cbuild import ExternalCompilationInfo GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) -def gc_malloc(size): - return llop.call_boehm_gc_alloc(llmemory.Address, size) +compilation_info = ExternalCompilationInfo(libraries=['gc']) + +malloc_fn_ptr = rffi.llexternal("GC_malloc", + [lltype.Signed], # size_t, but good enough + llmemory.Address, + compilation_info=compilation_info, + sandboxsafe=True, + _nowrapper=True) 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 + return rffi.cast(lltype.Signed, malloc_fn_ptr) Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Sun May 10 22:24:26 2009 @@ -971,10 +971,6 @@ def op_stack_malloc(self, size): # mmh raise NotImplementedError("backend only") - # ______ for the JIT ____________ - def op_call_boehm_gc_alloc(self): - raise NotImplementedError("call_boehm_gc_alloc") - # ____________________________________________________________ # Overflow-detecting variants 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 Sun May 10 22:24:26 2009 @@ -1025,6 +1025,8 @@ _TYPE = llmemory.Address def __new__(cls, void_p): + if isinstance(void_p, (int, long)): + void_p = ctypes.c_void_p(void_p) self = long.__new__(cls, void_p.value) self.void_p = void_p self.intval = intmask(void_p.value) @@ -1037,7 +1039,9 @@ return '<_lladdress %s>' % (self.void_p,) def __eq__(self, other): - return cast_adr_to_int(other) == self.intval + if not isinstance(other, (int, long)): + other = cast_adr_to_int(other) + return intmask(other) == self.intval def __ne__(self, other): return not self == other @@ -1066,7 +1070,7 @@ return self.intval def _cast_to_adr(self): - return _lladdress(ctypes.c_void_p(self.intval)) + return _lladdress(self.intval) def cast_adr_to_int(addr): if isinstance(addr, llmemory.fakeaddress): 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 Sun May 10 22:24:26 2009 @@ -383,7 +383,6 @@ # __________ used by the JIT ________ - 'call_boehm_gc_alloc': LLOp(canraise=(MemoryError,)), 'jit_marker': LLOp(), 'promote_virtualizable':LLOp(canrun=True), 'get_exception_addr': LLOp(), Modified: pypy/branch/pyjitpl5/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/src/mem.h (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/src/mem.h Sun May 10 22:24:26 2009 @@ -138,13 +138,6 @@ memset((void*) r, 0, size); \ } -/* as we said in rbuiltin.py: -# XXX this next little bit is a monstrous hack. the Real Thing awaits -# some kind of proper GC integration -if GC integration has happened and this junk is still here, please delete it :) -*/ -#define OP_CALL_BOEHM_GC_ALLOC(size, r) OP_BOEHM_ZERO_MALLOC(size, r, void *, 0, 0) - #define OP_BOEHM_DISAPPEARING_LINK(link, obj, r) \ if (GC_base(obj) == NULL) \ ; /* 'obj' is probably a prebuilt object - it makes no */ \ From afa at codespeak.net Sun May 10 22:26:51 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 10 May 2009 22:26:51 +0200 (CEST) Subject: [pypy-svn] r65209 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090510202651.A4AAA16854F@codespeak.net> Author: afa Date: Sun May 10 22:26:51 2009 New Revision: 65209 Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py Log: Remove confusion in imports Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Sun May 10 22:26:51 2009 @@ -513,10 +513,9 @@ def make_string_mappings(strtype): if strtype is str: - from pypy.rpython.lltypesystem.rstr import UNICODE as STRTYPE + from pypy.rpython.lltypesystem.rstr import STR 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 = '' From fijal at codespeak.net Mon May 11 00:55:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 May 2009 00:55:01 +0200 (CEST) Subject: [pypy-svn] r65210 - pypy/branch/pyjitpl5/lib-python Message-ID: <20090510225501.8A67F16853B@codespeak.net> Author: fijal Date: Mon May 11 00:55:00 2009 New Revision: 65210 Modified: pypy/branch/pyjitpl5/lib-python/conftest.py Log: Quick'n'dirty hack to skip all tests that require thread. Ideally we would detect what kind of translation provide what modules, but not yet. Modified: pypy/branch/pyjitpl5/lib-python/conftest.py ============================================================================== --- pypy/branch/pyjitpl5/lib-python/conftest.py (original) +++ pypy/branch/pyjitpl5/lib-python/conftest.py Mon May 11 00:55:00 2009 @@ -628,6 +628,9 @@ else: msg = regrtest.skip py.test.skip(msg) + # XXX evil hack + if 'thread' in regrtest.usemodules: + py.test.skip("uses thread") (skipped, exit_status, test_stdout, test_stderr) = self.getresult(regrtest) if skipped: From arigo at codespeak.net Mon May 11 12:10:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 12:10:07 +0200 (CEST) Subject: [pypy-svn] r65211 - in pypy/branch/pyjitpl5/pypy/rpython: lltypesystem test Message-ID: <20090511101007.3610B1684FB@codespeak.net> Author: arigo Date: Mon May 11 12:10:05 2009 New Revision: 65211 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rstr.py pypy/branch/pyjitpl5/pypy/rpython/test/test_rclass.py pypy/branch/pyjitpl5/pypy/rpython/test/test_rstr.py pypy/branch/pyjitpl5/pypy/rpython/test/test_runicode.py Log: Give a uniform way to hash strings, unicodes, and instances given a low-level pointer to them -- via an ADT method, gethash(). 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 Mon May 11 12:10:05 2009 @@ -350,6 +350,10 @@ if '_immutable_' in self.classdef.classdesc.classdict: hints = hints.copy() hints['immutable'] = True + if ('_hash_cache_' in fields or + '_hash_cache_' in self.rbase.allinstancefields): + adtmeths = adtmeths.copy() + adtmeths['gethash'] = self.get_ll_hash_function() object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rstr.py Mon May 11 12:10:05 2009 @@ -70,17 +70,6 @@ copy_string_contents = _new_copy_contents_fun(STR, Char, 'string') copy_unicode_contents = _new_copy_contents_fun(UNICODE, UniChar, 'unicode') -STR.become(GcStruct('rpy_string', ('hash', Signed), - ('chars', Array(Char, hints={'immutable': True})), - adtmeths={'malloc' : staticAdtMethod(mallocstr), - 'empty' : staticAdtMethod(emptystrfun), - 'copy_contents' : staticAdtMethod(copy_string_contents)})) -UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), - ('chars', Array(UniChar, hints={'immutable': True})), - adtmeths={'malloc' : staticAdtMethod(mallocunicode), - 'empty' : staticAdtMethod(emptyunicodefun), - 'copy_contents' : staticAdtMethod(copy_unicode_contents)} - )) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() CONST_UNICODE_CACHE = WeakValueDictionary() @@ -843,6 +832,22 @@ TEMP = GcArray(Ptr(STR)) +# ____________________________________________________________ + +STR.become(GcStruct('rpy_string', ('hash', Signed), + ('chars', Array(Char, hints={'immutable': True})), + adtmeths={'malloc' : staticAdtMethod(mallocstr), + 'empty' : staticAdtMethod(emptystrfun), + 'copy_contents' : staticAdtMethod(copy_string_contents), + 'gethash': LLHelpers.ll_strhash})) +UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), + ('chars', Array(UniChar, hints={'immutable': True})), + adtmeths={'malloc' : staticAdtMethod(mallocunicode), + 'empty' : staticAdtMethod(emptyunicodefun), + 'copy_contents' : staticAdtMethod(copy_unicode_contents), + 'gethash': LLHelpers.ll_strhash} + )) + # TODO: make the public interface of the rstr module cleaner ll_strconcat = LLHelpers.ll_strconcat Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_rclass.py Mon May 11 12:10:05 2009 @@ -781,6 +781,41 @@ expected = hex(r_uint(xid)).lower().replace('l', '') assert expected in xstr + def test_hash_via_type(self): + from pypy.annotation import model as annmodel + from pypy.rpython import extregistry + from pypy.rpython.annlowlevel import cast_object_to_ptr + class X(object): pass + class Y(X): pass + class Z(Y): pass + + def my_gethash(z): + not_implemented + + def ll_my_gethash(ptr): + return ptr.gethash() + + class MyGetHashEntry(extregistry.ExtRegistryEntry): + _about_ = my_gethash + def compute_result_annotation(self, s_instance): + return annmodel.SomeInteger() + def specialize_call(self, hop): + [v_instance] = hop.inputargs(*hop.args_r) + return hop.gendirectcall(ll_my_gethash, v_instance) + + def f(n): + if n > 10: + z = Y() + got = -1 # path never used + else: + z = Z() + got = my_gethash(z) + expected = hash(z) # put the _hash_cache_ in the class Y + return got - expected + + res = self.interpret(f, [5]) + assert res == 0 + class TestOOtype(BaseTestRclass, OORtypeMixin): Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_rstr.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_rstr.py Mon May 11 12:10:05 2009 @@ -1,7 +1,7 @@ import random from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.rstr import AbstractLLHelpers -from pypy.rpython.lltypesystem.rstr import LLHelpers, mallocstr +from pypy.rpython.lltypesystem.rstr import LLHelpers, STR from pypy.rpython.ootypesystem.ootype import make_string from pypy.rpython.rtyper import RPythonTyper, TyperError from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin @@ -861,6 +861,17 @@ res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1) assert res == s1.rfind(s2) + def test_hash_via_type(self): + def f(n): + s = malloc(STR, n) + s.hash = 0 + for i in range(n): + s.chars[i] = chr(i) + return s.gethash() - hash('\x00\x01\x02\x03\x04') + + res = self.interpret(f, [5]) + assert res == 0 + class TestOOtype(BaseTestRstr, OORtypeMixin): Modified: pypy/branch/pyjitpl5/pypy/rpython/test/test_runicode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/test/test_runicode.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/test/test_runicode.py Mon May 11 12:10:05 2009 @@ -1,5 +1,6 @@ - +from pypy.rpython.lltypesystem.lltype import malloc +from pypy.rpython.lltypesystem.rstr import LLHelpers, UNICODE from pypy.rpython.test.tool import LLRtypeMixin, OORtypeMixin from pypy.rpython.test.test_rstr import AbstractTestRstr import py @@ -214,5 +215,16 @@ class TestLLtype(BaseTestRUnicode, LLRtypeMixin): EMPTY_STRING_HASH = -1 + def test_hash_via_type(self): + def f(n): + s = malloc(UNICODE, n) + s.hash = 0 + for i in range(n): + s.chars[i] = unichr(ord('A') + i) + return s.gethash() - hash(u'ABCDE') + + res = self.interpret(f, [5]) + assert res == 0 + class TestOOtype(BaseTestRUnicode, OORtypeMixin): EMPTY_STRING_HASH = 0 From arigo at codespeak.net Mon May 11 14:23:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 14:23:44 +0200 (CEST) Subject: [pypy-svn] r65212 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/metainterp/test rlib Message-ID: <20090511122344.069A61684EC@codespeak.net> Author: arigo Date: Mon May 11 14:23:43 2009 New Revision: 65212 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.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_virtual.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py pypy/branch/pyjitpl5/pypy/rlib/jit.py Log: Use proper hashing in cast_whatever_to_int(). Use it for 'compiled_merge_point' too. The JIT should now be more or less ready to handle moving GCs. 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 Mon May 11 14:23:43 2009 @@ -355,7 +355,8 @@ # store the new_loop in compiled_merge_points too # XXX it's probably useless to do so when optimizing glob = metainterp_sd.globaldata - old_loops = glob.compiled_merge_points.setdefault(greenkey, []) + greenargs = glob.unpack_greenkey(greenkey) + old_loops = glob.compiled_merge_points.setdefault(greenargs, []) old_loops.append(new_loop) 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 Mon May 11 14:23:43 2009 @@ -591,22 +591,6 @@ def record(self, opnum, argboxes, resbox, descr=None): return None - -def mp_eq(greenkey1, greenkey2): - assert len(greenkey1) == len(greenkey2) - for i in range(len(greenkey1)): - g1 = greenkey1[i] - g2 = greenkey2[i] - if g1.get_() != g2.get_(): - return False - return True - -def mp_hash(greenkey): - h = 0x345678 - for g in greenkey: - h = (h ^ g.get_()) * 1000003 # XXX Boehm only - return intmask(h) - # ____________________________________________________________ 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 Mon May 11 14:23:43 2009 @@ -875,7 +875,6 @@ self.cpu = cpu self.stats = stats self.options = options - self.globaldata = MetaInterpGlobalData() RESULT = portal_graph.getreturnvar().concretetype self.result_type = history.getkind(RESULT) @@ -910,6 +909,11 @@ def _freeze_(self): return True + def finish_setup(self, num_green_args, state): + self.num_green_args = num_green_args + self.state = state + self.globaldata = MetaInterpGlobalData(self) + def _setup_once(self): """Runtime setup needed by the various components of the JIT.""" if not self.globaldata.initialized: @@ -949,11 +953,22 @@ # ____________________________________________________________ class MetaInterpGlobalData(object): - def __init__(self): + def __init__(self, staticdata): self._debug_history = [] - self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash) - # { greenkey: list-of-MergePoints } self.initialized = False + # + state = staticdata.state + if state is not None: + self.unpack_greenkey = state.unwrap_greenkey + def mp_eq(greenargs1, greenargs2): + return state.comparekey(greenargs1, greenargs2) + def mp_hash(greenargs): + return intmask(state.getkeyhash(*greenargs)) + self.compiled_merge_points = r_dict(mp_eq, mp_hash) + # { (greenargs): [MergePoints] } + else: + self.compiled_merge_points = {} # for tests only; not RPython + self.unpack_greenkey = tuple # ____________________________________________________________ @@ -1217,7 +1232,8 @@ self.history.inputargs = original_boxes[num_green_args:] greenkey = original_boxes[:num_green_args] glob = self.staticdata.globaldata - old_loops = glob.compiled_merge_points.setdefault(greenkey, []) + greenargs = glob.unpack_greenkey(greenkey) + old_loops = glob.compiled_merge_points.setdefault(greenargs, []) self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) loop = compile.compile_new_loop(self, old_loops, greenkey, start) assert loop is not None @@ -1229,8 +1245,9 @@ num_green_args = self.staticdata.num_green_args greenkey = live_arg_boxes[:num_green_args] glob = self.staticdata.globaldata + greenargs = glob.unpack_greenkey(greenkey) try: - old_loops = glob.compiled_merge_points[greenkey] + old_loops = glob.compiled_merge_points[greenargs] except KeyError: return self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None) 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 Mon May 11 14:23:43 2009 @@ -24,8 +24,8 @@ graph = rtyper.annotator.translator.graphs[0] opt = history.Options(specialize=False, listops=listops) metainterp_sd = pyjitpl.MetaInterpStaticData(graph, [], cpu, stats, opt) + metainterp_sd.finish_setup(0, None) metainterp = pyjitpl.MetaInterp(metainterp_sd) - metainterp.num_green_args = 0 return metainterp, rtyper class JitMixin: 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 Mon May 11 14:23:43 2009 @@ -490,7 +490,10 @@ jitdriver = JitDriver(greens = ['p', 'code'], reds = ['i', 'j', 'total']) - codes = [[], [0, 0, 1, 1]] + class Code: + def __init__(self, lst): + self.lst = lst + codes = [Code([]), Code([0, 0, 1, 1])] def interpret(num): code = codes[num] @@ -498,10 +501,10 @@ i = 0 j = 0 total = 0 - while p < len(code): + while p < len(code.lst): jitdriver.jit_merge_point(code=code, p=p, i=i, j=j, total=total) total += i - e = code[p] + e = code.lst[p] if e == 0: p += 1 elif e == 1: 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 Mon May 11 14:23:43 2009 @@ -171,21 +171,25 @@ assert res == 9 def test_immutable_constant_getfield(self): - myjitdriver = JitDriver(greens = ['stuff'], reds = ['n', 'i']) + myjitdriver = JitDriver(greens = ['stufflist'], reds = ['n', 'i']) class Stuff(object): _immutable_ = True def __init__(self, x): self.x = x + + class StuffList(object): + _immutable_ = True def f(n, a, i): - stuff = [Stuff(a), Stuff(3)] + stufflist = StuffList() + stufflist.lst = [Stuff(a), Stuff(3)] while n > 0: - myjitdriver.can_enter_jit(n=n, i=i, stuff=stuff) - myjitdriver.jit_merge_point(n=n, i=i, stuff=stuff) + myjitdriver.can_enter_jit(n=n, i=i, stufflist=stufflist) + myjitdriver.jit_merge_point(n=n, i=i, stufflist=stufflist) i = hint(i, promote=True) v = Stuff(i) - n -= stuff[v.x].x + n -= stufflist.lst[v.x].x return n res = self.meta_interp(f, [10, 1, 0], listops=True) 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 Mon May 11 14:23:43 2009 @@ -7,7 +7,7 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem import lltype def fn(x): - return cast_whatever_to_int(lltype.typeOf(x), x, None) + return cast_whatever_to_int(lltype.typeOf(x), x) for type_system in ('lltype', 'ootype'): res = interpret(fn, [42], type_system=type_system) assert res == 42 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 Mon May 11 14:23:43 2009 @@ -1,5 +1,5 @@ import sys -from pypy.rpython.lltypesystem import lltype, llmemory, rclass +from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.annlowlevel import llhelper, MixLevelHelperAnnotator,\ cast_base_ptr_to_instance @@ -132,8 +132,7 @@ self.make_enter_function() self.rewrite_can_enter_jit() self.add_profiler_finish() - self.metainterp_sd.num_green_args = self.num_green_args - self.metainterp_sd.state = self.state + self.metainterp_sd.finish_setup(self.num_green_args, self.state) def finish(self): if self.cpu.translate_support_code: @@ -480,10 +479,18 @@ return lltype.cast_primitive(TYPE, box.getint()) unwrap._annspecialcase_ = 'specialize:arg(0)' -def cast_whatever_to_int(TYPE, x, cpu): +def equal_whatever(TYPE, x, y): if isinstance(TYPE, lltype.Ptr): - # XXX moving GCs...? - return cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + if TYPE.TO is rstr.STR or TYPE.TO is rstr.UNICODE: + return rstr.LLHelpers.ll_streq(x, y) + return x == y +equal_whatever._annspecialcase_ = 'specialize:arg(0)' + +def cast_whatever_to_int(TYPE, x): + if isinstance(TYPE, lltype.Ptr): + # only supports strings, unicodes and regular instances *with a hash + # cache*. The 'jit_merge_point' hint forces a hash cache to appear. + return x.gethash() elif TYPE is ootype.String or TYPE is ootype.Unicode: return ootype.oohash(x) elif isinstance(TYPE, ootype.OOType): @@ -639,6 +646,23 @@ return metainterp.compile_and_run_once(*args) handle_hash_collision._dont_inline_ = True + def unwrap_greenkey(self, greenkey): + greenargs = () + i = 0 + for TYPE in green_args_spec: + value = unwrap(TYPE, greenkey[i]) + greenargs += (value,) + i += 1 + return greenargs + + def comparekey(self, greenargs1, greenargs2): + i = 0 + for TYPE in green_args_spec: + if not equal_whatever(TYPE, greenargs1[i], greenargs2[i]): + return False + return True + comparekey._always_inline_ = True + def getkeyhash(self, *greenargs): result = r_uint(0x345678) i = 0 @@ -648,8 +672,7 @@ result = result * mult mult = mult + 82520 + 2*len(greenargs) item = greenargs[i] - result = result ^ cast_whatever_to_int(TYPE, item, - warmrunnerdesc.cpu) + result = result ^ cast_whatever_to_int(TYPE, item) i = i + 1 return result & self.hashtablemask getkeyhash._always_inline_ = True @@ -659,12 +682,7 @@ return key.counter >= self.trace_eagerness def attach_unoptimized_bridge_from_interp(self, greenkey, bridge): - greenargs = () - i = 0 - for TYPE in green_args_spec: - value = unwrap(TYPE, greenkey[i]) - greenargs += (value,) - i += 1 + greenargs = self.unwrap_greenkey(greenkey) newcell = MachineCodeEntryPoint(bridge, *greenargs) argshash = self.getkeyhash(*greenargs) cell = self.cells[argshash] Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/jit.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/jit.py Mon May 11 14:23:43 2009 @@ -261,6 +261,9 @@ "arguments: %s" % (self.instance, expected)) driver._emulate_method_calls(self.bookkeeper, kwds_s) + for name in driver.greens: + s_green_key = kwds_s['s_' + name] + s_green_key.hash() # force the hash cache to appear return annmodel.s_None def specialize_call(self, hop, **kwds_i): From jandem at codespeak.net Mon May 11 15:06:49 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Mon, 11 May 2009 15:06:49 +0200 (CEST) Subject: [pypy-svn] r65213 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090511130649.223A61684ED@codespeak.net> Author: jandem Date: Mon May 11 15:06:47 2009 New Revision: 65213 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Add Array.prototype.sort. Two Array tests failures remaining (missing Date and a lexer bug) Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Mon May 11 15:06:47 2009 @@ -37,7 +37,7 @@ 'in': operations.In, } UNOP_TO_CLS = { - #'~': operations.BitwiseNot, + '~': operations.BitwiseNot, '!': operations.Not, '+': operations.UPlus, '-': operations.UMinus, Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Mon May 11 15:06:47 2009 @@ -13,6 +13,7 @@ from pypy.lang.js.jscode import JsCode from pypy.rlib.rarithmetic import NAN, INFINITY, isnan, isinf, r_uint from pypy.rlib.objectmodel import specialize +from pypy.rlib.listsort import TimSort ASTBUILDER = ASTBuilder() @@ -522,6 +523,7 @@ return sep.join(l) class W_ArrayToString(W_NewBuiltin): + length = 0 def Call(self, ctx, args=[], this=None): return W_String(common_join(ctx, this, sep=',')) @@ -558,6 +560,70 @@ return this +class Sorter(TimSort): + def __init__(self, list, listlength=None, compare_fn=None, ctx=None): + TimSort.__init__(self, list, listlength) + self.compare_fn = compare_fn + self.ctx = ctx + + def lt(self, a, b): + if self.compare_fn: + result = self.compare_fn.Call(self.ctx, [a, b]).ToInt32(self.ctx) + return result == -1 + return a.ToString(self.ctx) < b.ToString(self.ctx) + +class W_ArraySort(W_NewBuiltin): + length = 1 + #XXX: further optimize this function + def Call(self, ctx, args=[], this=None): + length = this.Get(ctx, 'length').ToUInt32(ctx) + + # According to ECMA-262 15.4.4.11, non-existing properties always come after + # existing values. Undefined is always greater than any other value. + # So we create a list of non-undefined values, sort them, and append undefined again. + values = [] + undefs = r_uint(0) + + for i in range(length): + P = str(i) + + if not this.HasProperty(P): + # non existing property + continue + + obj = this.Get(ctx, str(i)) + if obj is w_Undefined: + undefs += 1 + continue + + values.append(obj) + + # sort all values + if len(args) > 0: + sorter = Sorter(values, compare_fn=args[0], ctx=ctx) + else: + sorter = Sorter(values, ctx=ctx) + sorter.sort() + + # put sorted values back + values = sorter.list + for i in range(len(values)): + this.Put(ctx, str(i), values[i]) + + # append undefined values + newlength = len(values) + while undefs > 0: + undefs -= 1 + this.Put(ctx, str(newlength), w_Undefined) + newlength += 1 + + # delete non-existing elements on the end + while length > newlength: + this.Delete(str(newlength)) + newlength += 1 + + return this + class W_DateFake(W_NewBuiltin): # XXX This is temporary def Call(self, ctx, args=[], this=None): return create_object(ctx, 'Object') @@ -710,6 +776,7 @@ 'toString': W_ArrayToString(ctx), 'join': W_ArrayJoin(ctx), 'reverse': W_ArrayReverse(ctx), + 'sort': W_ArraySort(ctx), }) w_Array.Put(ctx, 'prototype', w_ArrPrototype, flags = allon) From jandem at codespeak.net Mon May 11 15:11:52 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Mon, 11 May 2009 15:11:52 +0200 (CEST) Subject: [pypy-svn] r65214 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090511131152.197B01684EC@codespeak.net> Author: jandem Date: Mon May 11 15:11:51 2009 New Revision: 65214 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Ignore undefined argument remove some whitespace Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Mon May 11 15:11:51 2009 @@ -586,20 +586,17 @@ for i in range(length): P = str(i) - if not this.HasProperty(P): # non existing property continue - obj = this.Get(ctx, str(i)) if obj is w_Undefined: undefs += 1 continue - values.append(obj) # sort all values - if len(args) > 0: + if len(args) > 0 and args[0] is not w_Undefined: sorter = Sorter(values, compare_fn=args[0], ctx=ctx) else: sorter = Sorter(values, ctx=ctx) @@ -621,7 +618,6 @@ while length > newlength: this.Delete(str(newlength)) newlength += 1 - return this class W_DateFake(W_NewBuiltin): # XXX This is temporary From arigo at codespeak.net Mon May 11 16:07:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 16:07:39 +0200 (CEST) Subject: [pypy-svn] r65215 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090511140739.3493D168517@codespeak.net> Author: arigo Date: Mon May 11 16:07:37 2009 New Revision: 65215 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Use the full range of integers for the hash in pyjitpl:mp_hash(). Only mask with 'hashtablemask' when useful. 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 Mon May 11 16:07:37 2009 @@ -584,7 +584,7 @@ def maybe_compile_and_run(self, *args): # get the greenargs and look for the cell corresponding to the hash greenargs = args[:num_green_args] - argshash = self.getkeyhash(*greenargs) + argshash = self.getkeyhash(*greenargs) & self.hashtablemask cell = self.cells[argshash] if isinstance(cell, Counter): # update the profiling counter @@ -674,7 +674,7 @@ item = greenargs[i] result = result ^ cast_whatever_to_int(TYPE, item) i = i + 1 - return result & self.hashtablemask + return result getkeyhash._always_inline_ = True def must_compile_from_failure(self, key): @@ -684,7 +684,7 @@ def attach_unoptimized_bridge_from_interp(self, greenkey, bridge): greenargs = self.unwrap_greenkey(greenkey) newcell = MachineCodeEntryPoint(bridge, *greenargs) - argshash = self.getkeyhash(*greenargs) + argshash = self.getkeyhash(*greenargs) & self.hashtablemask cell = self.cells[argshash] if not isinstance(cell, Counter): while True: From jandem at codespeak.net Mon May 11 17:05:11 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Mon, 11 May 2009 17:05:11 +0200 (CEST) Subject: [pypy-svn] r65216 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090511150511.AD63A1684EB@codespeak.net> Author: jandem Date: Mon May 11 17:05:10 2009 New Revision: 65216 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsgrammar.txt pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: Add continue statement and a small grammar fix. Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Mon May 11 17:05:10 2009 @@ -433,6 +433,14 @@ target = None return operations.Break(pos, target) + def visit_continuestatement(self, node): + pos = self.get_pos(node) + if len(node.children) > 0: + target = self.dispatch(node.children[0]) + else: + target = None + return operations.Continue(pos, target) + def visit_returnstatement(self, node): pos = self.get_pos(node) if len(node.children) > 0: Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Mon May 11 17:05:10 2009 @@ -84,6 +84,7 @@ self.has_labels = True self.startlooplabel = [] self.endlooplabel = [] + self.updatelooplabel = [] self.stack = [] def emit_label(self, num = -1): @@ -96,6 +97,11 @@ num = self.emit_label() self.startlooplabel.append(num) return num + + def emit_startloop_label(self): + num = self.emit_label() + self.startlooplabel.append(num) + return num def prealocate_label(self): num = self.label_count @@ -107,11 +113,20 @@ self.endlooplabel.append(num) return num + def prealocate_updateloop_label(self): + num = self.prealocate_label() + self.updatelooplabel.append(num) + return num + def emit_endloop_label(self, label): self.endlooplabel.pop() self.startlooplabel.pop() self.emit_label(label) + def emit_updateloop_label(self, label): + self.updatelooplabel.pop() + self.emit_label(label) + def emit_break(self): if not self.endlooplabel: raise ThrowException(W_String("Break outside loop")) @@ -120,7 +135,7 @@ def emit_continue(self): if not self.startlooplabel: raise ThrowError(W_String("Continue outside loop")) - self.emit('JUMP', self.startlooplabel[-1]) + self.emit('JUMP', self.updatelooplabel[-1]) def emit(self, operation, *args): opcode = getattr(opcodes, operation)(*args) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsgrammar.txt ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsgrammar.txt (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsgrammar.txt Mon May 11 17:05:10 2009 @@ -191,10 +191,10 @@ | ; -SINGLESTRING : "'([^'\\]|\\(\"|'|\\|n|r|b|f|u|t|v))*'" +SINGLESTRING : "'([^'\\]|\\.)*'" ; -DOUBLESTRING : "\"([^\"\\]|\\(\"|'|\\|n|r|b|f|u|t|v))*\"" +DOUBLESTRING : "\"([^\"\\]|\\.)*\"" ; primaryexpression : "this" Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Mon May 11 17:05:10 2009 @@ -571,7 +571,9 @@ for c in internalstring: if last == "\\": - unescapeseq = unescapedict[last+c] + # Lookup escape sequence. Ignore the backslash for + # unknown escape sequences (like SM) + unescapeseq = unescapedict.get(last+c, c) temp.append(unescapeseq) c = ' ' # Could be anything elif c != "\\": @@ -813,9 +815,11 @@ bytecode.emit('POP') precond = bytecode.emit_startloop_label() finish = bytecode.prealocate_endloop_label() + update = bytecode.prealocate_updateloop_label() self.condition.emit(bytecode) bytecode.emit('JUMP_IF_FALSE', finish) self.body.emit(bytecode) + bytecode.emit_updateloop_label(update) self.update.emit(bytecode) bytecode.emit('POP') bytecode.emit('JUMP', precond) From jandem at codespeak.net Mon May 11 17:05:45 2009 From: jandem at codespeak.net (jandem at codespeak.net) Date: Mon, 11 May 2009 17:05:45 +0200 (CEST) Subject: [pypy-svn] r65217 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20090511150545.168D31684ED@codespeak.net> Author: jandem Date: Mon May 11 17:05:44 2009 New Revision: 65217 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: Add stub for Date, all Array tests pass :) Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Mon May 11 17:05:44 2009 @@ -620,12 +620,12 @@ newlength += 1 return this -class W_DateFake(W_NewBuiltin): # XXX This is temporary +class W_DateObject(W_NativeObject): def Call(self, ctx, args=[], this=None): return create_object(ctx, 'Object') def Construct(self, ctx, args=[]): - return create_object(ctx, 'Object') + return create_object(ctx, 'Date', Value = W_FloatNumber(0.0)) def pypy_repr(ctx, repr, w_arg): return W_String(w_arg.__class__.__name__) @@ -802,7 +802,18 @@ w_Global.Put(ctx, 'version', W_Builtin(versionjs), flags=allon) #Date - w_Date = W_DateFake(ctx, Class='Date') + w_Date = W_DateObject('Date', w_FncPrototype) + + w_DatePrototype = create_object(ctx, 'Object', Value=W_String('')) + w_DatePrototype.Class = 'Date' + + put_values(ctx, w_DatePrototype, { + '__proto__': w_DatePrototype, + 'valueOf': get_value_of('Date')(ctx), + }) + + w_Date.Put(ctx, 'prototype', w_DatePrototype, flags=allon) + w_Global.Put(ctx, 'Date', w_Date) w_Global.Put(ctx, 'NaN', W_FloatNumber(NAN), flags = DE|DD) From arigo at codespeak.net Mon May 11 18:07:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 18:07:00 +0200 (CEST) Subject: [pypy-svn] r65218 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090511160700.E8649168579@codespeak.net> Author: arigo Date: Mon May 11 18:06:59 2009 New Revision: 65218 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Fix optimize.py to call getnode() on all arguments, just to make sure the nodes are created. 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 May 11 18:06:59 2009 @@ -394,10 +394,11 @@ instnode.allfields = op.vdesc.fields continue elif op.is_always_pure(): + is_pure = True for arg in op.args: if not self.getnode(arg).const: - break - else: + is_pure = False + if is_pure: box = op.result assert box is not None self.nodes[box] = InstanceNode(box.constbox(), From arigo at codespeak.net Mon May 11 18:12:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 18:12:58 +0200 (CEST) Subject: [pypy-svn] r65219 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090511161258.5D0C216853A@codespeak.net> Author: arigo Date: Mon May 11 18:12:57 2009 New Revision: 65219 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Don't use UnboxedValue any more. The current approach is only sightly more indirect (after translation), but it probably makes little time difference. 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 Mon May 11 18:12:57 2009 @@ -960,11 +960,7 @@ state = staticdata.state if state is not None: self.unpack_greenkey = state.unwrap_greenkey - def mp_eq(greenargs1, greenargs2): - return state.comparekey(greenargs1, greenargs2) - def mp_hash(greenargs): - return intmask(state.getkeyhash(*greenargs)) - self.compiled_merge_points = r_dict(mp_eq, mp_hash) + self.compiled_merge_points = r_dict(state.comparekey,state.hashkey) # { (greenargs): [MergePoints] } else: self.compiled_merge_points = {} # for tests only; not RPython 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 Mon May 11 18:12:57 2009 @@ -11,7 +11,7 @@ from pypy.rlib.objectmodel import we_are_translated, UnboxedValue, specialize from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.jit import PARAMETERS -from pypy.rlib.rarithmetic import r_uint +from pypy.rlib.rarithmetic import r_uint, intmask from pypy.rlib.debug import debug_print from pypy.rpython.lltypesystem.lloperation import llop from pypy.translator.simplify import get_funcobj, get_functype @@ -59,6 +59,7 @@ warmrunnerdesc = WarmRunnerDesc(translator, **kwds) warmrunnerdesc.state.set_param_threshold(3) # for tests warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests + warmrunnerdesc.state.create_tables_now() # for tests if hash_bits: warmrunnerdesc.state.set_param_hash_bits(hash_bits) warmrunnerdesc.finish() @@ -507,31 +508,28 @@ warmrunnerdesc.num_green_args = num_green_args green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec) green_args_names = unrolling_iterable(jitdriver.greens) + green_args_spec_names = unrolling_iterable(zip( + warmrunnerdesc.green_args_spec, jitdriver.greens)) red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types) if num_green_args: MAX_HASH_TABLE_BITS = 28 else: - MAX_HASH_TABLE_BITS = 0 - THRESHOLD_MAX = (sys.maxint-1) / 2 + MAX_HASH_TABLE_BITS = 1 + THRESHOLD_LIMIT = sys.maxint // 2 - class StateCell(object): - __slots__ = [] - - class Counter(StateCell, UnboxedValue): - __slots__ = 'counter' - - class MachineCodeEntryPoint(StateCell): + class MachineCodeEntryPoint(object): + next = None # linked list def __init__(self, bridge, *greenargs): self.bridge = bridge - self.next = Counter(0) i = 0 for name in green_args_names: setattr(self, 'green_' + name, greenargs[i]) i = i + 1 def equalkey(self, *greenargs): i = 0 - for name in green_args_names: - if getattr(self, 'green_' + name) != greenargs[i]: + for TYPE, name in green_args_spec_names: + myvalue = getattr(self, 'green_' + name) + if not equal_whatever(TYPE, myvalue, greenargs[i]): return False i = i + 1 return True @@ -561,47 +559,60 @@ meth(default_value) def set_param_threshold(self, threshold): - if threshold > THRESHOLD_MAX: - threshold = THRESHOLD_MAX - self.threshold = threshold + if threshold < 2: + threshold = 2 + self.increment_threshold = (THRESHOLD_LIMIT // threshold) + 1 + # the number is at least 1, and at most about half THRESHOLD_LIMIT def set_param_trace_eagerness(self, value): self.trace_eagerness = value def set_param_hash_bits(self, value): - if value < 0: - value = 0 + if value < 1: + value = 1 elif value > MAX_HASH_TABLE_BITS: value = MAX_HASH_TABLE_BITS - self.cells = [Counter(0)] * (1 << value) - self.hashtablemask = (1 << value) - 1 - - # Only use the hash of the arguments as the profiling key. - # Indeed, this is all a heuristic, so if things are designed - # correctly, the occasional mistake due to hash collision is - # not too bad. + # the tables are initialized with the correct size only in + # attach_unoptimized_bridge_from_interp() + self.hashbits = value + self.hashtablemask = 0 + self.mccounters = [0] + self.mcentrypoints = [None] + # invariant: (self.mccounters[j] < 0) if and only if + # (self.mcentrypoints[j] is not None) + + def create_tables_now(self): + count = 1 << self.hashbits + self.hashtablemask = count - 1 + self.mccounters = [0] * count + self.mcentrypoints = [None] * count + + # Only use the hash of the arguments as the profiling key. + # Indeed, this is all a heuristic, so if things are designed + # correctly, the occasional mistake due to hash collision is + # not too bad. def maybe_compile_and_run(self, *args): # get the greenargs and look for the cell corresponding to the hash greenargs = args[:num_green_args] argshash = self.getkeyhash(*greenargs) & self.hashtablemask - cell = self.cells[argshash] - if isinstance(cell, Counter): + counter = self.mccounters[argshash] + if counter >= 0: # update the profiling counter - n = cell.counter + 1 - if n < self.threshold: - #if hotrunnerdesc.verbose_level >= 3: - # interp.debug_trace("jit_not_entered", *args) - self.cells[argshash] = Counter(n) + n = counter + self.increment_threshold + if n <= THRESHOLD_LIMIT: # bound not reached + self.mccounters[argshash] = n + return + if self.hashtablemask == 0: # must really create the tables now + self.create_tables_now() return - #interp.debug_trace("jit_compile", *greenargs) metainterp_sd = warmrunnerdesc.metainterp_sd metainterp = MetaInterp(metainterp_sd) loop = metainterp.compile_and_run_once(*args) else: # machine code was already compiled for these greenargs # (or we have a hash collision) - assert isinstance(cell, MachineCodeEntryPoint) + cell = self.mcentrypoints[argshash] if not cell.equalkey(*greenargs): # hash collision loop = self.handle_hash_collision(cell, argshash, *args) @@ -621,25 +632,27 @@ loop = fail_op.descr.handle_fail_op(metainterp_sd, fail_op) maybe_compile_and_run._dont_inline_ = True - def handle_hash_collision(self, cell, argshash, *args): + def handle_hash_collision(self, firstcell, argshash, *args): greenargs = args[:num_green_args] - next = cell.next - while not isinstance(next, Counter): - assert isinstance(next, MachineCodeEntryPoint) - if next.equalkey(*greenargs): + # search the linked list for the correct cell + cell = firstcell + while cell.next is not None: + nextcell = cell.next + if nextcell.equalkey(*greenargs): # found, move to the front of the linked list - cell.next = next.next - next.next = self.cells[argshash] - self.cells[argshash] = next + cell.next = nextcell.next + nextcell.next = firstcell + self.mcentrypoints[argshash] = nextcell cpu = warmrunnerdesc.metainterp_sd.cpu - next.set_future_values(cpu, *args[num_green_args:]) - return next.bridge - cell = next - next = cell.next + nextcell.set_future_values(cpu, *args[num_green_args:]) + return nextcell.bridge + cell = nextcell # not found at all, do profiling - n = next.counter + 1 - if n < self.threshold: - cell.next = Counter(n) + counter = self.mccounters[argshash] + assert counter < 0 # by invariant + n = counter + self.increment_threshold + if n < 0: # bound not reached + self.mccounters[argshash] = n return None metainterp_sd = warmrunnerdesc.metainterp_sd metainterp = MetaInterp(metainterp_sd) @@ -652,18 +665,23 @@ for TYPE in green_args_spec: value = unwrap(TYPE, greenkey[i]) greenargs += (value,) - i += 1 + i = i + 1 return greenargs + unwrap_greenkey._always_inline_ = True - def comparekey(self, greenargs1, greenargs2): + def comparekey(greenargs1, greenargs2): i = 0 for TYPE in green_args_spec: if not equal_whatever(TYPE, greenargs1[i], greenargs2[i]): return False return True - comparekey._always_inline_ = True + comparekey = staticmethod(comparekey) + + def hashkey(greenargs): + return intmask(WarmEnterState.getkeyhash(*greenargs)) + hashkey = staticmethod(hashkey) - def getkeyhash(self, *greenargs): + def getkeyhash(*greenargs): result = r_uint(0x345678) i = 0 mult = r_uint(1000003) @@ -674,8 +692,9 @@ item = greenargs[i] result = result ^ cast_whatever_to_int(TYPE, item) i = i + 1 - return result + return result # returns a r_uint getkeyhash._always_inline_ = True + getkeyhash = staticmethod(getkeyhash) def must_compile_from_failure(self, key): key.counter += 1 @@ -685,16 +704,9 @@ greenargs = self.unwrap_greenkey(greenkey) newcell = MachineCodeEntryPoint(bridge, *greenargs) argshash = self.getkeyhash(*greenargs) & self.hashtablemask - cell = self.cells[argshash] - if not isinstance(cell, Counter): - while True: - assert isinstance(cell, MachineCodeEntryPoint) - next = cell.next - if isinstance(next, Counter): - cell.next = Counter(0) - break - cell = next - newcell.next = self.cells[argshash] - self.cells[argshash] = newcell + oldcell = self.mcentrypoints[argshash] + newcell.next = oldcell # link + self.mcentrypoints[argshash] = newcell + self.mccounters[argshash] = -THRESHOLD_LIMIT-1 return WarmEnterState From arigo at codespeak.net Mon May 11 18:15:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 18:15:48 +0200 (CEST) Subject: [pypy-svn] r65220 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090511161548.7BEC716853A@codespeak.net> Author: arigo Date: Mon May 11 18:15:47 2009 New Revision: 65220 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Log: Shut off a warning. 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 Mon May 11 18:15:47 2009 @@ -102,6 +102,9 @@ def sort_key(self): raise NotImplementedError + def set_future_value(self, cpu, j): + raise NotImplementedError + def repr_rpython(self): return '%s' % self From arigo at codespeak.net Mon May 11 18:33:12 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 18:33:12 +0200 (CEST) Subject: [pypy-svn] r65221 - in pypy/branch/pyjitpl5/pypy: config jit/backend/llgraph jit/backend/minimal jit/backend/x86 jit/backend/x86/test jit/metainterp jit/metainterp/test Message-ID: <20090511163312.285C9168479@codespeak.net> Author: arigo Date: Mon May 11 18:33:10 2009 New Revision: 65221 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.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: Start supporting the framework GC in addition to Boehm. Infrastructure work only; future work is described in backend/x86/TODO. Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/config/translationoption.py (original) +++ pypy/branch/pyjitpl5/pypy/config/translationoption.py Mon May 11 18:33:10 2009 @@ -111,9 +111,9 @@ # JIT generation BoolOption("jit", "generate a JIT", default=False, cmdline="--jit", - requires=[("translation.gc", "boehm"), - ("translation.list_comprehension_operations", True), - ("translation.thread", False)]), + requires=[("translation.thread", False)], + suggests=[("translation.gc", "boehm"), # for now + ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", ["auto", "minimal", "x86"], default="auto", cmdline="--jit-backend"), 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 Mon May 11 18:33:10 2009 @@ -69,7 +69,7 @@ class BaseCPU(model.AbstractCPU): def __init__(self, rtyper, stats=None, translate_support_code=False, - annmixlevel=None): + annmixlevel=None, gcdescr=None): self.rtyper = rtyper self.translate_support_code = translate_support_code self.stats = stats or MiniStats() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Mon May 11 18:33:10 2009 @@ -30,7 +30,7 @@ class BaseCPU(model.AbstractCPU): def __init__(self, rtyper, stats, translate_support_code=False, - mixlevelann=None): + mixlevelann=None, gcdescr=None): self.rtyper = rtyper if rtyper: if self.is_oo: 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 Mon May 11 18:33:10 2009 @@ -10,3 +10,13 @@ * optimization of comparison followed by a guard * MC_SIZE, FRAMESIZE + + +Support for non-Boehm GCs: + +* support calls to malloc and malloc_varsize from the generated assembler + +* support root stack enumeration (at first, the easiest is probably to + do it with asmgcc, which is good for performance :-) + +* support write_barriers (later; at first, we support the semispace gc only) 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 Mon May 11 18:33:10 2009 @@ -105,6 +105,7 @@ self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) self._exception_addr = 0 self.mcstack = MachineCodeStack() + self.gc_malloc_fn = gc_malloc_fnaddr(cpu.gcdescr) def _get_log(self): s = os.environ.get('PYPYJITLOG') @@ -144,10 +145,8 @@ self._exception_bck) self.mc = self.mcstack.next_mc() self.mc2 = self.mcstack.next_mc() - # the address of the function called by 'new': directly use - # Boehm's GC_malloc function. - if self.malloc_func_addr == 0: - self.malloc_func_addr = gc_malloc_fnaddr() + # the address of the function called by 'new' + self.malloc_func_addr = rffi.cast(lltype.Signed, self.gc_malloc_fn) def eventually_log_operations(self, inputargs, operations, memo=None, myid=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 Mon May 11 18:33:10 2009 @@ -72,9 +72,10 @@ BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed) def __init__(self, rtyper, stats, translate_support_code=False, - mixlevelann=None): + mixlevelann=None, gcdescr=None): self.rtyper = rtyper self.stats = stats + self.gcdescr = gcdescr self.translate_support_code = translate_support_code if translate_support_code: assert mixlevelann Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Mon May 11 18:33:10 2009 @@ -3,15 +3,30 @@ GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) -compilation_info = ExternalCompilationInfo(libraries=['gc']) -malloc_fn_ptr = rffi.llexternal("GC_malloc", - [lltype.Signed], # size_t, but good enough - llmemory.Address, - compilation_info=compilation_info, - sandboxsafe=True, - _nowrapper=True) - -def gc_malloc_fnaddr(): - """Returns the address of the Boehm 'malloc' function.""" - return rffi.cast(lltype.Signed, malloc_fn_ptr) +def gc_malloc__boehm(gcdescr): + """Returns a pointer to the Boehm 'malloc' function.""" + compilation_info = ExternalCompilationInfo(libraries=['gc']) + malloc_fn_ptr = rffi.llexternal("GC_malloc", + [lltype.Signed], # size_t, but good enough + llmemory.Address, + compilation_info=compilation_info, + sandboxsafe=True, + _nowrapper=True) + return malloc_fn_ptr + + +def gc_malloc__framework(gcdescr): + """Returns a pointer to the framework 'malloc' function.""" + return 0 # XXX write me! + + +def gc_malloc_fnaddr(gcdescr): + """Returns a pointer to the proper 'malloc' function.""" + name = gcdescr.config.translation.gctransformer + try: + func = globals()['gc_malloc__' + name] + except KeyError: + raise NotImplementedError("GC transformer %r not supported by " + "the x86 backend" % (name,)) + return func(gcdescr) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Mon May 11 18:33:10 2009 @@ -33,19 +33,30 @@ g._dont_inline_ = True def f(args): - r = g(3000) - rgc.collect(); rgc.collect(); rgc.collect() - print int(r() is None) + r_list = [] + for i in range(20): + r = g(1000) + r_list.append(r) + rgc.collect() + rgc.collect(); rgc.collect() + freed = 0 + for r in r_list: + if r() is None: + freed += 1 + print freed return 0 -def test_compile(): +def compile_and_run(gc, **kwds): from pypy.translator.translator import TranslationContext from pypy.jit.metainterp.warmspot import apply_jit from pypy.translator.c import genc # t = TranslationContext() - t.config.translation.jit = True # forces other options as well + t.config.translation.gc = gc + t.config.translation.jit = True + for name, value in kwds.items(): + setattr(t.config.translation, name, value) t.buildannotator().build_types(f, [int]) t.buildrtyper().specialize() apply_jit(t, CPUClass=CPU386) @@ -54,4 +65,16 @@ cbuilder.compile() # data = cbuilder.cmdexec('') - assert int(data.strip()) == 1 + res = int(data.strip()) + if gc == "boehm": + assert res >= 16 + else: + assert res == 20 + + +def test_compile_boehm(): + compile_and_run("boehm") + +def test_compile_semispace(): + # a moving GC, but with no write barrier + compile_and_run("semispace", gcrootfinder="asmgcc") 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 Mon May 11 18:33:10 2009 @@ -735,7 +735,10 @@ self.register_var(op.result) def serialize_op_zero_gc_pointers_inside(self, op): - pass # XXX assume Boehm for now + # XXX this is always a no-op for now + warmrunnerdesc = self.codewriter.metainterp_sd.warmrunnerdesc + if warmrunnerdesc is not None: + assert warmrunnerdesc.gcdescr.malloc_zero_filled def serialize_op_getfield(self, op): if self.is_typeptr_getset(op): Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py Mon May 11 18:33:10 2009 @@ -0,0 +1,42 @@ + + +class GcDescription: + def __init__(self, config): + self.config = config + + +class GC_boehm(GcDescription): + malloc_zero_filled = True + +class GC_semispace(GcDescription): + malloc_zero_filled = True + + +def get_description(config): + name = config.translation.gc + try: + cls = globals()['GC_' + name] + except KeyError: + raise NotImplementedError('GC %r not supported by the JIT' % (name,)) + return cls(config) + + +class GcDescription: + def __init__(self, config): + self.config = config + + +class GC_boehm(GcDescription): + malloc_zero_filled = True + +class GC_semispace(GcDescription): + malloc_zero_filled = True + + +def get_description(config): + name = config.translation.gc + try: + cls = globals()['GC_' + name] + except KeyError: + raise NotImplementedError('GC %r not supported by the JIT' % (name,)) + return cls(config) 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 Mon May 11 18:33:10 2009 @@ -867,7 +867,6 @@ # ____________________________________________________________ class MetaInterpStaticData(object): - num_green_args = 0 def __init__(self, portal_graph, graphs, cpu, stats, options, optimizer=None, profile=None): @@ -909,9 +908,14 @@ def _freeze_(self): return True - def finish_setup(self, num_green_args, state): - self.num_green_args = num_green_args - self.state = state + def finish_setup(self, warmrunnerdesc): + self.warmrunnerdesc = warmrunnerdesc + if warmrunnerdesc is not None: + self.num_green_args = warmrunnerdesc.num_green_args + self.state = warmrunnerdesc.state + else: + self.num_green_args = 0 + self.state = None self.globaldata = MetaInterpGlobalData(self) def _setup_once(self): 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 Mon May 11 18:33:10 2009 @@ -24,7 +24,7 @@ graph = rtyper.annotator.translator.graphs[0] opt = history.Options(specialize=False, listops=listops) metainterp_sd = pyjitpl.MetaInterpStaticData(graph, [], cpu, stats, opt) - metainterp_sd.finish_setup(0, None) + metainterp_sd.finish_setup(None) metainterp = pyjitpl.MetaInterp(metainterp_sd) return metainterp, rtyper @@ -523,6 +523,7 @@ inline_threshold=0, type_system=self.type_system) clear_tcache() translator = interp.typer.annotator.translator + translator.config.translation.gc = "boehm" warmrunnerdesc = WarmRunnerDesc(translator, CPUClass=self.CPUClass, optimizer=SimpleOptimizer) 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 Mon May 11 18:33:10 2009 @@ -17,7 +17,7 @@ from pypy.translator.simplify import get_funcobj, get_functype from pypy.translator.unsimplify import call_final_function -from pypy.jit.metainterp import support, history, pyjitpl +from pypy.jit.metainterp import support, history, pyjitpl, gc from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp from pypy.jit.metainterp.policy import JitPolicy from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper @@ -56,6 +56,7 @@ def jittify_and_run(interp, graph, args, repeat=1, hash_bits=None, **kwds): translator = interp.typer.annotator.translator + translator.config.translation.gc = "boehm" warmrunnerdesc = WarmRunnerDesc(translator, **kwds) warmrunnerdesc.state.set_param_threshold(3) # for tests warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests @@ -133,7 +134,7 @@ self.make_enter_function() self.rewrite_can_enter_jit() self.add_profiler_finish() - self.metainterp_sd.finish_setup(self.num_green_args, self.state) + self.metainterp_sd.finish_setup(self) def finish(self): if self.cpu.translate_support_code: @@ -149,6 +150,7 @@ else: assert translator.rtyper.type_system.name == 'ootypesystem' self.ts = OOTypeHelper() + self.gcdescr = gc.get_description(translator.config) def build_meta_interp(self, CPUClass=None, view="auto", translate_support_code=False, optimizer=None, @@ -162,7 +164,7 @@ else: annhelper = None cpu = CPUClass(self.translator.rtyper, self.stats, - translate_support_code, annhelper) + translate_support_code, annhelper, self.gcdescr) self.cpu = cpu graphs = self.translator.graphs self.jit_merge_point_pos = find_jit_merge_point(graphs) From arigo at codespeak.net Mon May 11 18:34:54 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 18:34:54 +0200 (CEST) Subject: [pypy-svn] r65222 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090511163454.2E6F3168479@codespeak.net> Author: arigo Date: Mon May 11 18:34:51 2009 New Revision: 65222 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py Log: Uh? This file was repeated, probably by a "patch" command when the file already existed. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py Mon May 11 18:34:51 2009 @@ -1,25 +1,6 @@ - - -class GcDescription: - def __init__(self, config): - self.config = config - - -class GC_boehm(GcDescription): - malloc_zero_filled = True - -class GC_semispace(GcDescription): - malloc_zero_filled = True - - -def get_description(config): - name = config.translation.gc - try: - cls = globals()['GC_' + name] - except KeyError: - raise NotImplementedError('GC %r not supported by the JIT' % (name,)) - return cls(config) - +""" +Support for the various GCs. +""" class GcDescription: def __init__(self, config): From arigo at codespeak.net Mon May 11 18:51:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 18:51:37 +0200 (CEST) Subject: [pypy-svn] r65223 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090511165137.38F831683E0@codespeak.net> Author: arigo Date: Mon May 11 18:51:35 2009 New Revision: 65223 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Log: Slight clean-up of the calls to malloc. 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 Mon May 11 18:51:35 2009 @@ -12,7 +12,6 @@ arg_pos, lower_byte, stack_pos) from pypy.rlib.objectmodel import we_are_translated, specialize, compute_unique_id from pypy.jit.backend.x86 import codebuf -from pypy.jit.backend.x86.support import gc_malloc_fnaddr from pypy.jit.backend.x86.ri386 import * from pypy.jit.metainterp.resoperation import rop @@ -105,8 +104,7 @@ self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) self._exception_addr = 0 self.mcstack = MachineCodeStack() - self.gc_malloc_fn = gc_malloc_fnaddr(cpu.gcdescr) - + def _get_log(self): s = os.environ.get('PYPYJITLOG') if not s: @@ -146,7 +144,8 @@ self.mc = self.mcstack.next_mc() self.mc2 = self.mcstack.next_mc() # the address of the function called by 'new' - self.malloc_func_addr = rffi.cast(lltype.Signed, self.gc_malloc_fn) + self.malloc_func_addr = rffi.cast(lltype.Signed, + self.cpu.gc_malloc_fn) def eventually_log_operations(self, inputargs, operations, memo=None, myid=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 Mon May 11 18:51:35 2009 @@ -17,8 +17,6 @@ from pypy.jit.backend.x86.support import gc_malloc_fnaddr from pypy.rlib.objectmodel import r_dict -GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) - VOID = 0 PTR = 1 INT = 2 @@ -103,6 +101,7 @@ self._setup_prebuilt_error('ovf', OverflowError) self._setup_prebuilt_error('zer', ZeroDivisionError) self.generated_mps = r_dict(const_descr_eq, const_descr_hash) + self.gc_malloc_fn = gc_malloc_fnaddr(gcdescr) def _setup_prebuilt_error(self, prefix, Class): if self.rtyper is not None: # normal case @@ -511,21 +510,22 @@ self._base_do_setfield(fielddescr, args[0].getint(), args[1]) def do_new(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.v[0]) - return BoxPtr(self.cast_int_to_gcref(res)) + res = self.gc_malloc_fn(descrsize.v[0]) + return BoxPtr(self.cast_adr_to_gcref(res)) def do_new_with_vtable(self, args, descrsize): - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(descrsize.v[0]) + res = self.gc_malloc_fn(descrsize.v[0]) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[0].getint() - return BoxPtr(self.cast_int_to_gcref(res)) + return BoxPtr(self.cast_adr_to_gcref(res)) def do_new_array(self, args, arraydescr): size_of_field, ofs, ptr = self.unpack_arraydescr(arraydescr) num_elem = args[0].getint() size = ofs + (1 << size_of_field) * num_elem - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) + res = self.gc_malloc_fn(size) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = num_elem - return BoxPtr(self.cast_int_to_gcref(res)) + # XXX don't use 0 above! + return BoxPtr(self.cast_adr_to_gcref(res)) def _new_do_newstr(TP): def do_newstr(self, args, descr=0): @@ -533,9 +533,9 @@ self.translate_support_code) num_elem = args[0].getint() size = basesize + num_elem * itemsize - res = rffi.cast(GC_MALLOC, gc_malloc_fnaddr())(size) + res = self.gc_malloc_fn(size) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem - return BoxPtr(self.cast_int_to_gcref(res)) + return BoxPtr(self.cast_adr_to_gcref(res)) return do_newstr do_newstr = _new_do_newstr(rstr.STR) do_newunicode = _new_do_newstr(rstr.UNICODE) @@ -663,7 +663,13 @@ return rffi.cast(lltype.Signed, x) def cast_int_to_gcref(self, x): - assert x == 0 or x > (1<<20) or x < (-1<<20) + if not we_are_translated(): + assert x == 0 or x > (1<<20) or x < (-1<<20) + return rffi.cast(llmemory.GCREF, x) + + def cast_adr_to_gcref(self, x): + if not we_are_translated(): + assert x == 0 or x > (1<<20) or x < (-1<<20) return rffi.cast(llmemory.GCREF, x) def uhex(x): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Mon May 11 18:51:35 2009 @@ -1,8 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.translator.tool.cbuild import ExternalCompilationInfo -GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) - def gc_malloc__boehm(gcdescr): """Returns a pointer to the Boehm 'malloc' function.""" @@ -23,7 +21,10 @@ def gc_malloc_fnaddr(gcdescr): """Returns a pointer to the proper 'malloc' function.""" - name = gcdescr.config.translation.gctransformer + if gcdescr is not None: + name = gcdescr.config.translation.gctransformer + else: + name = "boehm" try: func = globals()['gc_malloc__' + name] except KeyError: From arigo at codespeak.net Mon May 11 20:43:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 20:43:56 +0200 (CEST) Subject: [pypy-svn] r65225 - pypy/trunk/pypy/doc Message-ID: <20090511184356.9ED5216845C@codespeak.net> Author: arigo Date: Mon May 11 20:43:55 2009 New Revision: 65225 Modified: pypy/trunk/pypy/doc/translation.txt Log: Missing punctuation (thanks kirma). Modified: pypy/trunk/pypy/doc/translation.txt ============================================================================== --- pypy/trunk/pypy/doc/translation.txt (original) +++ pypy/trunk/pypy/doc/translation.txt Mon May 11 20:43:55 2009 @@ -485,7 +485,7 @@ function be inlined somewhere. This estimate is the sum of two numbers: for one every operations is assigned a specific weight, the default being a weight of one. Some operations are considered to be more effort than others, -e.g. memory allocation and calls others are considered to be no effort at all +e.g. memory allocation and calls; others are considered to be no effort at all (casts...). The size estimate is for one the sum of the weights of all operations occuring in the graph. This is called the "static instruction count". The other part of the size estimate of a graph is the "median From arigo at codespeak.net Mon May 11 22:09:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 22:09:14 +0200 (CEST) Subject: [pypy-svn] r65233 - in pypy/branch/pyjitpl5/pypy: jit/backend/x86 jit/backend/x86/test rpython/lltypesystem rpython/memory/gctransform Message-ID: <20090511200914.E8234168466@codespeak.net> Author: arigo Date: Mon May 11 22:09:13 2009 New Revision: 65233 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py - copied, changed from r65223, pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Removed: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py 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_zrpy_gc.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Log: In-progress: supporting other GCs in the x86 backend. 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 Mon May 11 22:09:13 2009 @@ -144,8 +144,8 @@ self.mc = self.mcstack.next_mc() self.mc2 = self.mcstack.next_mc() # the address of the function called by 'new' - self.malloc_func_addr = rffi.cast(lltype.Signed, - self.cpu.gc_malloc_fn) + ll_new = self.cpu.gc_ll_descr.get_funcptr_for_new() + self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new) def eventually_log_operations(self, inputargs, operations, memo=None, myid=0): @@ -164,8 +164,8 @@ op = operations[i] args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) if op.descr is not None and isinstance(op.descr, ConstDescr3): - descr = (str(op.descr.v[0]) + "," + str(op.descr.v[1]) + - "," + str(op.descr.v[2])) + descr = (str(op.descr.v0) + "," + str(op.descr.v1) + + "," + str(op.descr.flag2)) os.write(self._log_fd, "%d:%s %s[%s]\n" % (i, op.getopname(), args, descr)) else: @@ -541,17 +541,17 @@ def genop_new_with_vtable(self, op, arglocs, result_loc): assert result_loc is eax - loc_size, loc_vtable = arglocs - self.mc.PUSH(loc_vtable) - self.call(self.malloc_func_addr, [loc_size], eax) + loc_vtable = arglocs[-1] + assert isinstance(loc_vtable, IMM32) + arglocs = arglocs[:-1] + self.call(self.malloc_func_addr, arglocs, eax) # xxx ignore NULL returns for now - self.mc.POP(mem(eax, 0)) + self.mc.MOV(mem(eax, self.cpu.vtable_offset), loc_vtable) # same as malloc varsize after all def genop_new(self, op, arglocs, result_loc): assert result_loc is eax - loc_size = arglocs[0] - self.call(self.malloc_func_addr, [loc_size], eax) + self.call(self.malloc_func_addr, arglocs, eax) def genop_getfield_gc(self, op, arglocs, resloc): base_loc, ofs_loc, size_loc = arglocs Copied: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (from r65223, pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py) ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Mon May 11 22:09:13 2009 @@ -1,33 +1,126 @@ -from pypy.rpython.lltypesystem import lltype, llmemory, rffi +from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass +from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.annlowlevel import cast_base_ptr_to_instance from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.jit.backend.x86 import symbolic +from pypy.jit.backend.x86.runner import ConstDescr3 -def gc_malloc__boehm(gcdescr): - """Returns a pointer to the Boehm 'malloc' function.""" - compilation_info = ExternalCompilationInfo(libraries=['gc']) - malloc_fn_ptr = rffi.llexternal("GC_malloc", - [lltype.Signed], # size_t, but good enough - llmemory.Address, - compilation_info=compilation_info, - sandboxsafe=True, - _nowrapper=True) - return malloc_fn_ptr - - -def gc_malloc__framework(gcdescr): - """Returns a pointer to the framework 'malloc' function.""" - return 0 # XXX write me! +class GcLLDescription: + def __init__(self, gcdescr, mixlevelann): + self.gcdescr = gcdescr + def _freeze_(self): + return True + +# ____________________________________________________________ + +class GcLLDescr_boehm(GcLLDescription): + + def __init__(self, gcdescr, mixlevelann): + # grab a pointer to the Boehm 'malloc' function + compilation_info = ExternalCompilationInfo(libraries=['gc']) + malloc_fn_ptr = rffi.llexternal("GC_malloc", + [lltype.Signed], # size_t, but good enough + llmemory.GCREF, + compilation_info=compilation_info, + sandboxsafe=True, + _nowrapper=True) + self.funcptr_for_new = malloc_fn_ptr + + def sizeof(self, S, translate_support_code): + size = symbolic.get_size(S, translate_support_code) + return ConstDescr3(size, 0, False) + + def gc_malloc(self, descrsize): + assert isinstance(descrsize, ConstDescr3) + size = descrsize.v0 + return self.funcptr_for_new(size) + + def gc_malloc_array(self, arraydescr, num_elem): + assert isinstance(arraydescr, ConstDescr3) + size_of_field = arraydescr.v0 + ofs = arraydescr.v1 + size = ofs + (1 << size_of_field) * num_elem + return self.funcptr_for_new(size) + + def args_for_new(self, descrsize): + assert isinstance(descrsize, ConstDescr3) + size = descrsize.v0 + return [size] + + def get_funcptr_for_new(self): + return self.funcptr_for_new + +# ____________________________________________________________ + +class GcLLDescr_framework(GcLLDescription): + + def __init__(self, gcdescr, mixlevelann): + from pypy.rpython.memory.gc.base import choose_gc_from_config + from pypy.rpython.memory.gctransform import framework + self.translator = mixlevelann.rtyper.annotator.translator + + # make a TransformerLayoutBuilder and save it on the translator + # where it can be fished and reused by the FrameworkGCTransformer + self.layoutbuilder = framework.TransformerLayoutBuilder() + self.translator._transformerlayoutbuilder_from_jit = self.layoutbuilder + GCClass, _ = choose_gc_from_config(gcdescr.config) + + # make a malloc function, with three arguments + def getgc(): + ptr = llop.get_gc_pointer(rclass.OBJECTPTR) + return cast_base_ptr_to_instance(GCClass, ptr) + def malloc_basic(size, type_id, has_finalizer): + return getgc().malloc_fixedsize_clear(type_id, size, True, + has_finalizer, False) + self.malloc_basic = malloc_basic + self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType( + [lltype.Signed, lltype.Signed, lltype.Bool], llmemory.GCREF)) + + assert gcdescr.config.translation.gcrootfinder == "asmgcc", ( + "with the framework GCs, you must use" + " --gcrootfinder=asmgcc for now") + + def sizeof(self, S, translate_support_code): + from pypy.rpython.memory.gctypelayout import weakpointer_offset + assert translate_support_code, "required with the framework GC" + size = symbolic.get_size(S, True) + type_id = self.layoutbuilder.get_type_id(S) + has_finalizer = bool(self.layoutbuilder.has_finalizer(S)) + assert weakpointer_offset(S) == -1 # XXX + return ConstDescr3(size, type_id, has_finalizer) + + def gc_malloc(self, descrsize): + assert isinstance(descrsize, ConstDescr3) + size = descrsize.v0 + type_id = descrsize.v1 + has_finalizer = descrsize.flag2 + assert type_id > 0 + return self.malloc_basic(size, type_id, has_finalizer) + + def gc_malloc_array(self, arraydescr, num_elem): + raise NotImplementedError + + def args_for_new(self, descrsize): + assert isinstance(descrsize, ConstDescr3) + size = descrsize.v0 + type_id = descrsize.v1 + has_finalizer = descrsize.flag2 + return [size, type_id, has_finalizer] + def get_funcptr_for_new(self): + return llhelper(self.GC_MALLOC_BASIC, self.malloc_basic) -def gc_malloc_fnaddr(gcdescr): - """Returns a pointer to the proper 'malloc' function.""" +# ____________________________________________________________ + +def get_ll_description(gcdescr, mixlevelann): if gcdescr is not None: name = gcdescr.config.translation.gctransformer else: name = "boehm" try: - func = globals()['gc_malloc__' + name] + cls = globals()['GcLLDescr_' + name] except KeyError: raise NotImplementedError("GC transformer %r not supported by " "the x86 backend" % (name,)) - return func(gcdescr) + return cls(gcdescr, mixlevelann) 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 May 11 22:09:13 2009 @@ -885,15 +885,16 @@ def consider_new(self, op, ignored): from pypy.jit.backend.x86.runner import ConstDescr3 - descr = op.descr - assert isinstance(descr, ConstDescr3) - return self._call(op, [imm(descr.v[0])]) + args = self.assembler.cpu.gc_ll_descr.args_for_new(op.descr) + arglocs = [imm(x) for x in args] + return self._call(op, arglocs) def consider_new_with_vtable(self, op, ignored): from pypy.jit.backend.x86.runner import ConstDescr3 - descr = op.descr - assert isinstance(descr, ConstDescr3) - return self._call(op, [imm(descr.v[0]), self.loc(op.args[0])]) + args = self.assembler.cpu.gc_ll_descr.args_for_new(op.descr) + arglocs = [imm(x) for x in args] + arglocs.append(self.loc(op.args[0])) + return self._call(op, arglocs) def consider_newstr(self, op, ignored): ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code) 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 May 11 22:09:13 2009 @@ -14,7 +14,6 @@ from pypy.jit.backend.x86.assembler import Assembler386, WORD, MAX_FAIL_BOXES from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop, opname -from pypy.jit.backend.x86.support import gc_malloc_fnaddr from pypy.rlib.objectmodel import r_dict VOID = 0 @@ -24,19 +23,22 @@ history.TreeLoop._x86_compiled = 0 def const_descr_eq(a, b): - return a.v == b.v + return (a.v0 == b.v0 and + a.v1 == b.v1 and + a.flag2 == b.flag2) def const_descr_hash(a): - return a.v[0] + (a.v[1] << 2) + int(a.v[2] << 4) + return a.v0 + (a.v1 << 2) + int(a.flag2 << 4) class ConstDescr3(AbstractDescr): - def __init__(self, v): - # XXX don't use a tuple! that's yet another indirection... - self.v = v + def __init__(self, v0, v1, flag2): + self.v0 = v0 + self.v1 = v1 + self.flag2 = flag2 def _v(self): l = [] - for i in self.v: + for i in (self.v0, self.v1, self.flag2): if isinstance(i, Symbolic): l.append(id(i)) else: @@ -44,7 +46,7 @@ return tuple(l) def sort_key(self): - return self.v[0] # the ofs field for fielddescrs + return self.v0 # the ofs field for fielddescrs def equals(self, other): if not isinstance(other, ConstDescr3): @@ -61,7 +63,7 @@ return not self == other def __repr__(self): - return '' % (self.v,) + return '' % (self.v0, self.v1, self.flag2) class CPU386(object): debug = True @@ -71,9 +73,9 @@ def __init__(self, rtyper, stats, translate_support_code=False, mixlevelann=None, gcdescr=None): + from pypy.jit.backend.x86.gc import get_ll_description self.rtyper = rtyper self.stats = stats - self.gcdescr = gcdescr self.translate_support_code = translate_support_code if translate_support_code: assert mixlevelann @@ -101,7 +103,11 @@ self._setup_prebuilt_error('ovf', OverflowError) self._setup_prebuilt_error('zer', ZeroDivisionError) self.generated_mps = r_dict(const_descr_eq, const_descr_hash) - self.gc_malloc_fn = gc_malloc_fnaddr(gcdescr) + self.gc_ll_descr = get_ll_description(gcdescr, mixlevelann) + self._descr_caches = {} + self.vtable_offset, _ = symbolic.get_field_token(rclass.OBJECT, + 'typeptr', + translate_support_code) def _setup_prebuilt_error(self, prefix, Class): if self.rtyper is not None: # normal case @@ -375,10 +381,15 @@ # frame[mp.stacklocs[argindex]] = self.convert_box_to_int(valuebox) def sizeof(self, S): - size = symbolic.get_size(S, self.translate_support_code) - return ConstDescr3((size, 0, False)) + try: + return self._descr_caches['sizeof', S] + except KeyError: + pass + descr = self.gc_ll_descr.sizeof(S, self.translate_support_code) + self._descr_caches['sizeof', S] = descr + return descr - numof = sizeof +# numof = sizeof # addresssuffix = str(symbolic.get_size(llmemory.Address)) # def itemoffsetof(self, A): @@ -510,19 +521,18 @@ self._base_do_setfield(fielddescr, args[0].getint(), args[1]) def do_new(self, args, descrsize): - res = self.gc_malloc_fn(descrsize.v[0]) - return BoxPtr(self.cast_adr_to_gcref(res)) + res = self.gc_ll_descr.gc_malloc(descrsize) + return BoxPtr(res) def do_new_with_vtable(self, args, descrsize): - res = self.gc_malloc_fn(descrsize.v[0]) - rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = args[0].getint() - return BoxPtr(self.cast_adr_to_gcref(res)) + res = self.gc_ll_descr.gc_malloc(descrsize) + as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res) + as_array[self.vtable_offset/WORD] = args[0].getint() + return BoxPtr(res) def do_new_array(self, args, arraydescr): - size_of_field, ofs, ptr = self.unpack_arraydescr(arraydescr) num_elem = args[0].getint() - size = ofs + (1 << size_of_field) * num_elem - res = self.gc_malloc_fn(size) + res = self.gc_ll_descr.gc_malloc_array(arraydescr, num_elem) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = num_elem # XXX don't use 0 above! return BoxPtr(self.cast_adr_to_gcref(res)) @@ -533,7 +543,7 @@ self.translate_support_code) num_elem = args[0].getint() size = basesize + num_elem * itemsize - res = self.gc_malloc_fn(size) + res = self.gc_ll_descr.funcptr_for_new(size) # XXX don't use rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem return BoxPtr(self.cast_adr_to_gcref(res)) return do_newstr @@ -558,8 +568,8 @@ rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v) def do_call(self, args, calldescr): - num_args, size, ptr = self.unpack_calldescr(calldescr) assert isinstance(calldescr, ConstDescr3) + num_args, size, ptr = self.unpack_calldescr(calldescr) assert num_args == len(args) - 1 loop = self._get_loop_for_call(num_args, calldescr, ptr) history.set_future_values(self, args) @@ -592,6 +602,10 @@ return CPU386.cast_adr_to_int(adr) def arraydescrof(self, A): + try: + return self._descr_caches['array', A] + except KeyError: + pass assert isinstance(A, lltype.GcArray) basesize, itemsize, ofs_length = symbolic.get_array_token(A, self.translate_support_code) @@ -601,12 +615,16 @@ ptr = True else: ptr = False - return ConstDescr3((basesize, itemsize, ptr)) + descr = ConstDescr3(basesize, itemsize, ptr) + self._descr_caches['array', A] = descr + return descr @staticmethod def unpack_arraydescr(arraydescr): assert isinstance(arraydescr, ConstDescr3) - basesize, itemsize, ptr = arraydescr.v + basesize = arraydescr.v0 + itemsize = arraydescr.v1 + ptr = arraydescr.flag2 counter = 0 while itemsize != 1: itemsize >>= 1 @@ -614,6 +632,11 @@ return counter, basesize, ptr def calldescrof(self, functype, argtypes, resulttype): + cachekey = ('call', functype, tuple(argtypes), resulttype) + try: + return self._descr_caches[cachekey] + except KeyError: + pass for argtype in argtypes: if rffi.sizeof(argtype) > WORD: raise NotImplementedError("bigger than lltype.Signed") @@ -627,14 +650,20 @@ ptr = True else: ptr = False - return ConstDescr3((len(argtypes), size, ptr)) + descr = ConstDescr3(len(argtypes), size, ptr) + self._descr_caches[cachekey] = descr + return descr @staticmethod def unpack_calldescr(calldescr): assert isinstance(calldescr, ConstDescr3) - return calldescr.v + return calldescr.v0, calldescr.v1, calldescr.flag2 def fielddescrof(self, S, fieldname): + try: + return self._descr_caches['field', S, fieldname] + except KeyError: + pass ofs, size = symbolic.get_field_token(S, fieldname, self.translate_support_code) assert rffi.sizeof(getattr(S, fieldname)) in [1, 2, WORD] @@ -643,12 +672,14 @@ ptr = True else: ptr = False - return ConstDescr3((ofs, size, ptr)) + descr = ConstDescr3(ofs, size, ptr) + self._descr_caches['field', S, fieldname] = descr + return descr @staticmethod def unpack_fielddescr(fielddescr): assert isinstance(fielddescr, ConstDescr3) - return fielddescr.v + return fielddescr.v0, fielddescr.v1, fielddescr.flag2 @staticmethod def cast_int_to_adr(x): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Mon May 11 22:09:13 2009 @@ -21,7 +21,9 @@ while n > 0: myjitdriver.can_enter_jit(n=n, x=x) myjitdriver.jit_merge_point(n=n, x=x) - n -= x.foo + y = X() + y.foo = x.foo + n -= y.foo main._dont_inline_ = True def g(n): 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 May 11 22:09:13 2009 @@ -1050,7 +1050,10 @@ _TYPE = llmemory.GCREF def __init__(self, void_p): - self.intval = intmask(void_p.value) + if isinstance(void_p, (int, long)): + self.intval = intmask(void_p) + else: + self.intval = intmask(void_p.value) def __eq__(self, other): if isinstance(other, _llgcref): 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 Mon May 11 22:09:13 2009 @@ -387,6 +387,7 @@ 'promote_virtualizable':LLOp(canrun=True), 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), + 'get_gc_pointer': LLOp(), # __________ GC operations __________ Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Mon May 11 22:09:13 2009 @@ -124,7 +124,11 @@ # for regular translation: pick the GC from the config GCClass, GC_PARAMS = choose_gc_from_config(translator.config) - self.layoutbuilder = TransformerLayoutBuilder(self) + if hasattr(translator, '_transformerlayoutbuilder_from_jit'): + self.layoutbuilder = translator._transformerlayoutbuilder_from_jit + else: + self.layoutbuilder = TransformerLayoutBuilder() + self.layoutbuilder.transformer = self self.get_type_id = self.layoutbuilder.get_type_id # set up dummy a table, to be overwritten with the real one in finish() @@ -770,14 +774,13 @@ class TransformerLayoutBuilder(gctypelayout.TypeLayoutBuilder): - def __init__(self, transformer): - super(TransformerLayoutBuilder, self).__init__() - self.transformer = transformer - self.offsettable_cache = {} + def has_finalizer(self, TYPE): + rtti = get_rtti(TYPE) + return rtti is not None and hasattr(rtti._obj, 'destructor_funcptr') def make_finalizer_funcptr_for_type(self, TYPE): - rtti = get_rtti(TYPE) - if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): + if self.has_finalizer(TYPE): + rtti = get_rtti(TYPE) destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] else: From arigo at codespeak.net Mon May 11 22:16:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 22:16:32 +0200 (CEST) Subject: [pypy-svn] r65237 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090511201632.0EA2416847B@codespeak.net> Author: arigo Date: Mon May 11 22:16:31 2009 New Revision: 65237 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Log: Fix test. 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 Mon May 11 22:16:31 2009 @@ -48,10 +48,10 @@ cpu = CPU386(None, None) A = lltype.GcArray(lltype.Ptr(lltype.Array(lltype.Signed))) descr = cpu.arraydescrof(A) - assert not descr.v[2] + assert not descr.flag2 A = lltype.GcArray(lltype.Ptr(lltype.GcArray(lltype.Signed))) descr = cpu.arraydescrof(A) - assert descr.v[2] + assert descr.flag2 def test_varsized_struct_size(): S1 = lltype.GcStruct('S1', ('parent', S), From arigo at codespeak.net Mon May 11 23:18:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 23:18:13 +0200 (CEST) Subject: [pypy-svn] r65247 - pypy/branch/pyjitpl5/pypy/translator/c Message-ID: <20090511211813.8142616849D@codespeak.net> Author: arigo Date: Mon May 11 23:18:13 2009 New Revision: 65247 Modified: pypy/branch/pyjitpl5/pypy/translator/c/genc.py Log: It is convenient that "make lldebug" compiles with -O0 instead of -O1, to prevent all optimizations from gcc. Modified: pypy/branch/pyjitpl5/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/genc.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/genc.py Mon May 11 23:18:13 2009 @@ -465,7 +465,7 @@ ('no_obmalloc', '', '$(MAKE) CFLAGS="-g -O1 -DRPY_ASSERT -DNO_OBMALLOC" $(TARGET)'), ('linuxmemchk', '', '$(MAKE) CFLAGS="-g -O1 -DRPY_ASSERT -DLINUXMEMCHK" $(TARGET)'), ('llsafer', '', '$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(TARGET)'), - ('lldebug', '', '$(MAKE) CFLAGS="-g -O1 -DRPY_ASSERT -DRPY_LL_ASSERT" $(TARGET)'), + ('lldebug', '', '$(MAKE) CFLAGS="-g -DRPY_ASSERT -DRPY_LL_ASSERT" $(TARGET)'), ('profile', '', '$(MAKE) CFLAGS="-g -O1 -pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)" $(TARGET)'), ] if self.has_profopt(): From arigo at codespeak.net Mon May 11 23:19:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 May 2009 23:19:41 +0200 (CEST) Subject: [pypy-svn] r65248 - in pypy/branch/pyjitpl5/pypy: jit/backend/x86 rpython/lltypesystem rpython/memory/gctransform Message-ID: <20090511211941.E0F621684AC@codespeak.net> Author: arigo Date: Mon May 11 23:19:41 2009 New Revision: 65248 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Log: Transation fixes: add an operation 'do_malloc_fixedsize_clear' that is replaced later by the GC transform with a direct_call to the GC method of the same name. Fix a bug in the order of arguments in assembler.py. 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 Mon May 11 23:19:41 2009 @@ -399,7 +399,7 @@ def call(self, addr, args, res): - for i in range(len(args)): + for i in range(len(args)-1, -1, -1): arg = args[i] assert not isinstance(arg, MODRM) self.mc.PUSH(arg) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Mon May 11 23:19:41 2009 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rpython.annlowlevel import cast_base_ptr_to_instance +from pypy.rpython.annlowlevel import llhelper from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.jit.backend.x86 import symbolic from pypy.jit.backend.x86.runner import ConstDescr3 @@ -64,14 +64,12 @@ # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.TransformerLayoutBuilder() self.translator._transformerlayoutbuilder_from_jit = self.layoutbuilder - GCClass, _ = choose_gc_from_config(gcdescr.config) + #GCClass, _ = choose_gc_from_config(gcdescr.config) # make a malloc function, with three arguments - def getgc(): - ptr = llop.get_gc_pointer(rclass.OBJECTPTR) - return cast_base_ptr_to_instance(GCClass, ptr) def malloc_basic(size, type_id, has_finalizer): - return getgc().malloc_fixedsize_clear(type_id, size, True, + return llop.do_malloc_fixedsize_clear(llmemory.GCREF, + type_id, size, True, has_finalizer, False) self.malloc_basic = malloc_basic self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType( 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 Mon May 11 23:19:41 2009 @@ -387,7 +387,7 @@ 'promote_virtualizable':LLOp(canrun=True), 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), - 'get_gc_pointer': LLOp(), + 'do_malloc_fixedsize_clear': LLOp(), # __________ GC operations __________ Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Mon May 11 23:19:41 2009 @@ -596,6 +596,17 @@ [c_result], resultvar=op.result) + def gct_do_malloc_fixedsize_clear(self, hop): + # used by the JIT (see the x86 backend) + op = hop.spaceop + [v_typeid, v_size, v_can_collect, + v_has_finalizer, v_contains_weakptr] = op.args + hop.genop("direct_call", + [self.malloc_fixedsize_clear_ptr, self.c_const_gc, + v_typeid, v_size, v_can_collect, + v_has_finalizer, v_contains_weakptr], + resultvar=op.result) + def gct_zero_gc_pointers_inside(self, hop): if not self.malloc_zero_filled: v_ob = hop.spaceop.args[0] From benjamin at codespeak.net Tue May 12 00:17:04 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 12 May 2009 00:17:04 +0200 (CEST) Subject: [pypy-svn] r65249 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090511221704.1134A16846E@codespeak.net> Author: benjamin Date: Tue May 12 00:17:04 2009 New Revision: 65249 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: a trace of a presumably long-gone operation 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 Tue May 12 00:17:04 2009 @@ -836,7 +836,6 @@ consider_int_gt = _consider_compop consider_int_ge = _consider_compop consider_int_le = _consider_compop - xxx_consider_char_eq = _consider_compop consider_int_ne = _consider_compop consider_int_eq = _consider_compop consider_uint_gt = _consider_compop From arigo at codespeak.net Tue May 12 11:32:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 May 2009 11:32:02 +0200 (CEST) Subject: [pypy-svn] r65250 - in pypy/trunk/pypy: rpython/memory/gc translator/c/test Message-ID: <20090512093202.46A27168459@codespeak.net> Author: arigo Date: Tue May 12 11:32:00 2009 New Revision: 65250 Modified: pypy/trunk/pypy/rpython/memory/gc/semispace.py pypy/trunk/pypy/translator/c/test/test_newgc.py Log: Fix set_max_heap_size to round the number down, instead of up, which was a bit confusing. Modified: pypy/trunk/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/trunk/pypy/rpython/memory/gc/semispace.py Tue May 12 11:32:00 2009 @@ -180,12 +180,16 @@ return True # success def set_max_heap_size(self, size): - # Set the maximum semispace size. Note that the logic above will - # round this number *up* to the next power of two. Also, this is + # Set the maximum semispace size. + # The size is rounded down to the next power of two. Also, this is # the size of one semispace only, so actual usage can be the double # during a collection. Finally, note that this will never shrink # an already-allocated heap. - self.max_space_size = size + if size < 1: + size = 1 # actually, the minimum is 8MB in default translations + self.max_space_size = sys.maxint//2+1 + while self.max_space_size > size: + self.max_space_size >>= 1 def collect(self): self.debug_check_consistency() 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 Tue May 12 11:32:00 2009 @@ -976,7 +976,8 @@ # the semispace size starts at 8MB for now, so setting a # smaller limit has no effect from pypy.rlib import rgc - rgc.set_max_heap_size(20000000) # almost 20 MB + # set to more than 32MB -- which should be rounded down to 32MB + rgc.set_max_heap_size(32*1024*1024 + 20000) s1 = s2 = s3 = None try: s1 = g(400000) # ~ 400 KB From arigo at codespeak.net Tue May 12 11:35:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 May 2009 11:35:35 +0200 (CEST) Subject: [pypy-svn] r65251 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090512093535.2C77E168459@codespeak.net> Author: arigo Date: Tue May 12 11:35:34 2009 New Revision: 65251 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Log: A problem I naively overlooked. 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 Tue May 12 11:35:34 2009 @@ -19,4 +19,7 @@ * support root stack enumeration (at first, the easiest is probably to do it with asmgcc, which is good for performance :-) +* what to do about all ConstPtrs that end up embedded in the assembler? + annoying with a moving GC + * support write_barriers (later; at first, we support the semispace gc only) From arigo at codespeak.net Tue May 12 18:43:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 May 2009 18:43:48 +0200 (CEST) Subject: [pypy-svn] r65253 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090512164348.5307E16852A@codespeak.net> Author: arigo Date: Tue May 12 18:43:46 2009 New Revision: 65253 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Minor cleanups. 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 Tue May 12 18:43:46 2009 @@ -9,7 +9,7 @@ from pypy.annotation import model as annmodel from pypy.tool.uid import fixid from pypy.jit.backend.x86.regalloc import (RegAlloc, WORD, REGS, TempBox, - arg_pos, lower_byte, stack_pos) + lower_byte, stack_pos) from pypy.rlib.objectmodel import we_are_translated, specialize, compute_unique_id from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.ri386 import * @@ -291,30 +291,7 @@ finally: Box._extended_display = _prev -# def assemble_comeback_bootstrap(self, position, arglocs, stacklocs): -# return -# entry_point_addr = self.mc2.tell() -# for i in range(len(arglocs)): -# argloc = arglocs[i] -# if isinstance(argloc, REG): -# self.mc2.MOV(argloc, stack_pos(stacklocs[i])) -# elif not we_are_translated(): -# # debug checks -# if not isinstance(argloc, (IMM8, IMM32)): -# assert repr(argloc) == repr(stack_pos(stacklocs[i])) -# self.mc2.JMP(rel32(position)) -# self.mc2.done() -# return entry_point_addr - -# def assemble_generic_return(self): -# # generate a generic stub that just returns, taking the -# # return value from *esp (i.e. stack position 0). -# addr = self.mc.tell() -# self.mc.MOV(eax, mem(esp, 0)) -# self.mc.ADD(esp, imm(FRAMESIZE)) -# self.mc.RET() -# self.mc.done() -# return addr + # ------------------------------------------------------------ def regalloc_load(self, from_loc, to_loc): self.mc.MOV(to_loc, from_loc) @@ -646,7 +623,7 @@ def genop_arraylen_gc(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs - self.mc.MOV(resloc, addr_add(base_loc, imm(0))) + self.mc.MOV(resloc, addr_add_const(base_loc, 0)) # XXX fix this 0 def genop_strgetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs @@ -731,24 +708,6 @@ mc.JMP(rel32(pos)) mc.done() -# def genop_discard_return(self, op, locs): -# if op.args: -# loc = locs[0] -# if loc is not eax: -# self.mc.MOV(eax, loc) -# self.mc.ADD(esp, imm(FRAMESIZE)) -# # copy exception to some safe place and clean the original -# # one -# self.mc.MOV(ecx, heap(self._exception_addr)) -# self.mc.MOV(heap(self._exception_bck_addr), ecx) -# self.mc.MOV(ecx, addr_add(imm(self._exception_addr), imm(WORD))) -# self.mc.MOV(addr_add(imm(self._exception_bck_addr), imm(WORD)), -# ecx) -# # clean up the original exception, we don't want -# # to enter more rpython code with exc set -# self.mc.MOV(heap(self._exception_addr), imm(0)) -# self.mc.RET() - def genop_discard_jump(self, op, locs): targetmp = op.jump_target self.jumps_to_look_at.append((op, self.mc.tell())) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py Tue May 12 18:43:46 2009 @@ -4,8 +4,6 @@ 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 @@ -22,8 +20,7 @@ def write(self, data): p = self._pos - if p + len(data) > self._size: - raise CodeBlockOverflow + assert p + len(data) <= self._size for c in data: self._data[p] = c p += 1 @@ -126,48 +123,3 @@ size = self._size assert size >= 0 free(self._data, 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 Tue May 12 18:43:46 2009 @@ -1116,11 +1116,6 @@ num = getattr(rop, name.upper()) oplist[num] = value -def arg_pos(i, framesize): - res = mem(esp, framesize + WORD * (i + 1)) - res.position = (i + 1) + framesize // WORD - return res - def stack_pos(i): res = mem(esp, WORD * i) res.position = i From arigo at codespeak.net Tue May 12 21:06:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 May 2009 21:06:02 +0200 (CEST) Subject: [pypy-svn] r65254 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090512190602.18CBA169EA9@codespeak.net> Author: arigo Date: Tue May 12 21:06:00 2009 New Revision: 65254 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Log: Add the class GcRefList, designed to help with putting references to GC objects in the assembler. 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 Tue May 12 21:06:00 2009 @@ -146,6 +146,12 @@ # the address of the function called by 'new' ll_new = self.cpu.gc_ll_descr.get_funcptr_for_new() self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new) + # for moving GCs, the array used to hold the address of GC objects + # that appear as ConstPtr. + if self.cpu.gc_ll_descr.moving_gc: + self.gcrefs = self.cpu.gc_ll_descr.GcRefList() + else: + self.gcrefs = None def eventually_log_operations(self, inputargs, operations, memo=None, myid=0): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Tue May 12 21:06:00 2009 @@ -1,3 +1,4 @@ +from pypy.rlib import rgc from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.annlowlevel import llhelper @@ -5,6 +6,7 @@ from pypy.jit.backend.x86 import symbolic from pypy.jit.backend.x86.runner import ConstDescr3 +# ____________________________________________________________ class GcLLDescription: def __init__(self, gcdescr, mixlevelann): @@ -15,6 +17,7 @@ # ____________________________________________________________ class GcLLDescr_boehm(GcLLDescription): + moving_gc = False def __init__(self, gcdescr, mixlevelann): # grab a pointer to the Boehm 'malloc' function @@ -53,7 +56,69 @@ # ____________________________________________________________ +class GcRefList: + """Handles all references from the generated assembler to GC objects. + This is implemented as a nonmovable, but GC, list; the assembler contains + code that will (for now) always read from this list.""" + + GCREF_LIST = lltype.GcArray(llmemory.GCREF) # followed by the GC + + HASHTABLE = rffi.CArray(llmemory.Address) # ignored by the GC + HASHTABLE_BITS = 10 + HASHTABLE_SIZE = 1 << HASHTABLE_BITS + + def __init__(self): + self.list = self.alloc_gcref_list(2000) + self.nextindex = 0 + self.oldlists = [] + # A pseudo dictionary: it is fixed size, and it may contain + # random nonsense after a collection moved the objects. It is only + # used to avoid too many duplications in the GCREF_LISTs. + self.hashtable = lltype.malloc(self.HASHTABLE, + self.HASHTABLE_SIZE+1, + flavor='raw') + dummy = llmemory.itemoffsetof(self.hashtable, self.HASHTABLE_SIZE) + for i in range(self.HASHTABLE_SIZE+1): + self.hashtable[i] = dummy + + def alloc_gcref_list(self, n): + # Important: the GRREF_LISTs allocated are *non-movable*. This + # requires support in the gc (only the hybrid GC supports it so far). + list = rgc.malloc_nonmovable(self.GCREF_LIST, n) + assert list, "malloc_nonmovable failed!" + return list + + def get_address_of_gcref(self, gcref): + assert lltype.typeOf(gcref) == llmemory.GCREF + # first look in the hashtable, using an inexact hash (fails after + # the object moves) + addr = llmemory.cast_ptr_to_adr(gcref) + hash = llmemory.cast_adr_to_int(addr) + hash -= hash >> self.HASHTABLE_BITS + hash &= self.HASHTABLE_SIZE - 1 + addr_ref = self.hashtable[hash] + # the following test is safe anyway, because the addresses found + # in the hashtable are always the addresses of nonmovable stuff: + if addr_ref.address[0] == addr: + return addr_ref + # if it fails, add an entry to the list + if self.nextindex == len(self.list): + # reallocate first, increasing a bit the size every time + self.oldlists.append(self.list) + self.list = self.alloc_gcref_list(len(self.list) // 4 * 5) + self.nextindex = 0 + # add it + index = self.nextindex + self.list[index] = gcref + addr_ref = llmemory.itemoffsetof(self.GCREF_LIST, index) + self.nextindex = index + 1 + # record it in the hashtable + self.hashtable[hash] = addr_ref + return addr_ref + + class GcLLDescr_framework(GcLLDescription): + GcRefList = GcRefList def __init__(self, gcdescr, mixlevelann): from pypy.rpython.memory.gc.base import choose_gc_from_config @@ -64,7 +129,8 @@ # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.TransformerLayoutBuilder() self.translator._transformerlayoutbuilder_from_jit = self.layoutbuilder - #GCClass, _ = choose_gc_from_config(gcdescr.config) + GCClass, _ = choose_gc_from_config(gcdescr.config) + self.moving_gc = GCClass.moving_gc # make a malloc function, with three arguments def malloc_basic(size, type_id, has_finalizer): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Tue May 12 21:06:00 2009 @@ -5,6 +5,7 @@ soon as possible (at least in a simple case). """ import weakref +import py from pypy.rlib import rgc from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.jit import JitDriver @@ -77,6 +78,7 @@ def test_compile_boehm(): compile_and_run("boehm") -def test_compile_semispace(): - # a moving GC, but with no write barrier - compile_and_run("semispace", gcrootfinder="asmgcc") +def test_compile_hybrid(): + py.test.skip("in-progress") + # a moving GC, with a write barrier. Supports malloc_varsize_nonmovable. + compile_and_run("hybrid", gcrootfinder="asmgcc") From arigo at codespeak.net Tue May 12 22:00:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 May 2009 22:00:26 +0200 (CEST) Subject: [pypy-svn] r65255 - in pypy/branch/pyjitpl5/pypy/jit: backend/x86 backend/x86/test metainterp Message-ID: <20090512200026.7216F168556@codespeak.net> Author: arigo Date: Tue May 12 22:00:23 2009 New Revision: 65255 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py Log: The first (and only) test passes, for what it's worth. Still missing some proper testing... See comment in _rewrite_const_ptrs. 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 Tue May 12 22:00:23 2009 @@ -120,6 +120,8 @@ def make_sure_mc_exists(self): if self.mc is None: + from pypy.jit.backend.x86.runner import ConstDescr3 + self.fail_boxes = lltype.malloc(rffi.CArray(lltype.Signed), MAX_FAIL_BOXES, flavor='raw') self.fail_box_addr = self.cpu.cast_ptr_to_int(self.fail_boxes) @@ -150,6 +152,7 @@ # that appear as ConstPtr. if self.cpu.gc_ll_descr.moving_gc: self.gcrefs = self.cpu.gc_ll_descr.GcRefList() + self.single_gcref_descr = ConstDescr3(0, WORD, True) else: self.gcrefs = None Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Tue May 12 22:00:23 2009 @@ -77,7 +77,9 @@ self.hashtable = lltype.malloc(self.HASHTABLE, self.HASHTABLE_SIZE+1, flavor='raw') - dummy = llmemory.itemoffsetof(self.hashtable, self.HASHTABLE_SIZE) + dummy = lltype.direct_ptradd(lltype.direct_arrayitems(self.hashtable), + self.HASHTABLE_SIZE) + dummy = llmemory.cast_ptr_to_adr(dummy) for i in range(self.HASHTABLE_SIZE+1): self.hashtable[i] = dummy @@ -110,7 +112,9 @@ # add it index = self.nextindex self.list[index] = gcref - addr_ref = llmemory.itemoffsetof(self.GCREF_LIST, index) + addr_ref = lltype.direct_ptradd(lltype.direct_arrayitems(self.list), + index) + addr_ref = llmemory.cast_ptr_to_adr(addr_ref) self.nextindex = index + 1 # record it in the hashtable self.hashtable[hash] = addr_ref 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 Tue May 12 22:00:23 2009 @@ -3,11 +3,12 @@ """ from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, - ResOperation, ConstAddr) + ResOperation, ConstAddr, BoxPtr) from pypy.jit.backend.x86.ri386 import * 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.rlib import rgc from pypy.jit.backend.x86 import symbolic from pypy.jit.metainterp.resoperation import rop @@ -44,11 +45,15 @@ if isinstance(c, ConstInt): return imm(c.value) elif isinstance(c, ConstPtr): + if we_are_translated() and rgc.can_move(c.value): + print "convert_to_imm: ConstPtr needs special care" + raise AssertionError return imm(rffi.cast(lltype.Signed, c.value)) elif isinstance(c, ConstAddr): return imm(ll2ctypes.cast_adr_to_int(c.value)) else: - raise ValueError("convert_to_imm: got a %s" % c) + print "convert_to_imm: got a %s" % c + raise AssertionError class RegAlloc(object): max_stack_depth = 0 @@ -60,6 +65,7 @@ self.assembler = assembler self.translate_support_code = translate_support_code if regalloc is None: + self._rewrite_const_ptrs(tree.operations) self.tree = tree self.reg_bindings = newcheckdict() self.stack_bindings = newcheckdict() @@ -76,6 +82,7 @@ self.loop_consts = loop_consts self.current_stack_depth = sd else: + self._rewrite_const_ptrs(guard_op.suboperations) inp = guard_op.inputargs self.reg_bindings = {} self.stack_bindings = {} @@ -313,6 +320,33 @@ self.max_stack_depth = max(self.max_stack_depth, self.current_stack_depth + 1) + def _rewrite_const_ptrs(self, operations): + # Idea: when running on a moving GC, we can't (easily) encode + # the ConstPtrs in the assembler, because they can move at any + # point in time. Instead, we store them in 'gcrefs.list', a GC + # but nonmovable list; and here, we modify 'operations' to + # replace direct usage of ConstPtr with a BoxPtr loaded by a + # GETFIELD_RAW from the array 'gcrefs.list'. + gcrefs = self.assembler.gcrefs + if gcrefs is None: + return + single_gcref_descr = self.assembler.single_gcref_descr + newops = [] + for op in operations: + for i in range(len(op.args)): + v = op.args[i] + if isinstance(v, ConstPtr) and rgc.can_move(v.value): + box = BoxPtr(v.value) + addr = gcrefs.get_address_of_gcref(v.value) + addr = rffi.cast(lltype.Signed, addr) + newops.append(ResOperation(rop.GETFIELD_RAW, + [ConstInt(addr)], box, + single_gcref_descr)) + op.args[i] = box + newops.append(op) + del operations[:] + operations.extend(newops) + def _compute_vars_longevity(self, inputargs, operations): # compute a dictionary that maps variables to index in # operations that is a "last-time-seen" Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Tue May 12 22:00:23 2009 @@ -79,6 +79,5 @@ compile_and_run("boehm") def test_compile_hybrid(): - py.test.skip("in-progress") # a moving GC, with a write barrier. Supports malloc_varsize_nonmovable. compile_and_run("hybrid", gcrootfinder="asmgcc") Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/gc.py Tue May 12 22:00:23 2009 @@ -13,6 +13,12 @@ class GC_semispace(GcDescription): malloc_zero_filled = True +class GC_generation(GcDescription): + malloc_zero_filled = True + +class GC_hybrid(GcDescription): + malloc_zero_filled = True + def get_description(config): name = config.translation.gc From arigo at codespeak.net Tue May 12 22:03:04 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 May 2009 22:03:04 +0200 (CEST) Subject: [pypy-svn] r65256 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090512200304.B7D9D169E1E@codespeak.net> Author: arigo Date: Tue May 12 22:03:04 2009 New Revision: 65256 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Log: Two items out of 4 left... 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 Tue May 12 22:03:04 2009 @@ -14,12 +14,7 @@ Support for non-Boehm GCs: -* support calls to malloc and malloc_varsize from the generated assembler - * support root stack enumeration (at first, the easiest is probably to do it with asmgcc, which is good for performance :-) -* what to do about all ConstPtrs that end up embedded in the assembler? - annoying with a moving GC - * support write_barriers (later; at first, we support the semispace gc only) From pedronis at codespeak.net Wed May 13 16:22:10 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 May 2009 16:22:10 +0200 (CEST) Subject: [pypy-svn] r65257 - pypy/build/testrunner/test Message-ID: <20090513142210.E81AD169E29@codespeak.net> Author: pedronis Date: Wed May 13 16:22:08 2009 New Revision: 65257 Modified: pypy/build/testrunner/test/test_runner.py Log: fix tests now that resultlog is a plugin Modified: pypy/build/testrunner/test/test_runner.py ============================================================================== --- pypy/build/testrunner/test/test_runner.py (original) +++ pypy/build/testrunner/test/test_runner.py Wed May 13 16:22:08 2009 @@ -128,6 +128,8 @@ keep=3) cls.manydir = cls.udir.join('many').ensure(dir=1) + cls.udir.join("conftest.py").write("pytest_plugins = 'resultlog'\n") + def fill_test_dir(test_dir, fromdir='normal'): for p in py.path.local(__file__).dirpath( 'examples', fromdir).listdir("*.py"): From pedronis at codespeak.net Wed May 13 16:25:11 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 May 2009 16:25:11 +0200 (CEST) Subject: [pypy-svn] r65258 - pypy/build/testrunner Message-ID: <20090513142511.52A5F169E9F@codespeak.net> Author: pedronis Date: Wed May 13 16:25:10 2009 New Revision: 65258 Modified: pypy/build/testrunner/runner.py Log: fix tests now that resultlog is a plugin Modified: pypy/build/testrunner/runner.py ============================================================================== --- pypy/build/testrunner/runner.py (original) +++ pypy/build/testrunner/runner.py Wed May 13 16:25:10 2009 @@ -179,6 +179,8 @@ keep=4) run_param.sessdir = sessdir + run_param.startup() + N = run_param.parallel_runs failure = False @@ -218,6 +220,8 @@ if logdata: logfile.write(logdata) + run_param.shutdown() + return failure @@ -233,6 +237,12 @@ self.root = root self.self = self + def startup(self): + pass + + def shutdown(self): + pass + def get_test_driver(self, testdir): return self.test_driver From afa at codespeak.net Thu May 14 02:06:33 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 14 May 2009 02:06:33 +0200 (CEST) Subject: [pypy-svn] r65259 - in pypy/trunk/pypy/module: thread/test unicodedata unicodedata/test Message-ID: <20090514000633.63E71169E86@codespeak.net> Author: afa Date: Thu May 14 02:06:30 2009 New Revision: 65259 Modified: pypy/trunk/pypy/module/thread/test/test_fork.py (props changed) pypy/trunk/pypy/module/unicodedata/test/test_trie.py (props changed) pypy/trunk/pypy/module/unicodedata/triegenerator.py (props changed) Log: fixeol From arigo at codespeak.net Thu May 14 11:38:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 11:38:56 +0200 (CEST) Subject: [pypy-svn] r65260 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090514093856.F1735169E9F@codespeak.net> Author: arigo Date: Thu May 14 11:38:55 2009 New Revision: 65260 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Log: Add a test for the GcRefList class. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Thu May 14 11:38:55 2009 @@ -4,12 +4,14 @@ however, is the correct handling of GC, i.e. if objects are freed as soon as possible (at least in a simple case). """ -import weakref +import weakref, random import py from pypy.rlib import rgc +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.jit import JitDriver from pypy.jit.backend.x86.runner import CPU386 +from pypy.jit.backend.x86.gc import GcRefList myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @@ -35,7 +37,7 @@ return weakref.ref(x) g._dont_inline_ = True -def f(args): +def entrypoint(args): r_list = [] for i in range(20): r = g(1000) @@ -50,34 +52,49 @@ return 0 -def compile_and_run(gc, **kwds): +def compile_and_run(f, gc, **kwds): from pypy.translator.translator import TranslationContext from pypy.jit.metainterp.warmspot import apply_jit from pypy.translator.c import genc # t = TranslationContext() t.config.translation.gc = gc - t.config.translation.jit = True for name, value in kwds.items(): setattr(t.config.translation, name, value) t.buildannotator().build_types(f, [int]) t.buildrtyper().specialize() - apply_jit(t, CPUClass=CPU386) + if kwds['jit']: + apply_jit(t, CPUClass=CPU386) cbuilder = genc.CStandaloneBuilder(t, f, t.config) cbuilder.generate_source() cbuilder.compile() # data = cbuilder.cmdexec('') - res = int(data.strip()) - if gc == "boehm": - assert res >= 16 - else: - assert res == 20 + return data.strip() def test_compile_boehm(): - compile_and_run("boehm") + res = compile_and_run(entrypoint, "boehm", jit=True) + assert int(res) >= 16 + +def test_GcRefList(): + S = lltype.GcStruct('S') + order = range(20000) * 4 + random.shuffle(order) + def fn(args): + allocs = [lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)) + for i in range(20000)] + allocs = [allocs[i] for i in order] + # + gcrefs = GcRefList() + addrs = [gcrefs.get_address_of_gcref(ptr) for ptr in allocs] + for i in range(len(allocs)): + assert addrs[i].address[0] == llmemory.cast_ptr_to_adr(allocs[i]) + return 0 + compile_and_run(fn, "hybrid", gcrootfinder="asmgcc", jit=False) def test_compile_hybrid(): # a moving GC, with a write barrier. Supports malloc_varsize_nonmovable. - compile_and_run("hybrid", gcrootfinder="asmgcc") + res = compile_and_run(entrypoint, "hybrid", gcrootfinder="asmgcc", + jit=True) + assert int(res) == 20 From arigo at codespeak.net Thu May 14 11:43:21 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 11:43:21 +0200 (CEST) Subject: [pypy-svn] r65261 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090514094321.C7A0A169EA5@codespeak.net> Author: arigo Date: Thu May 14 11:43:21 2009 New Revision: 65261 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Log: Update the TODO. 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 Thu May 14 11:43:21 2009 @@ -17,4 +17,4 @@ * support root stack enumeration (at first, the easiest is probably to do it with asmgcc, which is good for performance :-) -* support write_barriers (later; at first, we support the semispace gc only) +* support write_barriers From arigo at codespeak.net Thu May 14 12:16:24 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 12:16:24 +0200 (CEST) Subject: [pypy-svn] r65262 - pypy/branch/pyjitpl5/pypy/translator/c/gcc Message-ID: <20090514101624.1C4B1169EA5@codespeak.net> Author: arigo Date: Thu May 14 12:16:23 2009 New Revision: 65262 Modified: pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py Log: Bad name (probably no consequence apart from debugging). Modified: pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/gcc/trackgcroot.py Thu May 14 12:16:23 2009 @@ -76,7 +76,7 @@ popl %ebp /* restore from ASM_FRAMEDATA[3] */ popl %eax ret - .size pypy_asm_stackwalk_init, .-pypy_asm_stackwalk_init + .size pypy_asm_stackwalk, .-pypy_asm_stackwalk """ print >> output, '\t.data' print >> output, '\t.align\t4' From arigo at codespeak.net Thu May 14 15:38:21 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 15:38:21 +0200 (CEST) Subject: [pypy-svn] r65263 - in pypy/branch/pyjitpl5/pypy: jit/backend/x86 jit/backend/x86/test rpython/memory/gctransform Message-ID: <20090514133821.99B98168529@codespeak.net> Author: arigo Date: Thu May 14 15:38:19 2009 New Revision: 65263 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Log: In-progress: stack root enumeration. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Thu May 14 15:38:19 2009 @@ -5,6 +5,7 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.jit.backend.x86 import symbolic from pypy.jit.backend.x86.runner import ConstDescr3 +from pypy.jit.backend.x86.ri386 import MODRM # ____________________________________________________________ @@ -41,9 +42,9 @@ def gc_malloc_array(self, arraydescr, num_elem): assert isinstance(arraydescr, ConstDescr3) - size_of_field = arraydescr.v0 - ofs = arraydescr.v1 - size = ofs + (1 << size_of_field) * num_elem + basesize = arraydescr.v0 + itemsize = arraydescr.v1 + size = basesize + itemsize * num_elem return self.funcptr_for_new(size) def args_for_new(self, descrsize): @@ -121,6 +122,94 @@ return addr_ref +class GcRootMap_asmgcc: + """Handles locating the stack roots in the assembler. + This is the class supporting --gcrootfinder=asmgcc. + """ + LOC_NOWHERE = 0 + LOC_REG = 1 + LOC_EBP_BASED = 2 + LOC_ESP_BASED = 3 + + GCMAP_ARRAY = rffi.CArray(llmemory.Address) + CALLSHAPE_ARRAY = rffi.CArray(rffi.UCHAR) + + def __init__(self): + self._gcmap = lltype.malloc(self.GCMAP_ARRAY, 0, flavor='raw') + self._gcmap_curlength = 0 + self._gcmap_maxlength = 0 + + def gcmapstart(self): + return llmemory.cast_ptr_to_adr(self._gcmap) + + def gcmapend(self): + start = self.gcmapstart() + return start + llmemory.sizeof(lltype.Signed) * self._gcmap_curlength + + def put(self, retaddr, callshapeaddr): + """'retaddr' is the address just after the CALL. + 'callshapeaddr' is the address returned by encode_callshape().""" + index = self._gcmap_curlength + if index + 2 > self._gcmap_maxlength: + self._enlarge_gcmap() + self._gcmap[index] = retaddr + self._gcmap[index+1] = callshapeaddr + self._gcmap_curlength = index + 2 + + def _enlarge_gcmap(self): + newlength = 128 + self._gcmap_maxlength // 4 + newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw') + oldgcmap = self._gcmap + for i in range(self._gcmap_curlength): + newgcmap[i] = oldgcmap[i] + self._gcmap = newgcmap + self._gcmap_maxlength = newlength + lltype.free(oldgcmap, flavor='raw') + + def encode_callshape(self, gclocs, framesize): + """Encode a callshape from the list of locations containing GC + pointers and from the frame size of the current (caller) frame. + The framesize gives the offset from %esp to the return address + of the current frame.""" + shape = self._get_callshape(gclocs, framesize) + return self._compress_callshape(shape) + + def _get_callshape(self, gclocs, framesize): + # the four registers %ebx, %esi, %edi, %ebp are not used at all + # so far, so their value always comes from the caller. + shape = [self.LOC_ESP_BASED | framesize, + self.LOC_REG | 0, + self.LOC_REG | 4, + self.LOC_REG | 8, + self.LOC_REG | 12, + 0] + for loc in gclocs: + assert isinstance(loc, MODRM) + shape.append(self.LOC_ESP_BASED | (4 * loc.position)) + return shape + + def _compress_callshape(self, shape): + # Similar to compress_callshape() in trackgcroot.py. XXX a bit slowish + result = [] + for loc in shape: + assert loc >= 0 + loc = loc * 2 + flag = 0 + while loc >= 0x80: + result.append(int(loc & 0x7F) | flag) + flag = 0x80 + loc >>= 7 + result.append(int(loc) | flag) + # XXX so far, we always allocate a new small array (we could regroup + # them inside bigger arrays) and we never try to share them. + length = len(result) + compressed = lltype.malloc(self.CALLSHAPE_ARRAY, length, + flavor='raw') + for i in range(length): + compressed[length-1-i] = rffi.cast(rffi.UCHAR, result[i]) + return llmemory.cast_ptr_to_adr(compressed) + + class GcLLDescr_framework(GcLLDescription): GcRefList = GcRefList @@ -129,10 +218,23 @@ from pypy.rpython.memory.gctransform import framework self.translator = mixlevelann.rtyper.annotator.translator + # to find roots in the assembler, make a GcRootMap + name = gcdescr.config.translation.gcrootfinder + try: + cls = globals()['GcRootMap_' + name] + except KeyError: + raise NotImplementedError("--gcrootfinder=%s not implemented" + " with the JIT" % (name,)) + self.gcrootmap = cls() + # make a TransformerLayoutBuilder and save it on the translator # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.TransformerLayoutBuilder() - self.translator._transformerlayoutbuilder_from_jit = self.layoutbuilder + self.translator._jit2gc = { + 'layoutbuilder': self.layoutbuilder, + 'gcmapstart': self.gcrootmap.gcmapstart, + 'gcmapend': self.gcrootmap.gcmapend, + } GCClass, _ = choose_gc_from_config(gcdescr.config) self.moving_gc = GCClass.moving_gc @@ -145,10 +247,6 @@ self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType( [lltype.Signed, lltype.Signed, lltype.Bool], llmemory.GCREF)) - assert gcdescr.config.translation.gcrootfinder == "asmgcc", ( - "with the framework GCs, you must use" - " --gcrootfinder=asmgcc for now") - def sizeof(self, S, translate_support_code): from pypy.rpython.memory.gctypelayout import weakpointer_offset assert translate_support_code, "required with the framework GC" Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Thu May 14 15:38:19 2009 @@ -11,45 +11,39 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.jit import JitDriver from pypy.jit.backend.x86.runner import CPU386 -from pypy.jit.backend.x86.gc import GcRefList - - -myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) +from pypy.jit.backend.x86.gc import GcRefList, GcRootMap_asmgcc +from pypy.jit.backend.x86.regalloc import stack_pos class X(object): pass -def main(n, x): - while n > 0: - myjitdriver.can_enter_jit(n=n, x=x) - myjitdriver.jit_merge_point(n=n, x=x) - y = X() - y.foo = x.foo - n -= y.foo -main._dont_inline_ = True - -def g(n): - x = X() - x.foo = 2 - main(n, x) - x.foo = 5 - return weakref.ref(x) -g._dont_inline_ = True - -def entrypoint(args): - r_list = [] - for i in range(20): - r = g(1000) - r_list.append(r) - rgc.collect() - rgc.collect(); rgc.collect() - freed = 0 - for r in r_list: - if r() is None: - freed += 1 - print freed - return 0 +def get_test(main): + main._dont_inline_ = True + + def g(n): + x = X() + x.foo = 2 + main(n, x) + x.foo = 5 + return weakref.ref(x) + g._dont_inline_ = True + + def entrypoint(args): + r_list = [] + for i in range(20): + r = g(1000) + r_list.append(r) + rgc.collect() + rgc.collect(); rgc.collect() + freed = 0 + for r in r_list: + if r() is None: + freed += 1 + print freed + return 0 + + return entrypoint def compile_and_run(f, gc, **kwds): @@ -74,7 +68,15 @@ def test_compile_boehm(): - res = compile_and_run(entrypoint, "boehm", jit=True) + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) + def main(n, x): + while n > 0: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + y = X() + y.foo = x.foo + n -= y.foo + res = compile_and_run(get_test(main), "boehm", jit=True) assert int(res) >= 16 def test_GcRefList(): @@ -93,8 +95,47 @@ return 0 compile_and_run(fn, "hybrid", gcrootfinder="asmgcc", jit=False) -def test_compile_hybrid(): - # a moving GC, with a write barrier. Supports malloc_varsize_nonmovable. - res = compile_and_run(entrypoint, "hybrid", gcrootfinder="asmgcc", +def test_compile_hybrid_1(): + # a moving GC. Supports malloc_varsize_nonmovable. Simple test, works + # without write_barriers and root stack enumeration. + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) + def main(n, x): + while n > 0: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + y = X() + y.foo = x.foo + n -= y.foo + res = compile_and_run(get_test(main), "hybrid", gcrootfinder="asmgcc", + jit=True) + assert int(res) == 20 + +def test_GcRootMap_asmgcc(): + gcrootmap = GcRootMap_asmgcc() + shape = gcrootmap._get_callshape([stack_pos(1), stack_pos(55)], 236) + assert shape == [236|3, 1, 5, 9, 13, 0, 4|3, 220|3] + # + addr = gcrootmap.encode_callshape([stack_pos(1), stack_pos(55)], 236) + PCALLSHAPE = lltype.Ptr(GcRootMap_asmgcc.CALLSHAPE_ARRAY) + p = llmemory.cast_adr_to_ptr(addr, PCALLSHAPE) + for i, expected in enumerate([131, 62, 14, 0, 26, 18, 10, 2, 131, 94]): + assert p[i] == expected + +def test_compile_hybrid_2(): + py.test.skip("in-progress") + # a moving GC. Supports malloc_varsize_nonmovable. More complex test, + # requires root stack enumeration but not write_barriers. + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) + def main(n, x): + while n > 0: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + prev = x + for j in range(101): # main() runs 20'000 times, thus allocates + y = X() # a total of 2'020'000 objects + y.foo = prev.foo + prev = y + n -= prev.foo + res = compile_and_run(get_test(main), "hybrid", gcrootfinder="asmgcc", jit=True) assert int(res) == 20 Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/asmgcroot.py Thu May 14 15:38:19 2009 @@ -46,6 +46,14 @@ self.walk_stack_from(initialframedata) self._asm_callback = _asm_callback self._shape_decompressor = ShapeDecompressor() + if hasattr(gctransformer.translator, '_jit2gc'): + jit2gc = gctransformer.translator._jit2gc + self._extra_gcmapstart = jit2gc['gcmapstart'] + self._extra_gcmapend = jit2gc['gcmapend'] + else: + returns_null = lambda: llmemory.NULL + self._extra_gcmapstart = returns_null + self._extra_gcmapend = returns_null def walk_stack_roots(self, collect_stack_root): gcdata = self.gcdata @@ -128,25 +136,12 @@ retaddr = callee.frame_address.address[0] # # try to locate the caller function based on retaddr. + # set up self._shape_decompressor. # - gcmapstart = llop.llvm_gcmapstart(llmemory.Address) - gcmapend = llop.llvm_gcmapend(llmemory.Address) - item = search_in_gcmap(gcmapstart, gcmapend, retaddr) - if not item: - # the item may have been not found because the array was - # not sorted. Sort it and try again. - sort_gcmap(gcmapstart, gcmapend) - item = search_in_gcmap(gcmapstart, gcmapend, retaddr) - if not item: - llop.debug_fatalerror(lltype.Void, "cannot find gc roots!") - return False + self.locate_caller_based_on_retaddr(retaddr) # # found! Enumerate the GC roots in the caller frame # - shape = item.signed[1] - if shape < 0: - shape = ~ shape # can ignore this "range" marker here - self._shape_decompressor.setpos(shape) collect_stack_root = self.gcdata._gc_collect_stack_root gc = self.gc while True: @@ -173,6 +168,36 @@ # of the entry point, stop walking" return caller.frame_address != llmemory.NULL + def locate_caller_based_on_retaddr(self, retaddr): + gcmapstart = llop.llvm_gcmapstart(llmemory.Address) + gcmapend = llop.llvm_gcmapend(llmemory.Address) + item = search_in_gcmap(gcmapstart, gcmapend, retaddr) + if item: + self._shape_decompressor.setpos(item.signed[1]) + return + gcmapstart2 = self._extra_gcmapstart() + gcmapend2 = self._extra_gcmapend() + if gcmapstart2 != gcmapend2: + # we have a non-empty JIT-produced table to look in + item = search_in_gcmap(gcmapstart2, gcmapend2, retaddr) + if item: + self._shape_decompressor.setaddr(item.address[1]) + return + # maybe the JIT-produced table is not sorted? + sort_gcmap(gcmapstart2, gcmapend2) + item = search_in_gcmap(gcmapstart2, gcmapend2, retaddr) + if item: + self._shape_decompressor.setaddr(item.address[1]) + return + # the item may have been not found because the main array was + # not sorted. Sort it and try again. + sort_gcmap(gcmapstart, gcmapend) + item = search_in_gcmap(gcmapstart, gcmapend, retaddr) + if item: + self._shape_decompressor.setpos(item.signed[1]) + return + llop.debug_fatalerror(lltype.Void, "cannot find gc roots!") + def getlocation(self, callee, location): """Get the location in the 'caller' frame of a variable, based on the integer 'location' that describes it. All locations are @@ -261,9 +286,14 @@ _alloc_flavor_ = "raw" def setpos(self, pos): + if pos < 0: + pos = ~ pos # can ignore this "range" marker here gccallshapes = llop.llvm_gccallshapes(llmemory.Address) self.addr = gccallshapes + pos + def setaddr(self, addr): + self.addr = addr + def next(self): value = 0 addr = self.addr Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Thu May 14 15:38:19 2009 @@ -124,8 +124,8 @@ # for regular translation: pick the GC from the config GCClass, GC_PARAMS = choose_gc_from_config(translator.config) - if hasattr(translator, '_transformerlayoutbuilder_from_jit'): - self.layoutbuilder = translator._transformerlayoutbuilder_from_jit + if hasattr(translator, '_jit2gc'): + self.layoutbuilder = translator._jit2gc['layoutbuilder'] else: self.layoutbuilder = TransformerLayoutBuilder() self.layoutbuilder.transformer = self From arigo at codespeak.net Thu May 14 19:03:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 19:03:27 +0200 (CEST) Subject: [pypy-svn] r65264 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090514170327.331D9169EFA@codespeak.net> Author: arigo Date: Thu May 14 19:03:25 2009 New Revision: 65264 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Log: Yay! GC roots finding seems to work. 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 Thu May 14 19:03:25 2009 @@ -155,6 +155,9 @@ self.single_gcref_descr = ConstDescr3(0, WORD, True) else: self.gcrefs = None + self.gcrootmap = self.cpu.gc_ll_descr.gcrootmap + if self.gcrootmap: + self.gcrootmap.initialize() def eventually_log_operations(self, inputargs, operations, memo=None, myid=0): @@ -240,8 +243,7 @@ self.eventually_log_operations(tree.inputargs, tree.operations, None, compute_unique_id(tree)) regalloc = RegAlloc(self, tree, self.cpu.translate_support_code) - if not we_are_translated(): - self._regalloc = regalloc # for debugging + self._regalloc = regalloc regalloc.walk_operations(tree) self.sanitize_tree(tree.operations) self.mc.done() @@ -257,6 +259,8 @@ tl = op.jump_target self.patch_jump(pos, tl._x86_compiled, tl.arglocs, tl.arglocs, tree._x86_stack_depth, tl._x86_stack_depth) + if we_are_translated(): + self._regalloc = None # else keep it around for debugging def sanitize_tree(self, operations): """ Cleans up all attributes attached by regalloc and backend @@ -270,6 +274,9 @@ def assemble_bootstrap_code(self, jumpaddr, arglocs, framesize): self.make_sure_mc_exists() addr = self.mc.tell() + if self.gcrootmap: + self.mc.PUSH(ebp) + self.mc.MOV(ebp, esp) self.mc.SUB(esp, imm(framesize * WORD)) # This uses XCHG to put zeroes in fail_boxes after reading them, # just in case they are pointers. @@ -390,6 +397,7 @@ assert not isinstance(arg, MODRM) self.mc.PUSH(arg) self.mc.CALL(rel32(addr)) + self.mark_gc_roots(len(args)) self.mc.ADD(esp, imm(len(args) * WORD)) assert res is eax @@ -814,6 +822,8 @@ self.mc.ADD(esp, imm32(0)) guard_index = self.cpu.make_guard_index(op) self.mc.MOV(eax, imm(guard_index)) + if self.gcrootmap: + self.mc.POP(ebp) self.mc.RET() def generate_ovf_set(self): @@ -860,6 +870,7 @@ if isinstance(x, MODRM): x = stack_pos(x.position + extra_on_stack) self.mc.CALL(x) + self.mark_gc_roots(extra_on_stack) self.mc.ADD(esp, imm(WORD * extra_on_stack)) if size == 1: self.mc.AND(eax, imm(0xff)) @@ -889,6 +900,18 @@ # self.gen_call(op, arglocs, resloc) # self.mc.MOVZX(eax, eax) + def mark_gc_roots(self, extra_on_stack): + if self.gcrootmap: + gclocs = [] + regalloc = self._regalloc + for v, val in regalloc.stack_bindings.items(): + if (isinstance(v, BoxPtr) and + regalloc.longevity[v][1] > regalloc.position): + gclocs.append(val) + shape = self.gcrootmap.encode_callshape(gclocs) + self.gcrootmap.put(rffi.cast(llmemory.Address, self.mc.tell()), + shape) + genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST genop_list = [Assembler386.not_implemented_op] * rop._LAST genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Thu May 14 19:03:25 2009 @@ -19,6 +19,7 @@ class GcLLDescr_boehm(GcLLDescription): moving_gc = False + gcrootmap = None def __init__(self, gcdescr, mixlevelann): # grab a pointer to the Boehm 'malloc' function @@ -135,16 +136,22 @@ CALLSHAPE_ARRAY = rffi.CArray(rffi.UCHAR) def __init__(self): - self._gcmap = lltype.malloc(self.GCMAP_ARRAY, 0, flavor='raw') + self._gcmap = lltype.nullptr(self.GCMAP_ARRAY) self._gcmap_curlength = 0 self._gcmap_maxlength = 0 + def initialize(self): + # hack hack hack. Remove these lines and see MissingRTypeAttribute + # when the rtyper tries to annotate these methods only when GC-ing... + self.gcmapstart() + self.gcmapend() + def gcmapstart(self): return llmemory.cast_ptr_to_adr(self._gcmap) def gcmapend(self): start = self.gcmapstart() - return start + llmemory.sizeof(lltype.Signed) * self._gcmap_curlength + return start + llmemory.sizeof(llmemory.Address)*self._gcmap_curlength def put(self, retaddr, callshapeaddr): """'retaddr' is the address just after the CALL. @@ -157,31 +164,31 @@ self._gcmap_curlength = index + 2 def _enlarge_gcmap(self): - newlength = 128 + self._gcmap_maxlength // 4 + newlength = 128 + self._gcmap_maxlength * 5 // 4 newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw') oldgcmap = self._gcmap for i in range(self._gcmap_curlength): newgcmap[i] = oldgcmap[i] self._gcmap = newgcmap self._gcmap_maxlength = newlength - lltype.free(oldgcmap, flavor='raw') + if oldgcmap: + lltype.free(oldgcmap, flavor='raw') - def encode_callshape(self, gclocs, framesize): + def encode_callshape(self, gclocs): """Encode a callshape from the list of locations containing GC - pointers and from the frame size of the current (caller) frame. - The framesize gives the offset from %esp to the return address - of the current frame.""" - shape = self._get_callshape(gclocs, framesize) + pointers.""" + shape = self._get_callshape(gclocs) return self._compress_callshape(shape) - def _get_callshape(self, gclocs, framesize): - # the four registers %ebx, %esi, %edi, %ebp are not used at all + def _get_callshape(self, gclocs): + # The return address is always found at 4(%ebp); and + # the three registers %ebx, %esi, %edi are not used at all # so far, so their value always comes from the caller. - shape = [self.LOC_ESP_BASED | framesize, + shape = [self.LOC_EBP_BASED | 4, self.LOC_REG | 0, self.LOC_REG | 4, self.LOC_REG | 8, - self.LOC_REG | 12, + self.LOC_EBP_BASED | 0, 0] for loc in gclocs: assert isinstance(loc, MODRM) @@ -225,15 +232,16 @@ except KeyError: raise NotImplementedError("--gcrootfinder=%s not implemented" " with the JIT" % (name,)) - self.gcrootmap = cls() + gcrootmap = cls() + self.gcrootmap = gcrootmap # make a TransformerLayoutBuilder and save it on the translator # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.TransformerLayoutBuilder() self.translator._jit2gc = { 'layoutbuilder': self.layoutbuilder, - 'gcmapstart': self.gcrootmap.gcmapstart, - 'gcmapend': self.gcrootmap.gcmapend, + 'gcmapstart': lambda: gcrootmap.gcmapstart(), + 'gcmapend': lambda: gcrootmap.gcmapend(), } GCClass, _ = choose_gc_from_config(gcdescr.config) self.moving_gc = GCClass.moving_gc 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 Thu May 14 19:03:25 2009 @@ -951,7 +951,8 @@ loc = self.make_sure_var_in_reg(v, [v]) self.sync_var(v) if size != 0: - # XXX lshift? + # XXX lshift? no, better yet, use 'LEA' somehow (it can be + # combined with the following INT_ADD) self.Perform(ResOperation(rop.INT_MUL, [], None), [loc, imm(1 << size)], loc) self.Perform(ResOperation(rop.INT_ADD, [], None), Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Thu May 14 19:03:25 2009 @@ -7,7 +7,7 @@ import weakref, random import py from pypy.rlib import rgc -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.jit import JitDriver from pypy.jit.backend.x86.runner import CPU386 @@ -112,17 +112,34 @@ def test_GcRootMap_asmgcc(): gcrootmap = GcRootMap_asmgcc() - shape = gcrootmap._get_callshape([stack_pos(1), stack_pos(55)], 236) - assert shape == [236|3, 1, 5, 9, 13, 0, 4|3, 220|3] + shape = gcrootmap._get_callshape([stack_pos(1), stack_pos(55)]) + assert shape == [6, 1, 5, 9, 2, 0, 4|3, 220|3] # - addr = gcrootmap.encode_callshape([stack_pos(1), stack_pos(55)], 236) + shapeaddr = gcrootmap.encode_callshape([stack_pos(1), stack_pos(55)]) PCALLSHAPE = lltype.Ptr(GcRootMap_asmgcc.CALLSHAPE_ARRAY) - p = llmemory.cast_adr_to_ptr(addr, PCALLSHAPE) - for i, expected in enumerate([131, 62, 14, 0, 26, 18, 10, 2, 131, 94]): + p = llmemory.cast_adr_to_ptr(shapeaddr, PCALLSHAPE) + for i, expected in enumerate([131, 62, 14, 0, 4, 18, 10, 2, 12]): assert p[i] == expected + # + retaddr = rffi.cast(llmemory.Address, 1234567890) + gcrootmap.put(retaddr, shapeaddr) + assert gcrootmap._gcmap[0] == retaddr + assert gcrootmap._gcmap[1] == shapeaddr + assert gcrootmap.gcmapstart().address[0] == retaddr + # + # the same as before, but enough times to trigger a few resizes + expected_shapeaddr = {} + for i in range(1, 600): + shapeaddr = gcrootmap.encode_callshape([stack_pos(i)]) + expected_shapeaddr[i] = shapeaddr + retaddr = rffi.cast(llmemory.Address, 123456789 + i) + gcrootmap.put(retaddr, shapeaddr) + for i in range(1, 600): + expected_retaddr = rffi.cast(llmemory.Address, 123456789 + i) + assert gcrootmap._gcmap[i*2+0] == expected_retaddr + assert gcrootmap._gcmap[i*2+1] == expected_shapeaddr[i] def test_compile_hybrid_2(): - py.test.skip("in-progress") # a moving GC. Supports malloc_varsize_nonmovable. More complex test, # requires root stack enumeration but not write_barriers. myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) From arigo at codespeak.net Thu May 14 19:33:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 19:33:58 +0200 (CEST) Subject: [pypy-svn] r65265 - pypy/branch/pyjitpl5/pypy/jit/backend/x86/test Message-ID: <20090514173358.27B56169DFB@codespeak.net> Author: arigo Date: Thu May 14 19:33:56 2009 New Revision: 65265 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Log: Test about write barriers, skipped. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Thu May 14 19:33:56 2009 @@ -16,7 +16,7 @@ class X(object): - pass + next = None def get_test(main): main._dont_inline_ = True @@ -140,8 +140,8 @@ assert gcrootmap._gcmap[i*2+1] == expected_shapeaddr[i] def test_compile_hybrid_2(): - # a moving GC. Supports malloc_varsize_nonmovable. More complex test, - # requires root stack enumeration but not write_barriers. + # More complex test, requires root stack enumeration but + # not write_barriers. myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) def main(n, x): while n > 0: @@ -156,3 +156,32 @@ res = compile_and_run(get_test(main), "hybrid", gcrootfinder="asmgcc", jit=True) assert int(res) == 20 + +def test_compile_hybrid_3(): + py.test.skip("in-progress") + # Third version of the test. Really requires write_barriers. + myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) + def main(n, x): + while n > 0: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + x.next = None + for j in range(101): # main() runs 20'000 times, thus allocates + y = X() # a total of 2'020'000 objects + y.foo = j+1 + y.next = x.next + x.next = y + total = 0 + y = x + for j in range(101): + y = y.next + total += y.foo + assert not y.next + assert total == 101*102/2 + n -= x.foo + x_test = X() + x_test.foo = 5 + main(6, x_test) # check that it does not raise AssertionError + res = compile_and_run(get_test(main), "hybrid", gcrootfinder="asmgcc", + jit=True) + assert int(res) == 20 From arigo at codespeak.net Thu May 14 22:04:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 May 2009 22:04:09 +0200 (CEST) Subject: [pypy-svn] r65266 - pypy/build/bot2/pypybuildbot Message-ID: <20090514200409.9B734169F21@codespeak.net> Author: arigo Date: Thu May 14 22:04:08 2009 New Revision: 65266 Modified: pypy/build/bot2/pypybuildbot/builds.py Log: Add --gc=boehm for now (it used to be the only option available). Modified: pypy/build/bot2/pypybuildbot/builds.py ============================================================================== --- pypy/build/bot2/pypybuildbot/builds.py (original) +++ pypy/build/bot2/pypybuildbot/builds.py Thu May 14 22:04:08 2009 @@ -200,7 +200,8 @@ setup_steps(platform, self) - self.addStep(Translate(['--jit'], ['--withoutmod-thread'])) + self.addStep(Translate(['--jit', '--gc=boehm'], + ['--withoutmod-thread'])) self.addStep(ShellCmd( description="lib-python test", From arigo at codespeak.net Fri May 15 11:45:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 May 2009 11:45:17 +0200 (CEST) Subject: [pypy-svn] r65267 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090515094517.1631E169EFC@codespeak.net> Author: arigo Date: Fri May 15 11:45:17 2009 New Revision: 65267 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: NULL pointers can't move. 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 May 15 11:45:17 2009 @@ -335,7 +335,8 @@ for op in operations: for i in range(len(op.args)): v = op.args[i] - if isinstance(v, ConstPtr) and rgc.can_move(v.value): + if (isinstance(v, ConstPtr) and v.value + and rgc.can_move(v.value)): box = BoxPtr(v.value) addr = gcrefs.get_address_of_gcref(v.value) addr = rffi.cast(lltype.Signed, addr) From arigo at codespeak.net Fri May 15 14:28:01 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 May 2009 14:28:01 +0200 (CEST) Subject: [pypy-svn] r65268 - in pypy/branch/pyjitpl5/pypy/rpython: lltypesystem memory/gc memory/gctransform Message-ID: <20090515122801.87C9A169EAF@codespeak.net> Author: arigo Date: Fri May 15 14:27:58 2009 New Revision: 65268 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/rpython/memory/gc/generation.py pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Log: In-progress: write barrier support. This just adds the necessary support to the GC. 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 May 15 14:27:58 2009 @@ -388,6 +388,7 @@ 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), 'do_malloc_fixedsize_clear': LLOp(), + 'get_write_barrier_failing_case': LLOp(sideeffects=False), # __________ GC operations __________ Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gc/generation.py Fri May 15 14:27:58 2009 @@ -407,6 +407,10 @@ continue # no need to remember this weakref any longer self.objects_with_weakrefs.append(obj) + # for the JIT: a minimal description of the write_barrier() method + JIT_WB_IF_FLAG = GCFLAG_NO_YOUNG_PTRS + JIT_WB_THEN_CALL = 'remember_young_pointer' + def write_barrier(self, newvalue, addr_struct): if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) Modified: pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/memory/gctransform/framework.py Fri May 15 14:27:58 2009 @@ -340,6 +340,12 @@ annmodel.SomeAddress()], annmodel.s_None, inline=True) + func = getattr(GCClass, GCClass.JIT_WB_THEN_CALL).im_func + self.write_barrier_failing_case_ptr = getfn(func, + [s_gc, + annmodel.SomeAddress(), + annmodel.SomeAddress()], + annmodel.s_None) else: self.write_barrier_ptr = None self.statistics_ptr = getfn(GCClass.statistics.im_func, @@ -607,6 +613,15 @@ v_has_finalizer, v_contains_weakptr], resultvar=op.result) + def gct_get_write_barrier_failing_case(self, hop): + op = hop.spaceop + c_result = rmodel.inputconst( + lltype.typeOf(self.write_barrier_failing_case_ptr), + self.write_barrier_failing_case_ptr) + hop.genop("same_as", + [c_result], + resultvar=op.result) + def gct_zero_gc_pointers_inside(self, hop): if not self.malloc_zero_filled: v_ob = hop.spaceop.args[0] From antocuni at codespeak.net Fri May 15 15:07:26 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 May 2009 15:07:26 +0200 (CEST) Subject: [pypy-svn] r65269 - pypy/trunk/pypy/translator/cli/test Message-ID: <20090515130726.8956A169F6F@codespeak.net> Author: antocuni Date: Fri May 15 15:07:26 2009 New Revision: 65269 Modified: pypy/trunk/pypy/translator/cli/test/test_carbonpython.py Log: fix this test as well. I wonder if the failures might be caused by some race condition when writing tmp.cs Modified: pypy/trunk/pypy/translator/cli/test/test_carbonpython.py ============================================================================== --- pypy/trunk/pypy/translator/cli/test/test_carbonpython.py (original) +++ pypy/trunk/pypy/translator/cli/test/test_carbonpython.py Fri May 15 15:07:26 2009 @@ -145,6 +145,7 @@ assert res == 42 def test_compile_dll(self): + py.test.skip('This test fails every other day. No clue why :-(') cwd, _ = os.path.split(__file__) mylib_py = os.path.join(cwd, 'mylib.py') compile_dll(mylib_py, copy_dll=False) From antocuni at codespeak.net Fri May 15 15:24:12 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 May 2009 15:24:12 +0200 (CEST) Subject: [pypy-svn] r65270 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090515132412.6338F169FB9@codespeak.net> Author: antocuni Date: Fri May 15 15:24:11 2009 New Revision: 65270 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Log: fix or skip the recently added tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Fri May 15 15:24:11 2009 @@ -18,7 +18,7 @@ is_oo = True def __init__(self, rtyper, stats, translate_support_code=False, - mixlevelann=None): + mixlevelann=None, gcdescr=None): self.rtyper = rtyper if rtyper: assert rtyper.type_system.name == "ootypesystem" Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Fri May 15 15:24:11 2009 @@ -29,11 +29,14 @@ test_print = skip test_bridge_from_interpreter_2 = skip test_bridge_from_interpreter_3 = skip + test_bridge_leaving_interpreter_5 = skip test_instantiate_classes = skip test_zerodivisionerror = skip test_isinstance = skip test_oois = skip test_oostring_instance = skip + test_long_long = skip + test_free_object = skip test_stopatxpolicy = _skip test_bridge_from_interpreter = _skip Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_runner.py Fri May 15 15:24:11 2009 @@ -27,4 +27,5 @@ test_failing_guard_class = skip # GUARD_CLASS def test_ovf_operations(self, reversed=False): - py.test.skip('fixme') + if reversed: + py.test.skip('fixme') From antocuni at codespeak.net Fri May 15 18:12:58 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 May 2009 18:12:58 +0200 (CEST) Subject: [pypy-svn] r65271 - in pypy/branch/pyjitpl5/pypy: config jit/backend/cli/test jit/backend/test Message-ID: <20090515161258.3099C169FD6@codespeak.net> Author: antocuni Date: Fri May 15 18:12:56 2009 New Revision: 65271 Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py Log: some tests failed because the gc was set to "ref"; fix that, and skip other tests that are still failing Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/config/translationoption.py (original) +++ pypy/branch/pyjitpl5/pypy/config/translationoption.py Fri May 15 18:12:56 2009 @@ -30,6 +30,7 @@ ("translation.backendopt.heap2stack", False), ("translation.backendopt.clever_malloc_removal", False), ("translation.list_comprehension_operations", False), + ("translation.gc", "generation"), # it's not really used, but some jit code expects a value here ] }), ChoiceOption("backend", "Backend to use for code generation", Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Fri May 15 18:12:56 2009 @@ -26,3 +26,6 @@ test_bridge_from_interpreter_2 = skip test_bridge_from_interpreter_3 = skip test_bridge_from_interpreter_4 = skip + test_bridge_leaving_interpreter_5 = skip + test_free_object = skip + test_we_are_jitted = skip Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py Fri May 15 18:12:56 2009 @@ -24,6 +24,7 @@ assert isinstance(arg, int) t = self._get_TranslationContext() + t.config.translation.type_system = self.type_system # force typesystem-specific options if repeat != 1: src = py.code.Source(""" def entry_point(argv): From antocuni at codespeak.net Fri May 15 18:23:09 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 May 2009 18:23:09 +0200 (CEST) Subject: [pypy-svn] r65272 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090515162309.D38C6169FD5@codespeak.net> Author: antocuni Date: Fri May 15 18:23:08 2009 New Revision: 65272 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Log: add a comment about a failing test Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Fri May 15 18:23:08 2009 @@ -28,4 +28,6 @@ test_bridge_from_interpreter_4 = skip test_bridge_leaving_interpreter_5 = skip test_free_object = skip - test_we_are_jitted = skip + + def test_we_are_jitted(self): + py.test.skip("it seems to fail even with the x86 backend, didn't investigate the problem") From antocuni at codespeak.net Fri May 15 19:19:23 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 May 2009 19:19:23 +0200 (CEST) Subject: [pypy-svn] r65273 - in pypy/branch/pyjitpl5/pypy: annotation rpython/ootypesystem rpython/ootypesystem/test Message-ID: <20090515171923.42D5C169FB9@codespeak.net> Author: antocuni Date: Fri May 15 19:19:21 2009 New Revision: 65273 Modified: pypy/branch/pyjitpl5/pypy/annotation/builtin.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Log: implement cast_to_object for SomeOOStaticMethods Modified: pypy/branch/pyjitpl5/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/annotation/builtin.py (original) +++ pypy/branch/pyjitpl5/pypy/annotation/builtin.py Fri May 15 19:19:21 2009 @@ -569,8 +569,9 @@ raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const) def cast_to_object(obj): - assert isinstance(obj.ootype, ootype.OOType) or \ - (isinstance(obj, SomeOOClass) and obj.ootype is None) + assert isinstance(obj, SomeOOStaticMeth) or \ + (isinstance(obj, SomeOOClass) and obj.ootype is None) or \ + isinstance(obj.ootype, ootype.OOType) return SomeOOObject() def cast_from_object(T, obj): Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py Fri May 15 19:19:21 2009 @@ -60,8 +60,9 @@ return hop.genop('oodowncast', [v_inst], resulttype = hop.r_result.lowleveltype) def rtype_cast_to_object(hop): - assert isinstance(hop.args_s[0].ootype, ootype.OOType) or \ - isinstance(hop.args_s[0], annmodel.SomeOOClass) + assert isinstance(hop.args_s[0], annmodel.SomeOOStaticMeth) or \ + isinstance(hop.args_s[0], annmodel.SomeOOClass) or \ + isinstance(hop.args_s[0].ootype, ootype.OOType) v_inst = hop.inputarg(hop.args_r[0], arg=0) return hop.genop('cast_to_object', [v_inst], resulttype = hop.r_result.lowleveltype) Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Fri May 15 19:19:21 2009 @@ -471,3 +471,21 @@ res = interpret(fn, [], type_system='ootype') assert cast_from_object(Class, res) == nullruntimeclass + +def test_cast_to_object_static_meth(): + from pypy.rpython.annlowlevel import llhelper + FUNC = StaticMethod([Signed], Signed) + def f(x): + return x+1 + fptr = llhelper(FUNC, f) + + def fn(x): + if x: + obj = cast_to_object(fptr) + else: + obj = NULL + myfunc = cast_from_object(FUNC, obj) + return myfunc(x) + + res = interpret(fn, [1], type_system='ootype') + assert res == 2 From pedronis at codespeak.net Sat May 16 10:01:27 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 16 May 2009 10:01:27 +0200 (CEST) Subject: [pypy-svn] r65274 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090516080127.66AD2169EB9@codespeak.net> Author: pedronis Date: Sat May 16 10:01:26 2009 New Revision: 65274 Added: pypy/extradoc/sprintinfo/ep2009/ pypy/extradoc/sprintinfo/ep2009/announcement.txt pypy/extradoc/sprintinfo/ep2009/people.txt Log: drafting sprint info for ep2009 Added: pypy/extradoc/sprintinfo/ep2009/announcement.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/ep2009/announcement.txt Sat May 16 10:01:26 2009 @@ -0,0 +1,76 @@ +================================================================== +Birmingham (UK) EuroPython PyPy Sprints 28-29 June/ 3-4 July 2009 +================================================================== + +The PyPy team is sprinting at EuroPython again. This year there are +`sprint days`_ before (28-29 June) and after (3-4 July) the +conference. Some PyPy core people should be present during both periods. + +.. _`sprint days`: http://wiki.europython.eu/Sprints + +If you plan to attend the sprints after the conference we recommend +you to listen to the PyPy technical talk (`EuroPython schedule`_) +during the conference since it will give you a good overview of the +status of development. + +XXX When/if tutorial? +On the morning of the first sprint day we will also have a +tutorial session for those new to PyPy development. + +------------------------------ +Goals and topics of the sprint +------------------------------ + +There are many possible and interesting sprint topics to work on - here +we list some possible task areas: + +XXX + +------------ +Registration +------------ + +If you'd like to come, please subscribe to the `pypy-sprint mailing list`_ +and drop a note about your interests and post any questions. More +organisational information will be sent to that list. + +Please register by adding yourself on the following list (via svn): + + http://codespeak.net/svn/pypy/extradoc/sprintinfo/ep2009/people.txt + +or on the pypy-sprint mailing list if you do not yet have check-in rights: + + http://codespeak.net/mailman/listinfo/pypy-sprint + +--------------------------------------- +Preparation (if you feel it is needed): +--------------------------------------- + +* read the `getting-started`_ pages on http://codespeak.net/pypy, + especially also the `development of PyPy itself part`_ . + +* for inspiration, overview and technical status you are welcome to + read `the technical reports available and other relevant documentation`_ + +* please direct any technical and/or development oriented questions to + pypy-dev at codespeak.net and any sprint organizing/logistical + questions to pypy-sprint at codespeak.net + +* if you need information about the conference, potential hotels, + directions etc we recommend to look at http://www.europython.eu. + + +We are looking forward to meet you at the EuroPython PyPy sprints! + +The PyPy team + + +.. See also .. + +.. _getting-started: http://codespeak.net/pypy/dist/pypy/doc/getting-started.html +.. _`development of PyPy itself part`: http://codespeak.net/pypy/dist/pypy/doc/getting-started-dev.html + +.. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint +.. _`the technical reports available and other relevant documentation`: http://codespeak.net/pypy/dist/pypy/doc/docindex.html + +.. _`EuroPython schedule`: http://europython.eu/XXX Added: pypy/extradoc/sprintinfo/ep2009/people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/ep2009/people.txt Sat May 16 10:01:26 2009 @@ -0,0 +1,56 @@ + +People coming to the EuroPython Sprints (Birmingham) 29-29 June/3-4 July 2009 +=============================================================================== + +People who have a ``?`` in their arrive/depart or accomodation +column are known to be coming but there are no details +available yet from them. + + +==================== ============== ============================ + Name Arrive/Depart Accomodation +==================== ============== ============================ +? ? ? +==================== ============== ============================ + +People on the following list were present at previous sprints: + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +Alexander Schremmer ? ? +Alexandre Fayolle ? ? +Amaury Forgeot d'Arc ? ? +Anders Chrigstroem ? ? +Anders Lehmann ? ? +Andrew Thompson ? ? +Antonio Cuni ? ? +Armin Rigo ? ? +Beatrice Duering ? ? +Bert Freudenberg ? ? +Boris Feigin ? ? +Camillo Bruni ? ? +Carl Friedrich Bolz ? ? +Christian Tismer ? ? +Eric van Riet Paap ? ? +Guido Wesdorp ? ? +Holger Krekel ? ? +Jacob Hallen ? ? +Jakub Gustak ? ? +Johan Hahn ? ? +Laura Creighton ? ? +Lene Wagner ? ? +Leonardo Santagada ? ? +Maciej Fijalkowski ? ? +Michael Hudson ? ? +Niklaus Haldimann ? ? +Niko Matsakis ? ? +Paul deGrandis ? ? +Richard Emslie ? ? +Samuele Pedroni ? ? +Stephan Diehl ? ? +Sylvain Th?nault ? ? +Toby Watson ? ? +Toon Verwaest ? ? +Valentino Volonghi ? ? +==================== ============== ===================== From antocuni at codespeak.net Sat May 16 10:29:40 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 16 May 2009 10:29:40 +0200 (CEST) Subject: [pypy-svn] r65275 - in pypy/branch/pyjitpl5/pypy/rpython/ootypesystem: . test Message-ID: <20090516082940.261CD169E71@codespeak.net> Author: antocuni Date: Sat May 16 10:29:38 2009 New Revision: 65275 Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Log: teach the rtyper how to handle ootype.instanceof Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rbuiltin.py Sat May 16 10:29:38 2009 @@ -36,6 +36,13 @@ return hop.genop('subclassof', vlist, resulttype = ootype.Bool) +def rtype_instanceof(hop): + INSTANCE = hop.args_v[1].value + v_inst = hop.inputarg(hop.args_r[0], arg=0) + c_cls = hop.inputconst(ootype.Void, INSTANCE) + return hop.genop('instanceof', [v_inst, c_cls], + resulttype=ootype.Bool) + def rtype_runtimenew(hop): vlist = hop.inputargs(rootype.ooclass_repr) return hop.genop('runtimenew', vlist, @@ -123,6 +130,7 @@ BUILTIN_TYPER[ootype.null] = rtype_null BUILTIN_TYPER[ootype.classof] = rtype_classof BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof +BUILTIN_TYPER[ootype.instanceof] = rtype_instanceof BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash BUILTIN_TYPER[ootype.ooupcast] = rtype_ooupcast Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/test/test_oortype.py Sat May 16 10:29:38 2009 @@ -489,3 +489,19 @@ res = interpret(fn, [1], type_system='ootype') assert res == 2 + +def test_instanceof(): + A = Instance('A', ootype.ROOT, {}) + B = Instance('B', A, {}) + + def fn(x): + if x: + obj = ooupcast(A, new(B)) + else: + obj = new(A) + return instanceof(obj, B) + + res = interpret(fn, [0], type_system='ootype') + assert not res + res = interpret(fn, [1], type_system='ootype') + assert res From pedronis at codespeak.net Sat May 16 10:31:40 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 16 May 2009 10:31:40 +0200 (CEST) Subject: [pypy-svn] r65276 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090516083140.6FC01169EB8@codespeak.net> Author: pedronis Date: Sat May 16 10:31:39 2009 New Revision: 65276 Modified: pypy/extradoc/sprintinfo/ep2009/people.txt Log: my dates, fix date in the headings Modified: pypy/extradoc/sprintinfo/ep2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/people.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/people.txt Sat May 16 10:31:39 2009 @@ -1,5 +1,5 @@ -People coming to the EuroPython Sprints (Birmingham) 29-29 June/3-4 July 2009 +People coming to the EuroPython Sprints (Birmingham) 28-29 June/3-4 July 2009 =============================================================================== People who have a ``?`` in their arrive/depart or accomodation @@ -10,7 +10,7 @@ ==================== ============== ============================ Name Arrive/Depart Accomodation ==================== ============== ============================ -? ? ? +Samuele Pedroni 28/5 ? ==================== ============== ============================ People on the following list were present at previous sprints: @@ -47,7 +47,6 @@ Niko Matsakis ? ? Paul deGrandis ? ? Richard Emslie ? ? -Samuele Pedroni ? ? Stephan Diehl ? ? Sylvain Th?nault ? ? Toby Watson ? ? From antocuni at codespeak.net Sat May 16 11:08:30 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 16 May 2009 11:08:30 +0200 (CEST) Subject: [pypy-svn] r65277 - pypy/trunk/pypy/translator/cli/test Message-ID: <20090516090830.6BD28169E3B@codespeak.net> Author: antocuni Date: Sat May 16 11:08:29 2009 New Revision: 65277 Modified: pypy/trunk/pypy/translator/cli/test/test_carbonpython.py Log: bah, skip the whole test :-/ Modified: pypy/trunk/pypy/translator/cli/test/test_carbonpython.py ============================================================================== --- pypy/trunk/pypy/translator/cli/test/test_carbonpython.py (original) +++ pypy/trunk/pypy/translator/cli/test/test_carbonpython.py Sat May 16 11:08:29 2009 @@ -1,4 +1,6 @@ import py +py.test.skip("it passes usually, but fails on buildbot, no clue why") + import os import os.path from pypy.tool import udir From antocuni at codespeak.net Sat May 16 11:34:58 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 16 May 2009 11:34:58 +0200 (CEST) Subject: [pypy-svn] r65282 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090516093458.F0B41169EBA@codespeak.net> Author: antocuni Date: Sat May 16 11:34:58 2009 New Revision: 65282 Modified: pypy/extradoc/sprintinfo/ep2009/people.txt Log: my dates Modified: pypy/extradoc/sprintinfo/ep2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/people.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/people.txt Sat May 16 11:34:58 2009 @@ -11,6 +11,7 @@ Name Arrive/Depart Accomodation ==================== ============== ============================ Samuele Pedroni 28/5 ? +Antonio Cuni 28/4 ETAPS Hotel (shared with cfbolz) ==================== ============== ============================ People on the following list were present at previous sprints: From fijal at codespeak.net Sun May 17 20:11:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 17 May 2009 20:11:27 +0200 (CEST) Subject: [pypy-svn] r65283 - pypy/build/bot2/pypybuildbot Message-ID: <20090517181127.2386F169DFB@codespeak.net> Author: fijal Date: Sun May 17 20:11:26 2009 New Revision: 65283 Modified: pypy/build/bot2/pypybuildbot/master.py Log: fix the category Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sun May 17 20:11:26 2009 @@ -120,7 +120,7 @@ "slavenames": ["bigdogvm1"], 'builddir' : JITLINUX32, 'factory' : pypyJITTranslatedTestFactory, - 'category' : 'other', + 'category' : 'lib-python', } ], From fijal at codespeak.net Sun May 17 22:30:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 17 May 2009 22:30:10 +0200 (CEST) Subject: [pypy-svn] r65284 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090517203010.3AE9016856F@codespeak.net> Author: fijal Date: Sun May 17 22:30:09 2009 New Revision: 65284 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: a rare case where type inference is actually useful with detecting bugs. 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 Sun May 17 22:30:09 2009 @@ -676,6 +676,7 @@ for TYPE in green_args_spec: if not equal_whatever(TYPE, greenargs1[i], greenargs2[i]): return False + i = i + 1 return True comparekey = staticmethod(comparekey) From fijal at codespeak.net Sun May 17 22:46:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 17 May 2009 22:46:51 +0200 (CEST) Subject: [pypy-svn] r65285 - pypy/branch/pyjitpl5/pypy/rlib Message-ID: <20090517204651.1154016857B@codespeak.net> Author: fijal Date: Sun May 17 22:46:47 2009 New Revision: 65285 Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py Log: experimental. Try to avoid tracing so much, increase parameters to *something* Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/jit.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/jit.py Sun May 17 22:46:47 2009 @@ -78,8 +78,8 @@ class JitHintError(Exception): """Inconsistency in the JIT hints.""" -PARAMETERS = {'threshold': 40, - 'trace_eagerness': 10, +PARAMETERS = {'threshold': 1000, + 'trace_eagerness': 200, 'hash_bits': 14, } unroll_parameters = unrolling_iterable(PARAMETERS.keys()) From fijal at codespeak.net Sun May 17 22:48:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 17 May 2009 22:48:57 +0200 (CEST) Subject: [pypy-svn] r65286 - pypy/branch/pyjitpl5/pypy/rlib Message-ID: <20090517204857.29824168562@codespeak.net> Author: fijal Date: Sun May 17 22:48:56 2009 New Revision: 65286 Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py Log: missing exception_cannot_occur Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/jit.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/jit.py Sun May 17 22:48:56 2009 @@ -302,6 +302,7 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype + hop.exception_cannot_occur() driver = self.instance.im_self name = hop.args_s[0].const v_value = hop.inputarg(lltype.Signed, arg=1) From fijal at codespeak.net Sun May 17 23:11:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 17 May 2009 23:11:31 +0200 (CEST) Subject: [pypy-svn] r65287 - pypy/branch/pyjitpl5/pypy/translator/platform Message-ID: <20090517211131.03CEC168569@codespeak.net> Author: fijal Date: Sun May 17 23:11:31 2009 New Revision: 65287 Modified: pypy/branch/pyjitpl5/pypy/translator/platform/linux.py Log: I think the time is now to have -O3 as default Modified: pypy/branch/pyjitpl5/pypy/translator/platform/linux.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/platform/linux.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/platform/linux.py Sun May 17 23:11:31 2009 @@ -9,7 +9,7 @@ name = "linux" link_flags = ['-pthread'] - cflags = ['-O0', '-pthread', '-fomit-frame-pointer'] + cflags = ['-O3', '-pthread', '-fomit-frame-pointer'] standalone_only = [] shared_only = [] so_ext = 'so' From antocuni at codespeak.net Mon May 18 10:18:00 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 10:18:00 +0200 (CEST) Subject: [pypy-svn] r65288 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli/test rpython/ootypesystem Message-ID: <20090518081800.DD8461684CC@codespeak.net> Author: antocuni Date: Mon May 18 10:17:58 2009 New Revision: 65288 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py Log: delay the search of methods until we are sure that all the reprs we depend on have been computed. This fix a bug that was shown by test_three_cases, but I didn't manage to reproduce a smaller failing test :-/ test_three_cases now proceed, but still fails for other reasons Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Mon May 18 10:17:58 2009 @@ -16,7 +16,6 @@ test_three_receivers = skip_loop test_three_classes = skip_loop test_recursive_call_to_portal_from_blackhole = skip_loop - - test_indirect_call_unknown_object_1 = skip # cast_to_object of StaticMethods - test_three_cases = skip # seems an annotator bug :-/ + test_indirect_call_unknown_object_1 = skip_loop + #test_three_cases = skip_loop Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py Mon May 18 10:17:58 2009 @@ -264,7 +264,6 @@ self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() - methods = {} classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) @@ -275,32 +274,6 @@ oovalue = classrepr.get_meta_instance() self.attach_class_attr_accessor('getmeta', oovalue) - for mangled, (name, s_value) in allmethods.iteritems(): - methdescs = s_value.descriptions - origin = dict([(methdesc.originclassdef, methdesc) for - methdesc in methdescs]) - if self.classdef in origin: - methdesc = origin[self.classdef] - else: - if name in selfattrs: - for superdef in self.classdef.getmro(): - if superdef in origin: - # put in methods - methdesc = origin[superdef] - break - else: - # abstract method - methdesc = None - else: - continue - - # get method implementation - from pypy.rpython.ootypesystem.rpbc import MethodImplementations - methimpls = MethodImplementations.get(self.rtyper, s_value) - m_impls = methimpls.get_impl(mangled, methdesc, - is_finalizer=name == "__del__") - - methods.update(m_impls) for classdef in self.classdef.getmro(): @@ -326,8 +299,6 @@ if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value - ootype.addMethods(self.lowleveltype, methods) - self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes @@ -342,6 +313,41 @@ ootype.addFields(self.lowleveltype, {mangled: (oot, impl)}) def _setup_repr_final(self): + if self.classdef is None: + return + + # we attach methods here and not in _setup(), because we want + # to be sure that all the reprs of the input arguments of all + # our methods have been computed at this point + methods = {} + selfattrs = self.classdef.attrs + for mangled, (name, s_value) in self.allmethods.iteritems(): + methdescs = s_value.descriptions + origin = dict([(methdesc.originclassdef, methdesc) for + methdesc in methdescs]) + if self.classdef in origin: + methdesc = origin[self.classdef] + else: + if name in selfattrs: + for superdef in self.classdef.getmro(): + if superdef in origin: + # put in methods + methdesc = origin[superdef] + break + else: + # abstract method + methdesc = None + else: + continue + # get method implementation + from pypy.rpython.ootypesystem.rpbc import MethodImplementations + methimpls = MethodImplementations.get(self.rtyper, s_value) + m_impls = methimpls.get_impl(mangled, methdesc, + is_finalizer=name == "__del__") + methods.update(m_impls) + ootype.addMethods(self.lowleveltype, methods) + + # step 3: provide accessor methods for class attributes that # are really overridden in subclasses. Must be done here # instead of _setup_repr to avoid recursion problems if class From antocuni at codespeak.net Mon May 18 10:18:44 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 10:18:44 +0200 (CEST) Subject: [pypy-svn] r65289 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090518081844.E54A31684CE@codespeak.net> Author: antocuni Date: Mon May 18 10:18:44 2009 New Revision: 65289 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: ops, this test was meant to be skipped Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Mon May 18 10:18:44 2009 @@ -17,5 +17,5 @@ test_three_classes = skip_loop test_recursive_call_to_portal_from_blackhole = skip_loop test_indirect_call_unknown_object_1 = skip_loop - #test_three_cases = skip_loop + test_three_cases = skip_loop From antocuni at codespeak.net Mon May 18 10:21:59 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 10:21:59 +0200 (CEST) Subject: [pypy-svn] r65290 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090518082159.6A8141684CC@codespeak.net> Author: antocuni Date: Mon May 18 10:21:58 2009 New Revision: 65290 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: add new tests Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Mon May 18 10:21:58 2009 @@ -10,9 +10,6 @@ def skip_loop(self): py.test.skip('jump across loops not implemented yet') - def skip(self): - py.test.skip('in-progress') - test_three_receivers = skip_loop test_three_classes = skip_loop test_recursive_call_to_portal_from_blackhole = skip_loop Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py Mon May 18 10:21:58 2009 @@ -0,0 +1,15 @@ +import py +from pypy.jit.backend.cli.test.test_zrpy_basic import CliTranslatedJitMixin +from pypy.jit.metainterp.test import test_slist + + +class TestSList(CliTranslatedJitMixin, test_slist.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_slist.py + + def skip(self): + py.test.skip('in-progress') + + + test_lazy_getitem_1 = skip + test_lazy_getitem_4 = skip From antocuni at codespeak.net Mon May 18 10:47:18 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 10:47:18 +0200 (CEST) Subject: [pypy-svn] r65292 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090518084718.EF04A1684B5@codespeak.net> Author: antocuni Date: Mon May 18 10:47:15 2009 New Revision: 65292 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py Log: implement {get,set}arrayitem_gc. test_lazy_getitem_1 mostly passes, but it's skipped at the end Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 18 10:47:15 2009 @@ -381,14 +381,39 @@ op.args[1].load(self) self.il.Emit(OpCodes.Stfld, fieldinfo) + def emit_op_getarrayitem_gc(self, op): + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + clitype = descr.get_array_clitype() + itemtype = descr.get_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Castclass, clitype) + op.args[1].load(self) + self.il.Emit(OpCodes.Ldelem, itemtype) + self.store_result(op) + + emit_op_getarrayitem_gc_pure = emit_op_getarrayitem_gc + + def emit_op_setarrayitem_gc(self, op): + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + clitype = descr.get_array_clitype() + itemtype = descr.get_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Castclass, clitype) + op.args[1].load(self) + op.args[2].load(self) + self.il.Emit(OpCodes.Stelem, itemtype) + def emit_op_arraylen_gc(self, op): + raise NotImplementedError + def not_implemented(self, op): raise NotImplementedError emit_op_guard_exception = not_implemented emit_op_cast_int_to_ptr = not_implemented emit_op_guard_nonvirtualized = not_implemented - emit_op_setarrayitem_gc = not_implemented emit_op_unicodelen = not_implemented emit_op_setfield_raw = not_implemented emit_op_cast_ptr_to_int = not_implemented @@ -397,11 +422,8 @@ emit_op_unicodegetitem = not_implemented emit_op_strgetitem = not_implemented emit_op_getfield_raw = not_implemented - emit_op_getarrayitem_gc_pure = not_implemented - emit_op_arraylen_gc = not_implemented emit_op_unicodesetitem = not_implemented emit_op_getfield_raw_pure = not_implemented - emit_op_getarrayitem_gc = not_implemented emit_op_strlen = not_implemented emit_op_newstr = not_implemented emit_op_strsetitem = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 18 10:47:15 2009 @@ -43,6 +43,12 @@ def typedescrof(self, TYPE): return TypeDescr(TYPE) + @cached_method('_arraycache') + def arraydescrof(self, A): + assert isinstance(A, ootype.Array) + TYPE = A.ITEM + return TypeDescr(TYPE) + @cached_method('_fieldcache') def fielddescrof(self, T, fieldname): return FieldDescr(T, fieldname) @@ -131,24 +137,62 @@ argboxes = args[1:] return descr.callmeth(selfbox, argboxes) + def do_getarrayitem_gc(self, args, descr): + assert isinstance(descr, TypeDescr) + assert len(args) == 2 + arraybox = args[0] + ibox = args[1] + return descr.getarrayitem(arraybox, ibox) + + def do_setarrayitem_gc(self, args, descr): + assert isinstance(descr, TypeDescr) + assert len(args) == 3 + arraybox = args[0] + ibox = args[1] + valuebox = args[2] + descr.setarrayitem(arraybox, ibox, valuebox) + # ---------------------------------------------------------------------- key_manager = KeyManager() +def get_class_for_type(T): + if T is ootype.Void: + return ootype.nullruntimeclass + elif T is ootype.Signed: + return dotnet.classof(System.Int32) + elif T is ootype.Bool: + return dotnet.classof(System.Boolean) + elif T is ootype.Float: + return dotnet.classof(System.Double) +## elif T is ootype.String: +## return dotnet.classof(System.String) + elif T is ootype.Char: + return dotnet.classof(System.Char) + elif isinstance(T, ootype.OOType): + return ootype.runtimeClass(T) + else: + assert False + class TypeDescr(AbstractDescr): def __init__(self, TYPE): from pypy.jit.backend.llgraph.runner import boxresult + from pypy.jit.metainterp.warmspot import unwrap + ARRAY = ootype.Array(TYPE) def create(): - return boxresult(TYPE, ootype.new(TYPE)) + if isinstance(TYPE, ootype.OOType): + return boxresult(TYPE, ootype.new(TYPE)) + return None def create_array(lengthbox): n = lengthbox.getint() return boxresult(ARRAY, ootype.oonewarray(ARRAY, n)) def getarrayitem(arraybox, ibox): array = ootype.cast_from_object(ARRAY, arraybox.getobj()) i = ibox.getint() - return boxresult(TYPE, array.ll_getitem_fast(i)) + if TYPE is not ootype.Void: + return boxresult(TYPE, array.ll_getitem_fast(i)) def setarrayitem(arraybox, ibox, valuebox): array = ootype.cast_from_object(ARRAY, arraybox.getobj()) i = ibox.getint() @@ -158,19 +202,25 @@ array = ootype.cast_from_object(ARRAY, arraybox.getobj()) return boxresult(ootype.Signed, array.ll_length()) def instanceof(box): - obj = ootype.cast_from_object(ootype.ROOT, box.getobj()) - return history.BoxInt(ootype.instanceof(obj, TYPE)) + if isinstance(TYPE, ootype.Instance): + obj = ootype.cast_from_object(ootype.ROOT, box.getobj()) + return BoxInt(ootype.instanceof(obj, TYPE)) + return None self.create = create self.create_array = create_array self.getarrayitem = getarrayitem self.setarrayitem = setarrayitem self.getarraylength = getarraylength self.instanceof = instanceof - self.ooclass = ootype.runtimeClass(TYPE) + self.ooclass = get_class_for_type(TYPE) + self.ooarrayclass = get_class_for_type(ARRAY) def get_clitype(self): return dotnet.class2type(self.ooclass) + def get_array_clitype(self): + return dotnet.class2type(self.ooarrayclass) + def get_constructor_info(self): clitype = self.get_clitype() return clitype.GetConstructor(dotnet.new_array(System.Type, 0)) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py Mon May 18 10:47:15 2009 @@ -11,5 +11,4 @@ py.test.skip('in-progress') - test_lazy_getitem_1 = skip test_lazy_getitem_4 = skip From antocuni at codespeak.net Mon May 18 10:53:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 10:53:04 +0200 (CEST) Subject: [pypy-svn] r65293 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090518085304.9507B1684BC@codespeak.net> Author: antocuni Date: Mon May 18 10:53:03 2009 New Revision: 65293 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py Log: implement arraylen_gc. test_lazy_getitem_4 mostly passes, but it's skipped at the end Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 18 10:53:03 2009 @@ -406,7 +406,13 @@ self.il.Emit(OpCodes.Stelem, itemtype) def emit_op_arraylen_gc(self, op): - raise NotImplementedError + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + clitype = descr.get_array_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Castclass, clitype) + self.il.Emit(OpCodes.Ldlen) + self.store_result(op) def not_implemented(self, op): raise NotImplementedError Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 18 10:53:03 2009 @@ -151,7 +151,12 @@ ibox = args[1] valuebox = args[2] descr.setarrayitem(arraybox, ibox, valuebox) - + + def do_arraylen_gc(self, args, descr): + assert isinstance(descr, TypeDescr) + assert len(args) == 1 + arraybox = args[0] + return descr.getarraylength(arraybox) # ---------------------------------------------------------------------- key_manager = KeyManager() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_slist.py Mon May 18 10:53:03 2009 @@ -6,9 +6,4 @@ class TestSList(CliTranslatedJitMixin, test_slist.TestOOtype): # for the individual tests see # ====> ../../../metainterp/test/test_slist.py - - def skip(self): - py.test.skip('in-progress') - - - test_lazy_getitem_4 = skip + pass From antocuni at codespeak.net Mon May 18 11:25:25 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 11:25:25 +0200 (CEST) Subject: [pypy-svn] r65294 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090518092525.3DC571684C9@codespeak.net> Author: antocuni Date: Mon May 18 11:25:24 2009 New Revision: 65294 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Log: this test passes nowadays Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Mon May 18 11:25:24 2009 @@ -19,7 +19,6 @@ def skip(self): py.test.skip('in-progress') - test_constant_across_mp = skip test_stopatxpolicy = skip test_print = skip test_bridge_from_interpreter = skip From antocuni at codespeak.net Mon May 18 15:46:50 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 15:46:50 +0200 (CEST) Subject: [pypy-svn] r65295 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090518134650.64DC01684BA@codespeak.net> Author: antocuni Date: Mon May 18 15:46:47 2009 New Revision: 65295 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (contents, props changed) Log: more tests Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Mon May 18 15:46:47 2009 @@ -0,0 +1,29 @@ +import py +from pypy.jit.backend.cli.test.test_zrpy_basic import CliTranslatedJitMixin +from pypy.jit.metainterp.test import test_exception + + +class TestException(CliTranslatedJitMixin, test_exception.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_exception.py + + def skip_loop(self): + py.test.skip('jump across loops not implemented yet') + + def skip(self): + py.test.skip('in-progress') + + test_bridge_from_guard_exception = skip + test_bridge_from_guard_no_exception = skip + test_exception_from_outside = skip + test_exception_from_outside_2 = skip + test_exception_two_cases = skip + test_exception_two_cases_2 = skip + test_exception_four_cases = skip + test_exception_later = skip + test_exception_and_then_no_exception = skip + test_raise_through_wrong_exc_2 = skip + test_int_ovf = skip + test_int_lshift_ovf = skip + test_bridge_from_interpreter_exc = skip + test_bridge_from_interpreter_exc_2 = skip From antocuni at codespeak.net Mon May 18 17:09:40 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 17:09:40 +0200 (CEST) Subject: [pypy-svn] r65296 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090518150940.189721684A9@codespeak.net> Author: antocuni Date: Mon May 18 17:09:38 2009 New Revision: 65296 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Log: - implement runner.get_{exception,exc_value} - do calls inside a try/catch block (both during tracing and in the generated code) - implement emit_op_guard_exception - the first half of test_bridge_from_guard_exception passes, the second still fails because we don't support bridges Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 18 17:09:38 2009 @@ -256,6 +256,10 @@ self.il.Emit(OpCodes.Stfld, self.exc_value_field) self.il.EndExceptionBlock() + def mark(self, msg): + self.il.Emit(OpCodes.Ldstr, msg) + self.il.Emit(OpCodes.Pop) + # -------------------------------- def emit_op_fail(self, op): @@ -309,6 +313,18 @@ self.il.Emit(OpCodes.Ldfld, self.exc_value_field) self.il.Emit(OpCodes.Brtrue, il_label) + def emit_op_guard_exception(self, op): + assert op.suboperations + il_label = self.newbranch(op) + classbox = op.args[0] + assert isinstance(classbox, ConstObj) + oocls = ootype.cast_from_object(ootype.Class, classbox.getobj()) + clitype = dotnet.class2type(oocls) + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldfld, self.exc_value_field) + self.il.Emit(OpCodes.Isinst, clitype) + self.il.Emit(OpCodes.Brfalse, il_label) + def emit_op_jump(self, op): target = op.jump_target assert target is self.loop, 'TODO' @@ -331,13 +347,18 @@ def emit_op_ooidentityhash(self, op): raise NotImplementedError - def emit_op_call(self, op): + def emit_op_call_impl(self, op): descr = op.descr assert isinstance(descr, runner.StaticMethDescr) delegate_type = descr.get_delegate_clitype() meth_invoke = descr.get_meth_info() self._emit_call(op, delegate_type, meth_invoke, descr.has_result) + def emit_op_call(self, op): + emit_op = Method.emit_op_call_impl.im_func + exctypes = [dotnet.typeof(System.Exception)] + self.emit_raising_op(op, emit_op, exctypes) + emit_op_call_pure = emit_op_call def emit_op_oosend(self, op): @@ -417,7 +438,6 @@ def not_implemented(self, op): raise NotImplementedError - emit_op_guard_exception = not_implemented emit_op_cast_int_to_ptr = not_implemented emit_op_guard_nonvirtualized = not_implemented emit_op_unicodelen = not_implemented Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 18 17:09:38 2009 @@ -82,12 +82,16 @@ def get_exception(self): exc_value = self.get_inputargs().get_exc_value() if exc_value: - assert False, 'TODO' + exc_obj = dotnet.cast_from_native_object(exc_value) + exc_inst = ootype.cast_from_object(ootype.ROOT, exc_obj) + cls = ootype.classof(exc_value) + return ootype.cast_to_object(cls) return ootype.cast_to_object(ootype.nullruntimeclass) def get_exc_value(self): - if self.get_inputargs().get_exc_value(): - assert False, 'TODO' + exc_value = self.get_inputargs().get_exc_value() + if exc_value: + return dotnet.cast_from_native_object(exc_value) else: return ootype.NULL @@ -129,7 +133,19 @@ def do_call(self, args, calldescr): assert isinstance(calldescr, StaticMethDescr) funcbox, args = args[0], args[1:] - return calldescr.callfunc(funcbox, args) + self.clear_exception() + try: + return calldescr.callfunc(funcbox, args) + except Exception, e: + exc_value = self._cast_instance_to_native_obj(e) + self.get_inputargs().set_exc_value(exc_value) + return calldescr.get_errbox() + + def _cast_instance_to_native_obj(self, e): + from pypy.rpython.annlowlevel import cast_instance_to_base_obj + inst = cast_instance_to_base_obj(e) # SomeOOInstance + obj = ootype.cast_to_object(inst) # SomeOOObject + return dotnet.cast_to_native_object(obj) # System.Object def do_oosend(self, args, descr=None): assert isinstance(descr, MethDescr) @@ -248,6 +264,16 @@ self.callfunc = callfunc self.funcclass = dotnet.classof(FUNC) self.has_result = (FUNC.RESULT != ootype.Void) + if RESULT is ootype.Void: + def get_errbox(): + return None + elif isinstance(RESULT, ootype.OOType): + def get_errbox(): + return BoxObj() + else: + def get_errbox(): + return BoxInt() + self.get_errbox = get_errbox def get_delegate_clitype(self): return dotnet.class2type(self.funcclass) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Mon May 18 17:09:38 2009 @@ -13,7 +13,8 @@ def skip(self): py.test.skip('in-progress') - test_bridge_from_guard_exception = skip + test_bridge_from_guard_exception = skip_loop + test_bridge_from_guard_no_exception = skip test_exception_from_outside = skip test_exception_from_outside_2 = skip From antocuni at codespeak.net Mon May 18 17:33:31 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 17:33:31 +0200 (CEST) Subject: [pypy-svn] r65297 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090518153331.2F057169E34@codespeak.net> Author: antocuni Date: Mon May 18 17:33:30 2009 New Revision: 65297 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Log: actually store the result of guard_exception; more tests pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 18 17:33:30 2009 @@ -87,6 +87,7 @@ class Method(object): operations = [] # overwritten at the end of the module + debug = False def __init__(self, cpu, name, loop): self.cpu = cpu @@ -204,6 +205,8 @@ def emit_operations(self, operations): for op in operations: + if self.debug: + self.il.EmitWriteLine(op.repr()) func = self.operations[op.opnum] assert func is not None func(self, op) @@ -324,6 +327,10 @@ self.il.Emit(OpCodes.Ldfld, self.exc_value_field) self.il.Emit(OpCodes.Isinst, clitype) self.il.Emit(OpCodes.Brfalse, il_label) + # the guard succeeded, store the result + self.av_inputargs.load(self) + self.il.Emit(OpCodes.Ldfld, self.exc_value_field) + self.store_result(op) def emit_op_jump(self, op): target = op.jump_target Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Mon May 18 17:33:30 2009 @@ -15,8 +15,6 @@ test_bridge_from_guard_exception = skip_loop - test_bridge_from_guard_no_exception = skip - test_exception_from_outside = skip test_exception_from_outside_2 = skip test_exception_two_cases = skip test_exception_two_cases_2 = skip From antocuni at codespeak.net Mon May 18 17:40:49 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 17:40:49 +0200 (CEST) Subject: [pypy-svn] r65298 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090518154049.53531168050@codespeak.net> Author: antocuni Date: Mon May 18 17:40:47 2009 New Revision: 65298 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Log: nice, a lot of tests passes out of the box Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Mon May 18 17:40:47 2009 @@ -14,15 +14,11 @@ py.test.skip('in-progress') test_bridge_from_guard_exception = skip_loop + test_exception_four_cases = skip_loop + test_bridge_from_interpreter_exc = skip_loop + test_bridge_from_interpreter_exc_2 = skip_loop - test_exception_from_outside_2 = skip - test_exception_two_cases = skip - test_exception_two_cases_2 = skip - test_exception_four_cases = skip - test_exception_later = skip - test_exception_and_then_no_exception = skip - test_raise_through_wrong_exc_2 = skip test_int_ovf = skip test_int_lshift_ovf = skip - test_bridge_from_interpreter_exc = skip - test_bridge_from_interpreter_exc_2 = skip + + From antocuni at codespeak.net Mon May 18 21:21:47 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 18 May 2009 21:21:47 +0200 (CEST) Subject: [pypy-svn] r65300 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090518192147.9D712169DF6@codespeak.net> Author: antocuni Date: Mon May 18 21:21:45 2009 New Revision: 65300 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Log: translate .NET OverflowException into RPython OverflowError when caught in the generated code. One more test passing Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Mon May 18 21:21:45 2009 @@ -104,6 +104,12 @@ t_InputArgs = dotnet.typeof(InputArgs) self.av_inputargs = MethodArgument(1,t_InputArgs ) self.exc_value_field = t_InputArgs.GetField('exc_value') + if cpu.rtyper: + self.av_OverflowError = ConstObj(ootype.cast_to_object(cpu.ll_ovf_exc)) + self.av_ZeroDivisionError = ConstObj(ootype.cast_to_object(cpu.ll_zero_exc)) + else: + self.av_OverflowError = None + self.av_ZeroDivisionError = None # ---- self.emit_load_inputargs() self.emit_preamble() @@ -253,6 +259,10 @@ for exctype in exctypes: v = self.il.DeclareLocal(exctype) self.il.BeginCatchBlock(exctype) + if exctype == dotnet.typeof(System.OverflowException) and self.av_OverflowError: + # translate OverflowException into excpetions.OverflowError + self.il.Emit(OpCodes.Pop) + self.av_OverflowError.load(self) self.il.Emit(OpCodes.Stloc, v) self.av_inputargs.load(self) self.il.Emit(OpCodes.Ldloc, v) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Mon May 18 21:21:45 2009 @@ -25,6 +25,17 @@ self.stats = stats self.translate_support_code = translate_support_code self.inputargs = None + self.ll_ovf_exc = self._get_prebuilt_exc(OverflowError) + self.ll_zero_exc = self._get_prebuilt_exc(ZeroDivisionError) + + def _get_prebuilt_exc(self, cls): + if self.rtyper is None: + return System.Exception() + else: + bk = self.rtyper.annotator.bookkeeper + clsdef = bk.getuniqueclassdef(cls) + return self.rtyper.exceptiondata.get_standard_ll_exc_instance( + self.rtyper, clsdef) def get_inputargs(self): if self.inputargs is None: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Mon May 18 21:21:45 2009 @@ -17,8 +17,7 @@ test_exception_four_cases = skip_loop test_bridge_from_interpreter_exc = skip_loop test_bridge_from_interpreter_exc_2 = skip_loop - - test_int_ovf = skip - test_int_lshift_ovf = skip + test_int_lshift_ovf = skip_loop + From fijal at codespeak.net Tue May 19 00:19:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 19 May 2009 00:19:11 +0200 (CEST) Subject: [pypy-svn] r65301 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090518221911.16AB1169E98@codespeak.net> Author: fijal Date: Tue May 19 00:19:11 2009 New Revision: 65301 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_simple_optimize.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_dummy.py Log: Port some simple optimizations from optimize.py to simple_optimize.py. I'm not too happy with the result as it is, because it's not any more modular than optimize.py It should also probably be renamed to optimize2.py or something like this. 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 May 19 00:19:11 2009 @@ -6,7 +6,8 @@ from pypy.jit.metainterp.resoperation import ResOperation, rop from pypy.jit.metainterp.history import TreeLoop, log, Box, History -from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj +from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj,\ + Const from pypy.jit.metainterp import history from pypy.jit.metainterp.specnode import NotSpecNode from pypy.rlib.debug import debug_print @@ -277,6 +278,8 @@ elif cpu.is_oo and isinstance(box, BoxObj): srcvalue = cpu.get_latest_value_obj(i) box.changevalue_obj(srcvalue) + elif isinstance(box, Const): + pass # we don't need to do anything else: assert False return patch @@ -289,6 +292,8 @@ dstbox.changevalue_int(srcbox.getint()) elif isinstance(dstbox, BoxPtr): dstbox.changevalue_ptr(srcbox.getptr_base()) + elif isinstance(dstbox, Const): + pass elif metainterp_sd.cpu.is_oo and isinstance(dstbox, BoxObj): dstbox.changevalue_obj(srcbox.getobj()) else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py Tue May 19 00:19:11 2009 @@ -2,18 +2,142 @@ """ Simplified optimize.py """ from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp.history import Const, Box + +class InstanceNode(object): + def __init__(self, source, const=False): + self.source = source + if const: + assert isinstance(source, Const) + self.const = const + self.cls = None + + 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' + return "" % (self.source, flags) + +class Specializer(object): + loop = None + nodes = None + + def getnode(self, box): + try: + return self.nodes[box] + except KeyError: + if isinstance(box, Const): + node = InstanceNode(box, const=True) + else: + node = InstanceNode(box) + self.nodes[box] = node + return node + + def getsource(self, box): + if isinstance(box, Const): + return box + return self.nodes[box].source + + def find_nodes(self): + for op in self.loop.operations: + if op.is_always_pure(): + is_pure = True + for arg in op.args: + if not self.getnode(arg).const: + is_pure = False + if is_pure: + box = op.result + assert box is not None + self.nodes[box] = InstanceNode(box.constbox(), const=True) + continue + else: + if op.is_guard(): + for arg in op.suboperations[0].args: + self.getnode(arg) + # default case + for box in op.args: + self.getnode(box) + box = op.result + if box is not None: + self.nodes[box] = InstanceNode(box) + + def new_arguments(self, op): + newboxes = [] + for box in op.args: + if isinstance(box, Box): + instnode = self.nodes[box] + box = instnode.source + newboxes.append(box) + return newboxes + + def optimize_guard(self, op): + assert len(op.suboperations) == 1 + op_fail = op.suboperations[0] + op_fail.args = self.new_arguments(op_fail) + # modification in place. Reason for this is explained in mirror + # in optimize.py + op.suboperations = [op_fail] + + def optimize_operations(self): + newoperations = [] + for op in self.loop.operations: + if op.is_guard(): + if op.opnum == rop.GUARD_NONVIRTUALIZED: + continue + elif op.opnum == rop.GUARD_CLASS: + node = self.getnode(op.args[0]) + if node.cls is not None: + # assert that they're equal maybe + continue + node.cls = InstanceNode(op.args[1], const=True) + elif op.opnum == rop.GUARD_VALUE: + instnode = self.nodes[op.args[0]] + assert isinstance(op.args[1], Const) + if instnode.const: + continue + self.optimize_guard(op) + instnode.const = True + instnode.source = op.args[0].constbox() + newoperations.append(op) + continue + self.optimize_guard(op) + newoperations.append(op) + continue + # default handler + op = op.clone() + op.args = self.new_arguments(op) + if op.is_always_pure(): + for box in op.args: + if isinstance(box, Box): + break + else: + # all constant arguments: constant-fold away + box = op.result + assert box is not None + instnode = InstanceNode(box.constbox(), const=True) + self.nodes[box] = instnode + continue + newoperations.append(op) + print "Length of the loop:", len(newoperations) + self.loop.operations = newoperations + + def optimize_loop(self, loop): + self.nodes = {} + self.loop = loop + self.find_nodes() + self.optimize_operations() + +specializer = Specializer() def optimize_loop(options, old_loops, loop, cpu=None): if old_loops: assert len(old_loops) == 1 return old_loops[0] else: - newoperations = [] - for op in loop.operations: - if op.opnum == rop.GUARD_NONVIRTUALIZED: - continue - newoperations.append(op) - loop.operations = newoperations + specializer.optimize_loop(loop) return None def optimize_bridge(options, old_loops, loop, cpu=None): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_dummy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_dummy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_dummy.py Tue May 19 00:19:11 2009 @@ -1,19 +1,24 @@ -from pypy.jit.metainterp.test import test_loop +from pypy.jit.metainterp.test import test_loop, test_send from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.jit.metainterp.simple_optimize import Optimizer from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -class LoopDummyTest(test_loop.LoopTest): +class LoopDummyTest(test_loop.LoopTest, test_send.SendTests): def meta_interp(self, func, args, **kwds): return ll_meta_interp(func, args, optimizer=Optimizer, CPUClass=self.CPUClass, type_system=self.type_system, **kwds) + def check_loops(self, *args, **kwds): + pass + + def check_loop_count(self, count): + pass class TestLLtype(LoopDummyTest, LLJitMixin): pass -class TestOOtype(LoopDummyTest, OOJitMixin): +class XTestOOtype(LoopDummyTest, OOJitMixin): pass Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_simple_optimize.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_simple_optimize.py Tue May 19 00:19:11 2009 @@ -0,0 +1,58 @@ + +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE + +from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.metainterp.history import ConstAddr, BoxPtr, TreeLoop,\ + ConstInt, BoxInt +from pypy.jit.backend.llgraph import runner + +from pypy.jit.metainterp.simple_optimize import optimize_loop +from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY + +node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) +node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) +cpu = runner.LLtypeCPU(None) +vtable_box = ConstAddr(node_vtable_adr, cpu) + +NODE = lltype.GcForwardReference() +NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT), + ('value', lltype.Signed), + ('next', lltype.Ptr(NODE)))) + +def newloop(inputargs, operations): + loop = TreeLoop("test") + loop.inputargs = inputargs + loop.operations = operations + return loop + +def test_remove_guard_class(): + node = lltype.malloc(NODE) + nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) + ops = [ + ResOperation(rop.GUARD_CLASS, [nodebox, vtable_box], None), + ResOperation(rop.GUARD_CLASS, [nodebox, vtable_box], None), + ] + ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] + ops[1].suboperations = [ResOperation(rop.FAIL, [], None)] + loop = newloop([nodebox], ops) + optimize_loop(None, [], loop) + assert len(loop.operations) == 1 + +def test_remove_consecutive_guard_value_constfold(): + n = BoxInt(0) + n1 = BoxInt(1) + n2 = BoxInt(3) + ops = [ + ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), + ResOperation(rop.INT_ADD, [n, ConstInt(1)], n1), + ResOperation(rop.GUARD_VALUE, [n1, ConstInt(1)], None), + ResOperation(rop.INT_ADD, [n1, ConstInt(2)], n2), + ] + ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] + ops[2].suboperations = [ResOperation(rop.FAIL, [], None)] + loop = newloop([n], ops) + optimize_loop(None, [], loop) + equaloplists(loop.operations, [ + ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), + ]) From fijal at codespeak.net Tue May 19 02:23:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 19 May 2009 02:23:36 +0200 (CEST) Subject: [pypy-svn] r65302 - pypy/branch/pyjitpl5-experiments Message-ID: <20090519002336.A265216854B@codespeak.net> Author: fijal Date: Tue May 19 02:23:34 2009 New Revision: 65302 Added: pypy/branch/pyjitpl5-experiments/ - copied from r65301, pypy/branch/pyjitpl5/ Log: back to the experimentation mode... From fijal at codespeak.net Tue May 19 08:16:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 19 May 2009 08:16:01 +0200 (CEST) Subject: [pypy-svn] r65303 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090519061601.67DC1169E0B@codespeak.net> Author: fijal Date: Tue May 19 08:15:59 2009 New Revision: 65303 Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py - copied, changed from r65302, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_optimize2.py - copied, changed from r65302, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py - copied, changed from r65302, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_simple_optimize.py Removed: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_simple_optimize.py Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py Log: Shuffle stuff, so simple_optimize stays simple and rename what is there to optimize2.py Copied: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (from r65302, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py) ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 19 08:15:59 2009 @@ -11,6 +11,7 @@ assert isinstance(source, Const) self.const = const self.cls = None + self.field_cache = {} def __repr__(self): flags = '' Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/simple_optimize.py Tue May 19 08:15:59 2009 @@ -1,143 +1,20 @@ """ Simplified optimize.py """ -from pypy.jit.metainterp.resoperation import rop -from pypy.jit.metainterp.history import Const, Box - -class InstanceNode(object): - def __init__(self, source, const=False): - self.source = source - if const: - assert isinstance(source, Const) - self.const = const - self.cls = None - - 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' - return "" % (self.source, flags) - -class Specializer(object): - loop = None - nodes = None - - def getnode(self, box): - try: - return self.nodes[box] - except KeyError: - if isinstance(box, Const): - node = InstanceNode(box, const=True) - else: - node = InstanceNode(box) - self.nodes[box] = node - return node - - def getsource(self, box): - if isinstance(box, Const): - return box - return self.nodes[box].source - - def find_nodes(self): - for op in self.loop.operations: - if op.is_always_pure(): - is_pure = True - for arg in op.args: - if not self.getnode(arg).const: - is_pure = False - if is_pure: - box = op.result - assert box is not None - self.nodes[box] = InstanceNode(box.constbox(), const=True) - continue - else: - if op.is_guard(): - for arg in op.suboperations[0].args: - self.getnode(arg) - # default case - for box in op.args: - self.getnode(box) - box = op.result - if box is not None: - self.nodes[box] = InstanceNode(box) - - def new_arguments(self, op): - newboxes = [] - for box in op.args: - if isinstance(box, Box): - instnode = self.nodes[box] - box = instnode.source - newboxes.append(box) - return newboxes - - def optimize_guard(self, op): - assert len(op.suboperations) == 1 - op_fail = op.suboperations[0] - op_fail.args = self.new_arguments(op_fail) - # modification in place. Reason for this is explained in mirror - # in optimize.py - op.suboperations = [op_fail] - - def optimize_operations(self): - newoperations = [] - for op in self.loop.operations: - if op.is_guard(): - if op.opnum == rop.GUARD_NONVIRTUALIZED: - continue - elif op.opnum == rop.GUARD_CLASS: - node = self.getnode(op.args[0]) - if node.cls is not None: - # assert that they're equal maybe - continue - node.cls = InstanceNode(op.args[1], const=True) - elif op.opnum == rop.GUARD_VALUE: - instnode = self.nodes[op.args[0]] - assert isinstance(op.args[1], Const) - if instnode.const: - continue - self.optimize_guard(op) - instnode.const = True - instnode.source = op.args[0].constbox() - newoperations.append(op) - continue - self.optimize_guard(op) - newoperations.append(op) - continue - # default handler - op = op.clone() - op.args = self.new_arguments(op) - if op.is_always_pure(): - for box in op.args: - if isinstance(box, Box): - break - else: - # all constant arguments: constant-fold away - box = op.result - assert box is not None - instnode = InstanceNode(box.constbox(), const=True) - self.nodes[box] = instnode - continue - newoperations.append(op) - print "Length of the loop:", len(newoperations) - self.loop.operations = newoperations - - def optimize_loop(self, loop): - self.nodes = {} - self.loop = loop - self.find_nodes() - self.optimize_operations() -specializer = Specializer() +from pypy.jit.metainterp.resoperation import rop def optimize_loop(options, old_loops, loop, cpu=None): if old_loops: assert len(old_loops) == 1 return old_loops[0] else: - specializer.optimize_loop(loop) + newoperations = [] + for op in loop.operations: + if op.opnum == rop.GUARD_NONVIRTUALIZED: + continue + newoperations.append(op) + loop.operations = newoperations return None def optimize_bridge(options, old_loops, loop, cpu=None): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py Tue May 19 08:15:59 2009 @@ -20,5 +20,5 @@ class TestLLtype(LoopDummyTest, LLJitMixin): pass -class XTestOOtype(LoopDummyTest, OOJitMixin): +class TestOOtype(LoopDummyTest, OOJitMixin): pass Copied: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_optimize2.py (from r65302, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py) ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_dummy.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop_optimize2.py Tue May 19 08:15:59 2009 @@ -1,7 +1,7 @@ from pypy.jit.metainterp.test import test_loop, test_send from pypy.jit.metainterp.warmspot import ll_meta_interp -from pypy.jit.metainterp.simple_optimize import Optimizer +from pypy.jit.metainterp.optimize2 import Optimizer from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class LoopDummyTest(test_loop.LoopTest, test_send.SendTests): @@ -20,5 +20,5 @@ class TestLLtype(LoopDummyTest, LLJitMixin): pass -class XTestOOtype(LoopDummyTest, OOJitMixin): +class TestOOtype(LoopDummyTest, OOJitMixin): pass Copied: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (from r65302, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_simple_optimize.py) ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_simple_optimize.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 19 08:15:59 2009 @@ -1,4 +1,5 @@ +import py from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE @@ -7,7 +8,7 @@ ConstInt, BoxInt from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp.simple_optimize import optimize_loop +from pypy.jit.metainterp.optimize2 import optimize_loop from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) @@ -19,6 +20,9 @@ NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT), ('value', lltype.Signed), ('next', lltype.Ptr(NODE)))) +node = lltype.malloc(NODE) +nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) +nodedescr = cpu.fielddescrof(NODE, 'value') def newloop(inputargs, operations): loop = TreeLoop("test") @@ -27,8 +31,6 @@ return loop def test_remove_guard_class(): - node = lltype.malloc(NODE) - nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) ops = [ ResOperation(rop.GUARD_CLASS, [nodebox, vtable_box], None), ResOperation(rop.GUARD_CLASS, [nodebox, vtable_box], None), @@ -56,3 +58,21 @@ equaloplists(loop.operations, [ ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), ]) + +def test_remove_consecutive_getfields(): + py.test.skip("in progress") + n1 = BoxInt() + n2 = BoxInt() + n3 = BoxInt() + ops = [ + ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), + ResOperation(rop.GETFIELD_GC, [nodebox], n2, nodedescr), + ResOperation(rop.INT_ADD, [n1, n2], n3), + ] + loop = newloop([nodebox], ops) + optimize_loop(None, [], loop) + equaloplists(loop.operations, [ + ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), + ResOperation(rop.INT_ADD, [n1, n1], n3), + ]) + From antocuni at codespeak.net Tue May 19 10:31:14 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 19 May 2009 10:31:14 +0200 (CEST) Subject: [pypy-svn] r65304 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090519083114.C125B169DF6@codespeak.net> Author: antocuni Date: Tue May 19 10:31:13 2009 New Revision: 65304 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py Log: don't print stuff on stdout, as it breaks the minimal and cli backends (because the spawn an external process and read the result as printed on stdout) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py Tue May 19 10:31:13 2009 @@ -121,7 +121,7 @@ self.nodes[box] = instnode continue newoperations.append(op) - print "Length of the loop:", len(newoperations) + #print "Length of the loop:", len(newoperations) self.loop.operations = newoperations def optimize_loop(self, loop): From david at codespeak.net Tue May 19 12:15:46 2009 From: david at codespeak.net (david at codespeak.net) Date: Tue, 19 May 2009 12:15:46 +0200 (CEST) Subject: [pypy-svn] r65305 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090519101546.56E47169E7B@codespeak.net> Author: david Date: Tue May 19 12:15:43 2009 New Revision: 65305 Added: pypy/branch/io-lang/pypy/lang/io/test/test_number.py Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/test/test_method.py Log: fixed issued evaluating variables in methods in the context of other objects than the Lobby Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Tue May 19 12:15:43 2009 @@ -110,7 +110,7 @@ w_result = w_method.apply(space, w_receiver, self, w_context) if self.next: #TODO: optimize - return self.next.eval(space, w_result, w_context) + return self.next.eval(space, w_result, w_receiver) else: return w_result Modified: pypy/branch/io-lang/pypy/lang/io/test/test_method.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_method.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_method.py Tue May 19 12:15:43 2009 @@ -50,4 +50,25 @@ def test_call_on_method(): inp = 'a := method(x, x + 1); getSlot("a") call(3)' res, space = interpret(inp) - assert res.value == 4 \ No newline at end of file + assert res.value == 4 + +def test_method_binding(): + inp = 'c := Object clone; c setSlot("b", 123); c setSlot("a", method(b)); c a' + res, space = interpret(inp) + assert res.value == 123 + +def test_method_modified_binding(): + inp = 'c := Object clone; c setSlot("b",123); c setSlot("a", method(x, b)); c setSlot("b",1); c a(3)' + res, space = interpret(inp) + assert res.value == 1 + + +def test_block_binding(): + inp = 'c := Object clone; b := 123; c setSlot("a", block(x, b)); c a call(3)' + res, space = interpret(inp) + assert res.value == 123 + +def test_block_modified_binding(): + inp = 'c := Object clone; b := 42; c setSlot("a", block(x, b)); b := 1; c a call(3)' + res, space = interpret(inp) + assert res.value == 1 \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_number.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_number.py Tue May 19 12:15:43 2009 @@ -0,0 +1,31 @@ +from pypy.lang.io.parserhack import interpret +from pypy.lang.io.model import W_Number +import py +def test_even_simpler(): + x, _ = interpret("2") + assert x.value == 2 + +def test_simple(): + x, _ = interpret("2 + 2") + assert x.value == 4 + +def test_simple_minus(): + x, _ = interpret("2 - 2") + assert x.value == 0 + +def test_plus_in_context(): + x, _ = interpret("""x := 7 + c := method(2 - x) + c() + """) + assert x.value == -5 + +def test_plus_in_method(): + inp = """c := Object clone + c f := 5 + c g := method(3 + f) + c g(7) + """ + res, space = interpret(inp) + assert res.value == 8 + From david at codespeak.net Tue May 19 12:22:54 2009 From: david at codespeak.net (david at codespeak.net) Date: Tue, 19 May 2009 12:22:54 +0200 (CEST) Subject: [pypy-svn] r65306 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090519102254.C29A8169E9B@codespeak.net> Author: david Date: Tue May 19 12:22:54 2009 New Revision: 65306 Added: pypy/branch/io-lang/pypy/lang/io/test/test_object.py Modified: pypy/branch/io-lang/pypy/lang/io/object.py Log: Add do slot to Object to evaluate a set of messages in the context of the reciever Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Tue May 19 12:22:54 2009 @@ -35,4 +35,8 @@ def w_object_list(space, w_target, w_message, w_context): w_items = [x.eval(space, w_target, w_context) for x in w_message.arguments] return space.w_list.clone_and_init(space, w_items) - \ No newline at end of file + + at register_method('Object', 'do') +def w_object_do(space, w_target, w_message, w_context): + w_message.arguments[0].eval(space, w_target, w_context) + return w_target \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_object.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_object.py Tue May 19 12:22:54 2009 @@ -0,0 +1,16 @@ +from pypy.lang.io.parserhack import parse, interpret +from pypy.lang.io.model import W_Object +import py.test + + +def test_object_do(): + inp = '4 do(a := 23)' + res, space = interpret(inp) + assert res.slots['a'].value == 23 + assert res.value == 4 + +def test_object_do_multiple_slots(): + inp = 'Object do(a := 23; b := method(a + 5); a := 1); Object b' + res, space = interpret(inp) + assert res.value == 6 + assert space.w_object.slots['a'].value == 1 \ No newline at end of file From david at codespeak.net Tue May 19 12:40:02 2009 From: david at codespeak.net (david at codespeak.net) Date: Tue, 19 May 2009 12:40:02 +0200 (CEST) Subject: [pypy-svn] r65307 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090519104002.37794169EC8@codespeak.net> Author: david Date: Tue May 19 12:40:01 2009 New Revision: 65307 Modified: pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/test/test_object.py Log: add anonymous slot to object, which evaluates and returns given argument Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Tue May 19 12:40:01 2009 @@ -39,4 +39,8 @@ @register_method('Object', 'do') def w_object_do(space, w_target, w_message, w_context): w_message.arguments[0].eval(space, w_target, w_context) - return w_target \ No newline at end of file + return w_target + + at register_method('Object', '', unwrap_spec=[object, object]) +def w_object_(space, w_target, w_arg): + return w_arg Modified: pypy/branch/io-lang/pypy/lang/io/test/test_object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_object.py Tue May 19 12:40:01 2009 @@ -13,4 +13,9 @@ inp = 'Object do(a := 23; b := method(a + 5); a := 1); Object b' res, space = interpret(inp) assert res.value == 6 - assert space.w_object.slots['a'].value == 1 \ No newline at end of file + assert space.w_object.slots['a'].value == 1 + +def test_object_anon_slot(): + inp = 'Object getSlot("+")("foo")' + res, space = interpret(inp) + assert res.value == 'foo' \ No newline at end of file From david at codespeak.net Tue May 19 13:09:32 2009 From: david at codespeak.net (david at codespeak.net) Date: Tue, 19 May 2009 13:09:32 +0200 (CEST) Subject: [pypy-svn] r65308 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090519110932.38BA6169E06@codespeak.net> Author: david Date: Tue May 19 13:09:30 2009 New Revision: 65308 Modified: pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/test/test_object.py Log: add hasSlot and ? slots to Object Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Tue May 19 13:09:30 2009 @@ -13,6 +13,19 @@ except KeyError: return space.w_nil + at register_method('Object', 'hasSlot', unwrap_spec=[object, str]) +def w_object_has_slot(space, w_target, name): + if w_target.lookup(name) is None: + return space.w_false + return space.w_true + + at register_method('Object', '?') +def w_object_question_mark(space, w_target, w_message, w_context): + name = w_message.arguments[0].name + if w_object_has_slot(space, w_target, name) is space.w_false: + return space.w_nil + return w_message.arguments[0].eval(space, w_target, w_context) + @register_method('Object', 'method') def w_object_method(space, w_target, w_message, w_context): w_body = w_message.arguments[-1] Modified: pypy/branch/io-lang/pypy/lang/io/test/test_object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_object.py Tue May 19 13:09:30 2009 @@ -18,4 +18,23 @@ def test_object_anon_slot(): inp = 'Object getSlot("+")("foo")' res, space = interpret(inp) - assert res.value == 'foo' \ No newline at end of file + assert res.value == 'foo' + +def test_object_has_slot(): + inp = 'Object hasSlot("foo")' + res, space = interpret(inp) + assert res is space.w_false + + inp2 = 'Object hasSlot("clone")' + res, space = interpret(inp2) + assert res is space.w_true + +def test_object_question_mark_simple(): + inp = 'Object do(a := 1); Object ?a' + res, space = interpret(inp) + assert res is not space.w_nil + assert res.value == 1 + + inp2 = 'Object ?a' + res, space = interpret(inp2) + assert res is space.w_nil From david at codespeak.net Tue May 19 14:21:44 2009 From: david at codespeak.net (david at codespeak.net) Date: Tue, 19 May 2009 14:21:44 +0200 (CEST) Subject: [pypy-svn] r65309 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090519122144.D6316169F10@codespeak.net> Author: david Date: Tue May 19 14:21:42 2009 New Revision: 65309 Added: pypy/branch/io-lang/pypy/lang/io/call.py pypy/branch/io-lang/pypy/lang/io/message.py pypy/branch/io-lang/pypy/lang/io/test/test_call.py pypy/branch/io-lang/pypy/lang/io/test/test_message.py Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/objspace.py pypy/branch/io-lang/pypy/lang/io/register.py pypy/branch/io-lang/pypy/lang/io/test/test_method.py pypy/branch/io-lang/pypy/lang/io/test/test_object.py Log: methods for Call and Message objects, corrected evaluation of method args and create call object for when a method is called. Add message slot to Object Added: pypy/branch/io-lang/pypy/lang/io/call.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/call.py Tue May 19 14:21:42 2009 @@ -0,0 +1,9 @@ +from pypy.lang.io.register import register_method +from pypy.lang.io.model import W_Message + + at register_method('Call', 'argAt') +def call_arg_at(space, w_target, w_message, w_context): + return space.w_message.slots['argAt'].apply( + space, + w_target.slots['message'], + w_message, w_context) \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/message.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/message.py Tue May 19 14:21:42 2009 @@ -0,0 +1,13 @@ +from pypy.lang.io.register import register_method +from pypy.lang.io.model import W_Message + + at register_method('Message', 'argAt', unwrap_spec=[object, int]) +def message_arg_at(space, w_message, arg_num): + if arg_num < len(w_message.arguments): + return w_message.arguments[arg_num] + return space.w_nil + +# @register_method('Message', 'setIsActivatable', unwrap_spec=[object, bool]) +# def message_setIsActivatable(space, w_target, setting): +# w_target.activateable = setting +# return w_target \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Tue May 19 14:21:42 2009 @@ -92,7 +92,7 @@ self.literal_value = parse_literal(space, name) self.arguments = arguments self.next = next - W_Object.__init__(self, space) + W_Object.__init__(self, space, [space.w_message]) def __repr__(self): return "Message(%r, %r, %r)" % (self.name, self.arguments, self.next) @@ -129,17 +129,17 @@ def call(self, space, w_receiver, w_message, w_context): w_locals = self.space.w_locals.clone() + w_call = self.space.w_call.clone() assert w_locals is not None - args = list(self.arguments) + assert w_call is not None - for arg in w_message.arguments: - try: - w_locals.slots[args.pop(0)] = arg.eval(space, w_receiver, w_context) - except IndexError: - break - - for arg_name in args: - w_locals.slots[arg_name] = space.w_nil + args = list(self.arguments) + n_params = len(w_message.arguments) + for i in range(len(args)): + if i < n_params: + w_locals.slots[args[i]] = w_message.arguments[i].eval(space, w_receiver, w_context) + else: + w_locals.slots[args[i]] = space.w_nil if self.activateable: w_locals.protos = [w_receiver] @@ -147,7 +147,9 @@ else: w_locals.protos = [w_context] w_locals.slots['self'] = w_context - + + w_locals.slots['call'] = w_call + w_call.slots['message'] = w_message return self.body.eval(space, w_locals, w_context) Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Tue May 19 14:21:42 2009 @@ -57,3 +57,8 @@ @register_method('Object', '', unwrap_spec=[object, object]) def w_object_(space, w_target, w_arg): return w_arg + + + at register_method('Object', 'message') +def object_message(space, w_target, w_message, w_context): + return w_message.arguments[0] \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/objspace.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/objspace.py (original) +++ pypy/branch/io-lang/pypy/lang/io/objspace.py Tue May 19 14:21:42 2009 @@ -6,7 +6,8 @@ import pypy.lang.io.object import pypy.lang.io.block import pypy.lang.io.list - +import pypy.lang.io.call +import pypy.lang.io.message class ObjSpace(object): """docstring for ObjSpace""" def __init__(self): @@ -19,24 +20,34 @@ self.w_true = W_Object(self, [self.w_object]) self.w_false = W_Object(self, [self.w_object]) self.w_nil = W_Object(self, [self.w_object]) - self.w_block = W_Block(self, [], W_Message(self, 'nil', []), False, [self.w_object]) self.w_list = W_List(self, [self.w_object]) + self.w_call = W_Object(self) + self.init_w_object() self.init_w_protos() self.init_w_list() - + + self.init_w_message() + + self.w_block = W_Block(self, [], W_Message(self, 'nil', []), False, [self.w_object]) self.init_w_block() self.init_w_lobby() self.init_w_number() + self.init_w_core() - + self.init_w_call() + + def init_w_call(self): + for key, function in cfunction_definitions['Call'].items(): + self.w_call.slots[key] = W_CFunction(self, function) + def init_w_protos(self): self.w_protos.protos.append(self.w_core) self.w_protos.slots['Core'] = self.w_core @@ -58,6 +69,7 @@ self.w_core.slots['false'] = self.w_false self.w_core.slots['nil'] = self.w_nil self.w_core.slots['List'] = self.w_list + self.w_core.slots['Call'] = self.w_call def init_w_number(self): self.w_number = instantiate(W_Number) @@ -67,6 +79,14 @@ for key, function in cfunction_definitions['Number'].items(): self.w_number.slots[key] = W_CFunction(self, function) + def init_w_message(self): + self.w_message = instantiate(W_Message) + W_Object.__init__(self.w_message, self) + self.w_message.protos = [self.w_object] + self.w_message.name = "Unnamed" + for key, function in cfunction_definitions['Message'].items(): + self.w_message.slots[key] = W_CFunction(self, function) + def init_w_lobby(self): self.w_lobby.protos.append(self.w_protos) self.w_object.protos.append(self.w_lobby) Modified: pypy/branch/io-lang/pypy/lang/io/register.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/register.py (original) +++ pypy/branch/io-lang/pypy/lang/io/register.py Tue May 19 14:21:42 2009 @@ -24,6 +24,11 @@ args += (x, ) elif typ is str: args += (x.value, ) + elif typ is bool: + if x is space.w_true: + args += (True, ) + else: + args += (False, ) else: raise ValueError, 'Unknown unwrap spec' Added: pypy/branch/io-lang/pypy/lang/io/test/test_call.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_call.py Tue May 19 14:21:42 2009 @@ -0,0 +1,8 @@ +from pypy.lang.io.parserhack import interpret +from pypy.lang.io.model import W_Message +import py + +def test_message_arg_at(): + inp = 'a := method(x, y, z, call); a(1,2,3) argAt(1)' + res, space = interpret(inp) + assert res.name == '2' \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_message.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_message.py Tue May 19 14:21:42 2009 @@ -0,0 +1,27 @@ +from pypy.lang.io.parserhack import interpret +from pypy.lang.io.model import W_Message, W_Block +import py + + +def test_message_protos(): + inp = "a := block(1)\na" + res,space = interpret(inp) + + assert res.body.protos == [space.w_message] + assert space.w_message.protos == [space.w_object] + +def test_message_arg_at(): + inp = 'a := message(foo(2,3,4)); a argAt(1)' + res, space = interpret(inp) + assert res.name == '3' + +# def test_setIsActivatable(): +# inp = "a := block(1);a setIsActivateable(true); a" +# res,space = interpret(inp) +# +# assert res.value == 1 +# +# inp = "a := method(1);a setIsActivateable(false); a" +# res,space = interpret(inp) +# +# assert isinstance(res, W_Block) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_method.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_method.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_method.py Tue May 19 14:21:42 2009 @@ -71,4 +71,36 @@ def test_block_modified_binding(): inp = 'c := Object clone; b := 42; c setSlot("a", block(x, b)); b := 1; c a call(3)' res, space = interpret(inp) - assert res.value == 1 \ No newline at end of file + assert res.value == 1 + +def test_block_call_slot(): + py.test.skip() + inp = """ + Object do( + /*doc Object inlineMethod + Creates a method which is executed directly in a receiver (no Locals object is created). +
+
+      Io> m := inlineMethod(x := x*2)
+      Io> x := 1
+      ==> 1
+      Io> m
+      ==> 2
+      Io> m
+      ==> 4
+      Io> m
+      ==> 8
+      
+ */ + inlineMethod := method(call message argAt(0) setIsActivatable(true)) + ) + m := inlineMethod(x := x*2) + x := 1 + m + m + """ + # from A0_List.io + res, space = interpret(inp) + assert space.w_object.slots['inlineMethod'] is not None + assert res.value == 4 + \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_object.py Tue May 19 14:21:42 2009 @@ -1,5 +1,5 @@ from pypy.lang.io.parserhack import parse, interpret -from pypy.lang.io.model import W_Object +from pypy.lang.io.model import W_Object, W_Message import py.test @@ -38,3 +38,9 @@ inp2 = 'Object ?a' res, space = interpret(inp2) assert res is space.w_nil + +def test_object_message(): + inp = 'message(foo)' + res, space = interpret(inp) + assert isinstance(res, W_Message) + assert res.name == 'foo' \ No newline at end of file From antocuni at codespeak.net Tue May 19 17:28:41 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 19 May 2009 17:28:41 +0200 (CEST) Subject: [pypy-svn] r65314 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli jit/backend/cli/test translator/cli/src Message-ID: <20090519152841.0C672169F6B@codespeak.net> Author: antocuni Date: Tue May 19 17:28:40 2009 New Revision: 65314 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Log: implement bridges; so far the implementation is very simple, just a tailcall to the method containing the next loop; hopefully, the speed penalty associated to the tail call is not too heavy, because we don't expect bridges to be so frequent (thanks cfbolz for the idea). In the future, we might think of other techniques to avoid tail calls. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Tue May 19 17:28:40 2009 @@ -14,6 +14,7 @@ System = CLR.System OpCodes = System.Reflection.Emit.OpCodes LoopDelegate = CLR.pypy.runtime.LoopDelegate +DelegateHolder = CLR.pypy.runtime.DelegateHolder InputArgs = CLR.pypy.runtime.InputArgs cVoid = ootype.nullruntimeclass @@ -51,12 +52,40 @@ def store(self, meth): assert False, 'cannot store() to Constant' + def get_cliobj(self): + return dotnet.cast_to_native_object(self.getobj()) + class __extend__(ConstInt): __metaclass__ = extendabletype def load(self, meth): meth.il.Emit(OpCodes.Ldc_I4, self.value) + +class ConstFunction(Const): + + def __init__(self, name): + self.name = name + self.holder = DelegateHolder() + + def get_cliobj(self): + return dotnet.cliupcast(self.holder, System.Object) + + def load(self, meth): + holdertype = self.holder.GetType() + funcfield = holdertype.GetField('func') + Const.load(self, meth) + meth.il.Emit(OpCodes.Castclass, holdertype) + meth.il.Emit(OpCodes.Ldfld, funcfield) + meth.il.Emit(OpCodes.Castclass, dotnet.typeof(LoopDelegate)) + + def _getrepr_(self): + return '' % self.name + + def __hash__(self): + return hash(self.holder) + + class MethodArgument(AbstractValue): def __init__(self, index, cliType): self.index = index @@ -87,6 +116,7 @@ class Method(object): operations = [] # overwritten at the end of the module + tailcall = True debug = False def __init__(self, cpu, name, loop): @@ -124,10 +154,12 @@ # initialize the array of genconsts consts = dotnet.new_array(System.Object, len(self.consts)) for av_const, i in self.consts.iteritems(): - consts[i] = dotnet.cast_to_native_object(av_const.getobj()) + #consts[i] = dotnet.cast_to_native_object(av_const.getobj()) + consts[i] = av_const.get_cliobj() # build the delegate func = self.meth_wrapper.create_delegate(delegatetype, consts) - self.func = dotnet.clidowncast(func, LoopDelegate) + func = dotnet.clidowncast(func, LoopDelegate) + self.loop._cli_funcbox.holder.SetFunc(func) def _get_meth_wrapper(self): restype = dotnet.class2type(cVoid) @@ -282,7 +314,10 @@ self.il.Emit(OpCodes.Ldc_I4, index_op) field = dotnet.typeof(InputArgs).GetField('failed_op') self.il.Emit(OpCodes.Stfld, field) - # store the lates values + self.emit_store_opargs(op) + + def emit_store_opargs(self, op): + # store the latest values i = 0 for box in op.args: self.store_inputarg(i, box.type, box.getCliType(), box) @@ -344,13 +379,23 @@ def emit_op_jump(self, op): target = op.jump_target - assert target is self.loop, 'TODO' assert len(op.args) == len(target.inputargs) - i = 0 - for i in range(len(op.args)): - op.args[i].load(self) - target.inputargs[i].store(self) - self.il.Emit(OpCodes.Br, self.il_loop_start) + if target is self.loop: + i = 0 + for i in range(len(op.args)): + op.args[i].load(self) + target.inputargs[i].store(self) + self.il.Emit(OpCodes.Br, self.il_loop_start) + else: + # it's a real bridge + self.emit_store_opargs(op) + self.av_inputargs.load(self) + self.loop._cli_funcbox.load(self) + methinfo = dotnet.typeof(LoopDelegate).GetMethod('Invoke') + if self.tailcall: + self.il.Emit(OpCodes.Tailcall) + self.il.Emit(OpCodes.Callvirt, methinfo) + self.il.Emit(OpCodes.Ret) def emit_op_new_with_vtable(self, op): assert isinstance(op.args[0], ConstObj) # ignored, using the descr instead Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Tue May 19 17:28:40 2009 @@ -1,6 +1,9 @@ +from pypy.tool.pairtype import extendabletype from pypy.rpython.ootypesystem import ootype +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.history import AbstractDescr, AbstractMethDescr -from pypy.jit.metainterp.history import Box, BoxInt, BoxObj +from pypy.jit.metainterp.history import Box, BoxInt, BoxObj, ConstObj, Const +from pypy.jit.metainterp.history import TreeLoop from pypy.jit.metainterp import executor from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model @@ -12,6 +15,12 @@ System = CLR.System InputArgs = CLR.pypy.runtime.InputArgs +class __extend__(TreeLoop): + __metaclass__ = extendabletype + + _cli_funcbox = None + _cli_meth = None + class CliCPU(model.AbstractCPU): @@ -67,13 +76,18 @@ # ---------------------- def compile_operations(self, loop): - from pypy.jit.backend.cli.method import Method - meth = Method(self, loop.name, loop) - loop._cli_meth = meth + from pypy.jit.backend.cli.method import Method, ConstFunction + if loop._cli_funcbox is None: + loop._cli_funcbox = ConstFunction(loop.name) + else: + # discard previously compiled loop + loop._cli_funcbox.holder.SetFunc(None) + loop._cli_meth = Method(self, loop.name, loop) def execute_operations(self, loop): meth = loop._cli_meth - meth.func(self.get_inputargs()) + func = loop._cli_funcbox.holder.GetFunc() + func(self.get_inputargs()) return meth.failing_ops[self.inputargs.get_failed_op()] def set_future_value_int(self, index, intvalue): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Tue May 19 17:28:40 2009 @@ -37,7 +37,7 @@ test_oostring_instance = skip test_long_long = skip test_free_object = skip + test_stopatxpolicy = skip - test_stopatxpolicy = _skip test_bridge_from_interpreter = _skip - test_bridge_from_interpreter_4 = _skip + Modified: pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs Tue May 19 17:28:40 2009 @@ -291,24 +291,25 @@ return default_blockid; } } + */ public class DelegateHolder { - public Delegate func; + public LoopDelegate func; // we need getter and setter because we can't directly access fields from RPython - public void SetFunc(Delegate func) + public void SetFunc(LoopDelegate func) { this.func = func; } - public Delegate GetFunc() + public LoopDelegate GetFunc() { return this.func; } } - */ + public class AutoSaveAssembly { From fijal at codespeak.net Tue May 19 18:11:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 19 May 2009 18:11:48 +0200 (CEST) Subject: [pypy-svn] r65315 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090519161148.A3F8A169F16@codespeak.net> Author: fijal Date: Tue May 19 18:11:47 2009 New Revision: 65315 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: more of optimizations. It's wrong with regard to aliasing and other things, but that's in-progress Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 19 18:11:47 2009 @@ -1,7 +1,7 @@ """ Simplified optimize.py """ -from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.history import Const, Box class InstanceNode(object): @@ -11,7 +11,8 @@ assert isinstance(source, Const) self.const = const self.cls = None - self.field_cache = {} + self.cleanfields = {} + self.dirtyfields = {} def __repr__(self): flags = '' @@ -107,6 +108,24 @@ self.optimize_guard(op) newoperations.append(op) continue + elif op.opnum == rop.GETFIELD_GC: + instnode = self.getnode(op.args[0]) + descr = op.descr + node = instnode.cleanfields.get(descr, None) + if node is not None: + self.nodes[op.result] = node + continue + else: + instnode.cleanfields[descr] = self.getnode(op.result) + elif op.opnum == rop.SETFIELD_GC: + instnode = self.getnode(op.args[0]) + descr = op.descr + node = self.getnode(op.args[1]) + instnode.dirtyfields[descr] = node + instnode.cleanfields[descr] = node + l = self.field_caches.setdefault(descr, []) + l.append((instnode, node)) + continue # default handler op = op.clone() op.args = self.new_arguments(op) @@ -121,12 +140,23 @@ instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue + elif not op.has_no_side_effect(): + self.clean_up_caches(newoperations) newoperations.append(op) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations + + def clean_up_caches(self, newoperations): + for descr, v in self.field_caches.iteritems(): + for instnode, fieldnode in v: + newoperations.append(ResOperation(rop.SETFIELD_GC, + [instnode.source, fieldnode.source], None, descr)) + del instnode.cleanfields[descr] + del instnode.dirtyfields[descr] def optimize_loop(self, loop): self.nodes = {} + self.field_caches = {} self.loop = loop self.find_nodes() self.optimize_operations() Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 19 18:11:47 2009 @@ -60,7 +60,6 @@ ]) def test_remove_consecutive_getfields(): - py.test.skip("in progress") n1 = BoxInt() n2 = BoxInt() n3 = BoxInt() @@ -76,3 +75,21 @@ ResOperation(rop.INT_ADD, [n1, n1], n3), ]) +def test_setfield_getfield_clean_cache(): + n1 = BoxInt() + n2 = BoxInt() + n3 = BoxInt() + ops = [ + ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), + ResOperation(rop.SETFIELD_GC, [nodebox, ConstInt(3)], None, nodedescr), + ResOperation(rop.GETFIELD_GC, [nodebox], n2, nodedescr), + ResOperation(rop.CALL, [n2], None), + ] + loop = newloop([nodebox], ops) + optimize_loop(None, [], loop) + equaloplists(loop.operations, [ + ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), + ResOperation(rop.SETFIELD_GC, [nodebox, ConstInt(3)], None, nodedescr), + ResOperation(rop.CALL, [ConstInt(3)], None), + ]) + From antocuni at codespeak.net Wed May 20 16:21:29 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 20 May 2009 16:21:29 +0200 (CEST) Subject: [pypy-svn] r65331 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090520142129.875B1169F06@codespeak.net> Author: antocuni Date: Wed May 20 16:21:28 2009 New Revision: 65331 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/methodfactory.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Log: the code to implement bridges was broken, fix it: - don't put a 'ret' in emit_store_opargs, else the jump is never taken - put the array of failing ops on the cpu, not on the method, else the "failed_op" index stored in inputargs is meaningless - add a bunch of debugging stuff Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Wed May 20 16:21:28 2009 @@ -124,7 +124,6 @@ self.name = name self.loop = loop self.boxes = {} # box --> local var - self.failing_ops = [] # index --> op self.branches = [] self.branchlabels = [] self.consts = {} # object --> index @@ -183,10 +182,10 @@ def get_index_for_failing_op(self, op): try: - return self.failing_ops.index(op) + return self.cpu.failing_ops.index(op) except ValueError: - self.failing_ops.append(op) - return len(self.failing_ops)-1 + self.cpu.failing_ops.append(op) + return len(self.cpu.failing_ops)-1 def get_index_for_constant(self, obj): try: @@ -231,6 +230,7 @@ self.il.Emit(OpCodes.Stelem, clitype) def emit_load_inputargs(self): + self.emit_debug("executing: " + self.name) i = 0 for box in self.loop.inputargs: self.load_inputarg(i, box.type, box.getCliType()) @@ -243,8 +243,7 @@ def emit_operations(self, operations): for op in operations: - if self.debug: - self.il.EmitWriteLine(op.repr()) + self.emit_debug(op.repr()) func = self.operations[op.opnum] assert func is not None func(self, op) @@ -278,6 +277,10 @@ def store_result(self, op): op.result.store(self) + def emit_debug(self, msg): + if self.debug: + self.il.EmitWriteLine(msg) + def emit_clear_exception(self): self.av_inputargs.load(self) self.il.Emit(OpCodes.Ldnull) @@ -315,6 +318,7 @@ field = dotnet.typeof(InputArgs).GetField('failed_op') self.il.Emit(OpCodes.Stfld, field) self.emit_store_opargs(op) + self.il.Emit(OpCodes.Ret) def emit_store_opargs(self, op): # store the latest values @@ -322,7 +326,6 @@ for box in op.args: self.store_inputarg(i, box.type, box.getCliType(), box) i+=1 - self.il.Emit(OpCodes.Ret) def emit_guard_bool(self, op, opcode): assert op.suboperations @@ -388,9 +391,10 @@ self.il.Emit(OpCodes.Br, self.il_loop_start) else: # it's a real bridge + self.emit_debug('jumping to ' + target.name) self.emit_store_opargs(op) + target._cli_funcbox.load(self) self.av_inputargs.load(self) - self.loop._cli_funcbox.load(self) methinfo = dotnet.typeof(LoopDelegate).GetMethod('Invoke') if self.tailcall: self.il.Emit(OpCodes.Tailcall) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/methodfactory.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/methodfactory.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/methodfactory.py Wed May 20 16:21:28 2009 @@ -71,7 +71,7 @@ def create_delegate(self, delegatetype, consts): t = self.typeBuilder.CreateType() methinfo = t.GetMethod("invoke") -## if self.name == 'generated_case_1': +## if self.name == 'Loop #0(r1)_2': ## assemblyData.auto_save_assembly.Save() return System.Delegate.CreateDelegate(delegatetype, consts, Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Wed May 20 16:21:28 2009 @@ -20,6 +20,10 @@ _cli_funcbox = None _cli_meth = None + _cli_count = 0 + + def _get_cli_name(self): + return '%s(r%d)' % (self.name, self._cli_count) class CliCPU(model.AbstractCPU): @@ -34,6 +38,7 @@ self.stats = stats self.translate_support_code = translate_support_code self.inputargs = None + self.failing_ops = [] # index --> op self.ll_ovf_exc = self._get_prebuilt_exc(OverflowError) self.ll_zero_exc = self._get_prebuilt_exc(ZeroDivisionError) @@ -82,13 +87,13 @@ else: # discard previously compiled loop loop._cli_funcbox.holder.SetFunc(None) - loop._cli_meth = Method(self, loop.name, loop) + loop._cli_meth = Method(self, loop._get_cli_name(), loop) + loop._cli_count += 1 def execute_operations(self, loop): - meth = loop._cli_meth func = loop._cli_funcbox.holder.GetFunc() func(self.get_inputargs()) - return meth.failing_ops[self.inputargs.get_failed_op()] + return self.failing_ops[self.inputargs.get_failed_op()] def set_future_value_int(self, index, intvalue): self.get_inputargs().set_int(index, intvalue) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py Wed May 20 16:21:28 2009 @@ -38,6 +38,3 @@ test_long_long = skip test_free_object = skip test_stopatxpolicy = skip - - test_bridge_from_interpreter = _skip - From antocuni at codespeak.net Wed May 20 18:19:31 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 20 May 2009 18:19:31 +0200 (CEST) Subject: [pypy-svn] r65335 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090520161931.50F9A169F1C@codespeak.net> Author: antocuni Date: Wed May 20 18:19:29 2009 New Revision: 65335 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Log: update test status: two more tests pass, one fails only on mono but not on windows, another is not a translation test Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_basic.py Wed May 20 18:19:29 2009 @@ -16,17 +16,21 @@ # for the individual tests see # ====> ../../../metainterp/test/test_basic.py + def mono_bug(self): + py.test.skip('mono bug?') + def skip(self): py.test.skip('in-progress') - test_stopatxpolicy = skip + test_stopatxpolicy = mono_bug + test_print = skip test_bridge_from_interpreter = skip test_bridge_from_interpreter_2 = skip - test_bridge_from_interpreter_3 = skip - test_bridge_from_interpreter_4 = skip - test_bridge_leaving_interpreter_5 = skip test_free_object = skip + def test_bridge_from_interpreter_4(self): + pass # not a translation test + def test_we_are_jitted(self): py.test.skip("it seems to fail even with the x86 backend, didn't investigate the problem") From antocuni at codespeak.net Wed May 20 18:32:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 20 May 2009 18:32:08 +0200 (CEST) Subject: [pypy-svn] r65336 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090520163208.5F353169F7A@codespeak.net> Author: antocuni Date: Wed May 20 18:32:07 2009 New Revision: 65336 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Log: good, all these tests pass now Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_send.py Wed May 20 18:32:07 2009 @@ -7,12 +7,6 @@ # for the individual tests see # ====> ../../../metainterp/test/test_send.py - def skip_loop(self): - py.test.skip('jump across loops not implemented yet') - - test_three_receivers = skip_loop - test_three_classes = skip_loop - test_recursive_call_to_portal_from_blackhole = skip_loop - test_indirect_call_unknown_object_1 = skip_loop - test_three_cases = skip_loop + def test_recursive_call_to_portal_from_blackhole(self): + py.test.skip('string return values are not supported') From antocuni at codespeak.net Wed May 20 18:36:31 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 20 May 2009 18:36:31 +0200 (CEST) Subject: [pypy-svn] r65337 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090520163631.99F0A169EF3@codespeak.net> Author: antocuni Date: Wed May 20 18:36:30 2009 New Revision: 65337 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Log: more passing tests. test_int_lshift_ovf still fails because of a NotImplementedError (will investigate later) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Wed May 20 18:36:30 2009 @@ -7,17 +7,10 @@ # for the individual tests see # ====> ../../../metainterp/test/test_exception.py - def skip_loop(self): - py.test.skip('jump across loops not implemented yet') - def skip(self): py.test.skip('in-progress') - test_bridge_from_guard_exception = skip_loop - test_exception_four_cases = skip_loop - test_bridge_from_interpreter_exc = skip_loop - test_bridge_from_interpreter_exc_2 = skip_loop - test_int_lshift_ovf = skip_loop + test_int_lshift_ovf = skip From antocuni at codespeak.net Wed May 20 18:42:02 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 20 May 2009 18:42:02 +0200 (CEST) Subject: [pypy-svn] r65338 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090520164202.3A1E1169F54@codespeak.net> Author: antocuni Date: Wed May 20 18:42:01 2009 New Revision: 65338 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Log: implement set_overflow_error to make test_int_lshift_ovf passing Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Wed May 20 18:42:01 2009 @@ -129,10 +129,14 @@ self.get_inputargs().set_exc_value(None) def set_overflow_error(self): - raise NotImplementedError + exc_obj = ootype.cast_to_object(self.ll_ovf_exc) + exc_value = dotnet.cast_to_native_object(exc_obj) + self.get_inputargs().set_exc_value(exc_value) def set_zero_division_error(self): - raise NotImplementedError + exc_obj = ootype.cast_to_object(self.ll_zero_exc) + exc_value = dotnet.cast_to_native_object(exc_obj) + self.get_inputargs().set_exc_value(exc_value) # ---------------------- Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_exception.py Wed May 20 18:42:01 2009 @@ -7,10 +7,5 @@ # for the individual tests see # ====> ../../../metainterp/test/test_exception.py - def skip(self): - py.test.skip('in-progress') - - test_int_lshift_ovf = skip - - + pass From antocuni at codespeak.net Wed May 20 18:51:57 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 20 May 2009 18:51:57 +0200 (CEST) Subject: [pypy-svn] r65339 - pypy/branch/pyjitpl5/pypy/jit/backend/cli Message-ID: <20090520165157.9E5A7169F1C@codespeak.net> Author: antocuni Date: Wed May 20 18:51:57 2009 New Revision: 65339 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Log: be explicit on which operation we don't expect in the cli backend. Only few "real" operations are left now Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Wed May 20 18:51:57 2009 @@ -504,21 +504,26 @@ def not_implemented(self, op): raise NotImplementedError - emit_op_cast_int_to_ptr = not_implemented emit_op_guard_nonvirtualized = not_implemented emit_op_unicodelen = not_implemented - emit_op_setfield_raw = not_implemented - emit_op_cast_ptr_to_int = not_implemented emit_op_newunicode = not_implemented emit_op_new_array = not_implemented emit_op_unicodegetitem = not_implemented emit_op_strgetitem = not_implemented - emit_op_getfield_raw = not_implemented - emit_op_unicodesetitem = not_implemented - emit_op_getfield_raw_pure = not_implemented emit_op_strlen = not_implemented emit_op_newstr = not_implemented - emit_op_strsetitem = not_implemented + + def lltype_only(self, op): + print 'Operation %s is lltype specific, should not get here!' % op.getopname() + raise NotImplementedError + + emit_op_setfield_raw = lltype_only + emit_op_getfield_raw = lltype_only + emit_op_getfield_raw_pure = lltype_only + emit_op_strsetitem = lltype_only + emit_op_unicodesetitem = lltype_only + emit_op_cast_int_to_ptr = lltype_only + emit_op_cast_ptr_to_int = lltype_only # -------------------------------------------------------------------- From antocuni at codespeak.net Thu May 21 10:06:40 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 10:06:40 +0200 (CEST) Subject: [pypy-svn] r65341 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090521080640.05049169F9F@codespeak.net> Author: antocuni Date: Thu May 21 10:06:38 2009 New Revision: 65341 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py (contents, props changed) Log: add new tests (to be run directly through Python for .NET); most of them pass, a bunch can be run only after translation, only one seems to be related to a real failure Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py Thu May 21 10:06:38 2009 @@ -0,0 +1,25 @@ +import py +from pypy.jit.metainterp.test import test_loop +from pypy.jit.backend.cli.test.test_basic import CliJitMixin + + +class TestLoop(CliJitMixin, test_loop.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_loop.py + + def skip(self): + py.test.skip("works only after translation") + + def _skip(self): + py.test.skip("in-progress") + + test_loop_with_two_paths = skip + test_interp_many_paths = skip + test_interp_many_paths_2 = skip + test_adapt_bridge_to_merge_point = skip + test_outer_and_inner_loop = skip + test_path_with_operations_not_from_start_2 = skip + + test_loop_unicode = _skip + + From antocuni at codespeak.net Thu May 21 10:09:52 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 10:09:52 +0200 (CEST) Subject: [pypy-svn] r65342 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090521080952.2CA7B169F96@codespeak.net> Author: antocuni Date: Thu May 21 10:09:51 2009 New Revision: 65342 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py Log: I was wrong, this test also has no chances to pass without translation Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py Thu May 21 10:09:51 2009 @@ -10,16 +10,12 @@ def skip(self): py.test.skip("works only after translation") - def _skip(self): - py.test.skip("in-progress") - test_loop_with_two_paths = skip test_interp_many_paths = skip test_interp_many_paths_2 = skip test_adapt_bridge_to_merge_point = skip test_outer_and_inner_loop = skip test_path_with_operations_not_from_start_2 = skip - - test_loop_unicode = _skip + test_loop_unicode = skip From antocuni at codespeak.net Thu May 21 10:20:00 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 10:20:00 +0200 (CEST) Subject: [pypy-svn] r65343 - pypy/branch/pyjitpl5/pypy/jit/backend/cli/test Message-ID: <20090521082000.4524D169F97@codespeak.net> Author: antocuni Date: Thu May 21 10:19:59 2009 New Revision: 65343 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py (contents, props changed) Log: more tests, most of them pass :-) Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py Thu May 21 10:19:59 2009 @@ -0,0 +1,15 @@ +import py +from pypy.jit.backend.cli.test.test_zrpy_basic import CliTranslatedJitMixin +from pypy.jit.metainterp.test import test_loop + + +class TestLoop(CliTranslatedJitMixin, test_loop.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_loop.py + + def skip(self): + py.test.skip('in-progress') + + test_interp_many_paths = skip + test_interp_many_paths_2 = skip + test_loop_unicode = skip From antocuni at codespeak.net Thu May 21 11:46:25 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 11:46:25 +0200 (CEST) Subject: [pypy-svn] r65344 - in pypy/branch/pyjitpl5/pypy/jit: backend/cli backend/cli/test backend/test metainterp/test Message-ID: <20090521094625.D8EAF169F5C@codespeak.net> Author: antocuni Date: Thu May 21 11:46:23 2009 New Revision: 65344 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Log: - add a new test to test_loop to test string operations - fix oosends to String and Unicode objects - test_loop_{string,unicode} pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 21 11:46:23 2009 @@ -418,7 +418,8 @@ assert isinstance(descr, runner.StaticMethDescr) delegate_type = descr.get_delegate_clitype() meth_invoke = descr.get_meth_info() - self._emit_call(op, delegate_type, meth_invoke, descr.has_result) + self._emit_call(op, OpCodes.Callvirt, delegate_type, + meth_invoke, descr.has_result) def emit_op_call(self, op): emit_op = Method.emit_op_call_impl.im_func @@ -432,17 +433,18 @@ assert isinstance(descr, runner.MethDescr) clitype = descr.get_self_clitype() methinfo = descr.get_meth_info() - self._emit_call(op, clitype, methinfo, descr.has_result) + opcode = descr.get_call_opcode() + self._emit_call(op, opcode, clitype, methinfo, descr.has_result) emit_op_oosend_pure = emit_op_oosend - def _emit_call(self, op, clitype, methinfo, has_result): + def _emit_call(self, op, opcode, clitype, methinfo, has_result): av_sm, args_av = op.args[0], op.args[1:] av_sm.load(self) self.il.Emit(OpCodes.Castclass, clitype) for av_arg in args_av: av_arg.load(self) - self.il.Emit(OpCodes.Callvirt, methinfo) + self.il.Emit(opcode, methinfo) if has_result: self.store_result(op) @@ -505,13 +507,7 @@ raise NotImplementedError emit_op_guard_nonvirtualized = not_implemented - emit_op_unicodelen = not_implemented - emit_op_newunicode = not_implemented emit_op_new_array = not_implemented - emit_op_unicodegetitem = not_implemented - emit_op_strgetitem = not_implemented - emit_op_strlen = not_implemented - emit_op_newstr = not_implemented def lltype_only(self, op): print 'Operation %s is lltype specific, should not get here!' % op.getopname() @@ -524,6 +520,12 @@ emit_op_unicodesetitem = lltype_only emit_op_cast_int_to_ptr = lltype_only emit_op_cast_ptr_to_int = lltype_only + emit_op_newstr = lltype_only + emit_op_strlen = lltype_only + emit_op_strgetitem = lltype_only + emit_op_newunicode = lltype_only + emit_op_unicodelen = lltype_only + emit_op_unicodegetitem = lltype_only # -------------------------------------------------------------------- Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 21 11:46:23 2009 @@ -13,7 +13,9 @@ from pypy.translator.cli.dotnet import CLR System = CLR.System +OpCodes = System.Reflection.Emit.OpCodes InputArgs = CLR.pypy.runtime.InputArgs +cpypyString = dotnet.classof(CLR.pypy.runtime.String) class __extend__(TreeLoop): __metaclass__ = extendabletype @@ -62,6 +64,8 @@ @cached_method('_methcache') def methdescrof(self, SELFTYPE, methname): + if SELFTYPE in (ootype.String, ootype.Unicode): + return StringMethDescr(SELFTYPE, methname) return MethDescr(SELFTYPE, methname) @cached_method('_typecache') @@ -348,6 +352,19 @@ clitype = self.get_self_clitype() return clitype.GetMethod(self.methname+'') + def get_call_opcode(self): + return OpCodes.Callvirt + + +class StringMethDescr(MethDescr): + + def get_meth_info(self): + clitype = dotnet.class2type(cpypyString) + return clitype.GetMethod(self.methname+'') + + def get_call_opcode(self): + return OpCodes.Call + class FieldDescr(AbstractDescr): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py Thu May 21 11:46:23 2009 @@ -17,5 +17,5 @@ test_outer_and_inner_loop = skip test_path_with_operations_not_from_start_2 = skip test_loop_unicode = skip - + test_loop_string = skip Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py Thu May 21 11:46:23 2009 @@ -10,6 +10,10 @@ def skip(self): py.test.skip('in-progress') - test_interp_many_paths = skip - test_interp_many_paths_2 = skip - test_loop_unicode = skip + def test_interp_many_paths(self): + pass # no chance to pass it after translation, because it passes + # non-int arguments to the function + + def test_interp_many_paths_2(self): + pass # see above + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/test/support.py Thu May 21 11:46:23 2009 @@ -104,3 +104,9 @@ from pypy.translator.cli.test.runtest import compile_graph func = compile_graph(entry_point_graph, t, nowrap=True, standalone=True) return func(*args) + + def run_directly(self, fn, args): + from pypy.translator.cli.test.runtest import compile_function, get_annotation + ann = [get_annotation(x) for x in args] + clifunc = compile_function(fn, ann) + return clifunc(*args) 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 Thu May 21 11:46:23 2009 @@ -16,6 +16,9 @@ CPUClass=self.CPUClass, type_system=self.type_system) + def run_directly(self, f, args): + return f(*args) + def test_simple_loop(self): myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) def f(x, y): @@ -348,7 +351,21 @@ x += unichr(n) n -= 1 return hash(x) - expected = f(100) + expected = self.run_directly(f, [100]) + res = self.meta_interp(f, [100]) + assert res == expected + + def test_loop_string(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + def f(n): + x = '' + while n > 13: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + x += chr(n) + n -= 1 + return hash(x) + expected = self.run_directly(f, [100]) res = self.meta_interp(f, [100]) assert res == expected From antocuni at codespeak.net Thu May 21 12:39:36 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 12:39:36 +0200 (CEST) Subject: [pypy-svn] r65345 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090521103936.96331169F06@codespeak.net> Author: antocuni Date: Thu May 21 12:39:34 2009 New Revision: 65345 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Log: port more tests, implement do_oonewarray; test_simple_array passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 21 12:39:34 2009 @@ -149,6 +149,11 @@ assert len(args) == 1 # but we don't need it, so ignore return typedescr.create() + def do_new_array(self, args, typedescr): + assert isinstance(typedescr, TypeDescr) + assert len(args) == 1 + return typedescr.create_array(args[0]) + def do_runtimenew(self, args, descr): classbox = args[0] classobj = ootype.cast_from_object(ootype.Class, classbox.getobj()) Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py Thu May 21 12:39:34 2009 @@ -0,0 +1,18 @@ +import py +from pypy.jit.metainterp.test import test_vlist +from pypy.jit.backend.cli.test.test_basic import CliJitMixin + + +class TestVlist(CliJitMixin, test_vlist.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_vlist.py + + def skip(self): + py.test.skip("works only after translation") + + def _skip(self): + py.test.skip("in-progress") + + test_list_pass_around = _skip + test_cannot_be_virtual = _skip + test_ll_fixed_setitem_fast = _skip From antocuni at codespeak.net Thu May 21 13:55:09 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 13:55:09 +0200 (CEST) Subject: [pypy-svn] r65346 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090521115509.BB87D169E92@codespeak.net> Author: antocuni Date: Thu May 21 13:55:06 2009 New Revision: 65346 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py Log: implement emit_op_new_arry, but comment it out as it cannot be tested without translation. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 21 13:55:06 2009 @@ -502,12 +502,18 @@ self.il.Emit(OpCodes.Castclass, clitype) self.il.Emit(OpCodes.Ldlen) self.store_result(op) - - def not_implemented(self, op): + + def emit_op_new_array(self, op): raise NotImplementedError +## descr = op.descr +## assert isinstance(descr, runner.TypeDescr) +## item_clitype = descr.get_clitype() +## op.args[0].load(self) +## self.il.Emit(OpCodes.Newarr, item_clitype) +## self.store_result(op) - emit_op_guard_nonvirtualized = not_implemented - emit_op_new_array = not_implemented + def emit_op_guard_nonvirtualized(self, op): + raise NotImplementedError def lltype_only(self, op): print 'Operation %s is lltype specific, should not get here!' % op.getopname() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Thu May 21 13:55:06 2009 @@ -277,13 +277,12 @@ self.getarraylength = getarraylength self.instanceof = instanceof self.ooclass = get_class_for_type(TYPE) - self.ooarrayclass = get_class_for_type(ARRAY) def get_clitype(self): return dotnet.class2type(self.ooclass) def get_array_clitype(self): - return dotnet.class2type(self.ooarrayclass) + return self.get_clitype().MakeArrayType() def get_constructor_info(self): clitype = self.get_clitype() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py Thu May 21 13:55:06 2009 @@ -10,9 +10,6 @@ def skip(self): py.test.skip("works only after translation") - def _skip(self): - py.test.skip("in-progress") - - test_list_pass_around = _skip - test_cannot_be_virtual = _skip - test_ll_fixed_setitem_fast = _skip + test_list_pass_around = skip + test_cannot_be_virtual = skip + test_ll_fixed_setitem_fast = skip From antocuni at codespeak.net Thu May 21 14:05:48 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 14:05:48 +0200 (CEST) Subject: [pypy-svn] r65347 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090521120548.C613A169EAA@codespeak.net> Author: antocuni Date: Thu May 21 14:05:47 2009 New Revision: 65347 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Log: implement emit_op_new_arry to make almost all these tests passing Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 21 14:05:47 2009 @@ -504,13 +504,12 @@ self.store_result(op) def emit_op_new_array(self, op): - raise NotImplementedError -## descr = op.descr -## assert isinstance(descr, runner.TypeDescr) -## item_clitype = descr.get_clitype() -## op.args[0].load(self) -## self.il.Emit(OpCodes.Newarr, item_clitype) -## self.store_result(op) + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + item_clitype = descr.get_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Newarr, item_clitype) + self.store_result(op) def emit_op_guard_nonvirtualized(self, op): raise NotImplementedError Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py Thu May 21 14:05:47 2009 @@ -0,0 +1,13 @@ +import py +from pypy.jit.backend.cli.test.test_zrpy_basic import CliTranslatedJitMixin +from pypy.jit.metainterp.test import test_vlist + + +class TestVList(CliTranslatedJitMixin, test_vlist.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_vlist.py + + def skip(self): + py.test.skip('in-progress') + + test_ll_fixed_setitem_fast = skip From antocuni at codespeak.net Thu May 21 14:12:42 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 14:12:42 +0200 (CEST) Subject: [pypy-svn] r65348 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli/test rpython/ootypesystem Message-ID: <20090521121242.71B38169EC4@codespeak.net> Author: antocuni Date: Thu May 21 14:12:41 2009 New Revision: 65348 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rpbc.py Log: delay the call to get_concrete_calltable, so that the low level types of the methods arguments have been fully computed, much like r65288. test_ll_fixed_setitem_fast passes Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py Thu May 21 14:12:41 2009 @@ -7,7 +7,4 @@ # for the individual tests see # ====> ../../../metainterp/test/test_vlist.py - def skip(self): - py.test.skip('in-progress') - - test_ll_fixed_setitem_fast = skip + pass Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rpbc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rpbc.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rpbc.py Thu May 21 14:12:41 2009 @@ -116,10 +116,11 @@ class MethodsPBCRepr(AbstractMethodsPBCRepr): - def __init__(self, rtyper, s_pbc): - AbstractMethodsPBCRepr.__init__(self, rtyper, s_pbc) - sampledesc = s_pbc.descriptions.iterkeys().next() - self.concretetable, _ = get_concrete_calltable(rtyper, + concretetable = None # set by _setup_repr_final + + def _setup_repr_final(self): + sampledesc = self.s_pbc.descriptions.iterkeys().next() + self.concretetable, _ = get_concrete_calltable(self.rtyper, sampledesc.funcdesc.getcallfamily()) def rtype_simple_call(self, hop): From antocuni at codespeak.net Thu May 21 14:31:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 14:31:04 +0200 (CEST) Subject: [pypy-svn] r65349 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli/test translator/cli Message-ID: <20090521123104.746E9169F07@codespeak.net> Author: antocuni Date: Thu May 21 14:31:03 2009 New Revision: 65349 Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py Log: port more tests, ignore 'promote_virtualizable' in the normal cli backend. Added: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py Thu May 21 14:31:03 2009 @@ -0,0 +1,20 @@ +import py +from pypy.jit.backend.cli.test.test_zrpy_basic import CliTranslatedJitMixin +from pypy.jit.metainterp.test import test_virtualizable + + +class TestVirtualizable(CliTranslatedJitMixin, test_virtualizable.TestOOtype): + # for the individual tests see + # ====> ../../../metainterp/test/test_virtualizable.py + + def skip(self): + py.test.skip('in-progress') + + test_virtual_on_virtualizable = skip + test_no_virtual_on_virtualizable = skip + test_unequal_list_lengths_cannot_be_virtual = skip + test_virtualizable_hierarchy = skip + test_non_virtual_on_always_virtual = skip + test_external_pass = skip + test_always_virtual_with_origfields = skip + test_pass_always_virtual_to_bridge = skip Modified: pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/cli/opcodes.py Thu May 21 14:31:03 2009 @@ -80,6 +80,7 @@ 'keepalive': Ignore, 'is_early_constant': [PushPrimitive(ootype.Bool, False)], 'jit_marker': Ignore, + 'promote_virtualizable': Ignore, } # __________ numeric operations __________ From antocuni at codespeak.net Thu May 21 14:50:56 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 14:50:56 +0200 (CEST) Subject: [pypy-svn] r65350 - in pypy/branch/pyjitpl5/pypy/jit/backend/cli: . test Message-ID: <20090521125056.64C7A168044@codespeak.net> Author: antocuni Date: Thu May 21 14:50:55 2009 New Revision: 65350 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py Log: implement emit_op_instanceof, and all the remaining virtualizable tests pass. Moreover, add stubs for all the few still missing operations, so that we can kill the warning and put an assert instead Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py Thu May 21 14:50:55 2009 @@ -410,6 +410,19 @@ self.il.Emit(OpCodes.Newobj, ctor_info) self.store_result(op) + def emit_op_runtimenew(self, op): + raise NotImplementedError + + def emit_op_instanceof(self, op): + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + clitype = descr.get_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Isinst, clitype) + self.il.Emit(OpCodes.Ldnull) + self.il.Emit(OpCodes.Cgt_Un) + self.store_result(op) + def emit_op_ooidentityhash(self, op): raise NotImplementedError @@ -518,6 +531,7 @@ print 'Operation %s is lltype specific, should not get here!' % op.getopname() raise NotImplementedError + emit_op_new = lltype_only emit_op_setfield_raw = lltype_only emit_op_getfield_raw = lltype_only emit_op_getfield_raw_pure = lltype_only @@ -568,10 +582,7 @@ elif isinstance(instr, opcodes.PushArg): lines.append('self.push_arg(op, %d)' % instr.n) else: - if not isinstance(instr, str): - print 'WARNING: unknown instruction %s' % instr - return - + assert isinstance(instr, str), 'unknown instruction %s' % instr if instr.startswith('call '): signature = instr[len('call '):] renderCall(lines, signature) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py Thu May 21 14:50:55 2009 @@ -7,14 +7,4 @@ # for the individual tests see # ====> ../../../metainterp/test/test_virtualizable.py - def skip(self): - py.test.skip('in-progress') - - test_virtual_on_virtualizable = skip - test_no_virtual_on_virtualizable = skip - test_unequal_list_lengths_cannot_be_virtual = skip - test_virtualizable_hierarchy = skip - test_non_virtual_on_always_virtual = skip - test_external_pass = skip - test_always_virtual_with_origfields = skip - test_pass_always_virtual_to_bridge = skip + pass From antocuni at codespeak.net Thu May 21 21:51:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 21 May 2009 21:51:08 +0200 (CEST) Subject: [pypy-svn] r65351 - pypy/branch/pyjitpl5/pypy/config Message-ID: <20090521195108.B4EF9169F51@codespeak.net> Author: antocuni Date: Thu May 21 21:51:06 2009 New Revision: 65351 Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py Log: use "boehm" as a dummy value, else it conflicts with tl/pypyjit.py Modified: pypy/branch/pyjitpl5/pypy/config/translationoption.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/config/translationoption.py (original) +++ pypy/branch/pyjitpl5/pypy/config/translationoption.py Thu May 21 21:51:06 2009 @@ -30,7 +30,7 @@ ("translation.backendopt.heap2stack", False), ("translation.backendopt.clever_malloc_removal", False), ("translation.list_comprehension_operations", False), - ("translation.gc", "generation"), # it's not really used, but some jit code expects a value here + ("translation.gc", "boehm"), # it's not really used, but some jit code expects a value here ] }), ChoiceOption("backend", "Backend to use for code generation", From antocuni at codespeak.net Fri May 22 00:47:35 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 22 May 2009 00:47:35 +0200 (CEST) Subject: [pypy-svn] r65352 - pypy/branch/pyjitpl5/pypy/jit/backend/cli Message-ID: <20090521224735.6BE41169F01@codespeak.net> Author: antocuni Date: Fri May 22 00:47:33 2009 New Revision: 65352 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Log: implement sort_key() for all CLI descrs Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py Fri May 22 00:47:33 2009 @@ -220,6 +220,16 @@ # ---------------------------------------------------------------------- key_manager = KeyManager() +class DescrWithKey(AbstractDescr): + key = -1 + + def __init__(self, key): + self.key = key_manager.getkey(key) + + def sort_key(self): + return self.key + + def get_class_for_type(T): if T is ootype.Void: return ootype.nullruntimeclass @@ -238,10 +248,10 @@ else: assert False - -class TypeDescr(AbstractDescr): +class TypeDescr(DescrWithKey): def __init__(self, TYPE): + DescrWithKey.__init__(self, TYPE) from pypy.jit.backend.llgraph.runner import boxresult from pypy.jit.metainterp.warmspot import unwrap ARRAY = ootype.Array(TYPE) @@ -288,13 +298,14 @@ clitype = self.get_clitype() return clitype.GetConstructor(dotnet.new_array(System.Type, 0)) -class StaticMethDescr(AbstractDescr): +class StaticMethDescr(DescrWithKey): callfunc = None funcclass = ootype.nullruntimeclass has_result = False def __init__(self, FUNC, ARGS, RESULT): + DescrWithKey.__init__(self, (FUNC, ARGS, RESULT)) from pypy.jit.backend.llgraph.runner import boxresult, make_getargs getargs = make_getargs(FUNC.ARGS) def callfunc(funcbox, argboxes): @@ -331,6 +342,7 @@ selfclass = ootype.nullruntimeclass methname = '' has_result = False + key = -1 def __init__(self, SELFTYPE, methname): from pypy.jit.backend.llgraph.runner import boxresult, make_getargs @@ -348,6 +360,10 @@ self.selfclass = ootype.runtimeClass(SELFTYPE) self.methname = methname self.has_result = (METH.RESULT != ootype.Void) + self.key = key_manager.getkey((SELFTYPE, methname)) + + def sort_key(self): + return self.key def get_self_clitype(self): return dotnet.class2type(self.selfclass) @@ -370,15 +386,15 @@ return OpCodes.Call -class FieldDescr(AbstractDescr): +class FieldDescr(DescrWithKey): getfield = None setfield = None selfclass = ootype.nullruntimeclass fieldname = '' - key = -1 def __init__(self, TYPE, fieldname): + DescrWithKey.__init__(self, (TYPE, fieldname)) from pypy.jit.backend.llgraph.runner import boxresult from pypy.jit.metainterp.warmspot import unwrap _, T = TYPE._lookup_field(fieldname) @@ -397,9 +413,6 @@ self.fieldname = fieldname self.key = key_manager.getkey((TYPE, fieldname)) - def sort_key(self): - return self.key - def equals(self, other): assert isinstance(other, FieldDescr) return self.key == other.key From pedronis at codespeak.net Fri May 22 12:40:03 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 22 May 2009 12:40:03 +0200 (CEST) Subject: [pypy-svn] r65356 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090522104003.B1BF0169F4C@codespeak.net> Author: pedronis Date: Fri May 22 12:40:01 2009 New Revision: 65356 Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt Log: slightly more pre-puplication friendly Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/announcement.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/announcement.txt Fri May 22 12:40:01 2009 @@ -13,7 +13,7 @@ during the conference since it will give you a good overview of the status of development. -XXX When/if tutorial? +.. xxx When/if tutorial? On the morning of the first sprint day we will also have a tutorial session for those new to PyPy development. @@ -24,7 +24,7 @@ There are many possible and interesting sprint topics to work on - here we list some possible task areas: -XXX +TBA ------------ Registration @@ -73,4 +73,4 @@ .. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint .. _`the technical reports available and other relevant documentation`: http://codespeak.net/pypy/dist/pypy/doc/docindex.html -.. _`EuroPython schedule`: http://europython.eu/XXX +.. _`EuroPython schedule`: http://europython.eu/xxx From cfbolz at codespeak.net Fri May 22 13:45:13 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 22 May 2009 13:45:13 +0200 (CEST) Subject: [pypy-svn] r65357 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090522114513.213EB169FA7@codespeak.net> Author: cfbolz Date: Fri May 22 13:45:12 2009 New Revision: 65357 Modified: pypy/extradoc/sprintinfo/ep2009/people.txt Log: my dates Modified: pypy/extradoc/sprintinfo/ep2009/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/people.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/people.txt Fri May 22 13:45:12 2009 @@ -12,6 +12,7 @@ ==================== ============== ============================ Samuele Pedroni 28/5 ? Antonio Cuni 28/4 ETAPS Hotel (shared with cfbolz) +Carl Friedrich Bolz 28/4 ETAPS Hotel ==================== ============== ============================ People on the following list were present at previous sprints: @@ -31,7 +32,6 @@ Bert Freudenberg ? ? Boris Feigin ? ? Camillo Bruni ? ? -Carl Friedrich Bolz ? ? Christian Tismer ? ? Eric van Riet Paap ? ? Guido Wesdorp ? ? From antocuni at codespeak.net Fri May 22 13:56:38 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 22 May 2009 13:56:38 +0200 (CEST) Subject: [pypy-svn] r65358 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090522115638.A6D4F169EB1@codespeak.net> Author: antocuni Date: Fri May 22 13:56:38 2009 New Revision: 65358 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: these two tests pass also on ootype nowadays 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 May 22 13:56:38 2009 @@ -95,8 +95,6 @@ def test_tl_base(self): res = self.meta_interp(self.main.im_func, [0, 6], listops=True) assert res == 5040 - if self.type_system == 'ootype': - py.test.skip('optimizing problem') self.check_loops({'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, 'guard_false':1, 'guard_value':1}) @@ -104,8 +102,6 @@ def test_tl_2(self): res = self.meta_interp(self.main.im_func, [1, 10], listops=True) assert res == self.main.im_func(1, 10) - if self.type_system == 'ootype': - py.test.skip('optimizing problem') self.check_loops({'int_sub':1, 'int_le':1, 'int_is_true':1, 'guard_false':1, 'jump':1, 'guard_value':1}) From cfbolz at codespeak.net Fri May 22 18:43:46 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 22 May 2009 18:43:46 +0200 (CEST) Subject: [pypy-svn] r65359 - pypy/branch/speedup-global2 Message-ID: <20090522164346.5F61E169F29@codespeak.net> Author: cfbolz Date: Fri May 22 18:43:44 2009 New Revision: 65359 Added: pypy/branch/speedup-global2/ - copied from r65358, pypy/trunk/ Log: Make a new branch for fixing globals, to have a new enough py-lib on it to be able to start a buildbot run. From cfbolz at codespeak.net Fri May 22 18:53:15 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 22 May 2009 18:53:15 +0200 (CEST) Subject: [pypy-svn] r65360 - in pypy/branch/speedup-global2/pypy: config interpreter objspace objspace/fake objspace/std objspace/std/test translator/microbench Message-ID: <20090522165315.42F1F16A004@codespeak.net> Author: cfbolz Date: Fri May 22 18:53:13 2009 New Revision: 65360 Added: pypy/branch/speedup-global2/pypy/objspace/std/celldict.py (contents, props changed) pypy/branch/speedup-global2/pypy/objspace/std/test/test_celldict.py (contents, props changed) Modified: pypy/branch/speedup-global2/pypy/config/pypyoption.py pypy/branch/speedup-global2/pypy/interpreter/module.py pypy/branch/speedup-global2/pypy/interpreter/pycode.py pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py pypy/branch/speedup-global2/pypy/objspace/reflective.py pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py pypy/branch/speedup-global2/pypy/objspace/std/objspace.py pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py Log: Port over changes from old speedup-globals branch: ------------------------------------------------------------------------ r62765 | cfbolz | 2009-03-09 17:53:28 +0100 (Mon, 09 Mar 2009) | 3 lines Changed paths: A /pypy/branch/speedup-globals (from /pypy/trunk:62764) A branch to try Armin's and mine newest idea about how to speed up global lookups. ------------------------------------------------------------------------ r62773 | cfbolz | 2009-03-09 19:02:50 +0100 (Mon, 09 Mar 2009) | 5 lines Changed paths: M /pypy/branch/speedup-globals/pypy/config/pypyoption.py M /pypy/branch/speedup-globals/pypy/interpreter/module.py M /pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py M /pypy/branch/speedup-globals/pypy/objspace/reflective.py M /pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py M /pypy/branch/speedup-globals/pypy/objspace/std/objspace.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py First step to make global lookups faster: Introduce a special dict implementation for modules, where every value in the RPython-level dict is a cell that contains the real value. As long as the "valid" flag on such a cell is set, it is safe to store the cell somewhere else. ------------------------------------------------------------------------ r62811 | cfbolz | 2009-03-10 16:00:52 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: A /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py M /pypy/branch/speedup-globals/pypy/objspace/std/objspace.py A /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py Actually use the cell-dict stuff to cache global lookups in frames. ------------------------------------------------------------------------ r62816 | cfbolz | 2009-03-10 16:34:17 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py help flow space ------------------------------------------------------------------------ r62819 | cfbolz | 2009-03-10 17:54:44 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py fix typo ------------------------------------------------------------------------ r62823 | cfbolz | 2009-03-10 17:57:56 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py fix gadfly ------------------------------------------------------------------------ r62827 | cfbolz | 2009-03-10 19:07:12 +0100 (Tue, 10 Mar 2009) | 4 lines Changed paths: M /pypy/branch/speedup-globals/pypy/interpreter/pycode.py M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py It turns out that using one additional dict lookup per call negates many of the benefits of this optimization. Therefore, attach the cache to the code object directly. ------------------------------------------------------------------------ r62830 | cfbolz | 2009-03-10 20:38:30 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py two more microbenchmarks ------------------------------------------------------------------------ r62845 | cfbolz | 2009-03-11 11:54:45 +0100 (Wed, 11 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py get rid of invalid flag ------------------------------------------------------------------------ r62856 | cfbolz | 2009-03-11 13:16:33 +0100 (Wed, 11 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py fix a corner-case ------------------------------------------------------------------------ Modified: pypy/branch/speedup-global2/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/speedup-global2/pypy/config/pypyoption.py (original) +++ pypy/branch/speedup-global2/pypy/config/pypyoption.py Fri May 22 18:53:13 2009 @@ -228,6 +228,13 @@ "use dictionaries optimized for flexibility", default=False), + BoolOption("withcelldict", + "use dictionaries that are opimized for being used as module dicts", + default=False, + requires=[("objspace.std.withmultidict", True), + ("objspace.opcodes.CALL_LIKELY_BUILTIN", False), + ("objspace.honor__builtins__", False)]), + BoolOption("withsharingdict", "use dictionaries that share the keys part", default=False, Modified: pypy/branch/speedup-global2/pypy/interpreter/module.py ============================================================================== --- pypy/branch/speedup-global2/pypy/interpreter/module.py (original) +++ pypy/branch/speedup-global2/pypy/interpreter/module.py Fri May 22 18:53:13 2009 @@ -11,7 +11,7 @@ def __init__(self, space, w_name, w_dict=None): self.space = space if w_dict is None: - w_dict = space.newdict(track_builtin_shadowing=True) + w_dict = space.newdict(module=True) self.w_dict = w_dict self.w_name = w_name if w_name is not None: Modified: pypy/branch/speedup-global2/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/speedup-global2/pypy/interpreter/pycode.py (original) +++ pypy/branch/speedup-global2/pypy/interpreter/pycode.py Fri May 22 18:53:13 2009 @@ -111,6 +111,10 @@ self._compute_flatcall() + if space.config.objspace.std.withcelldict: + from pypy.objspace.std.celldict import init_code + init_code(self) + co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): Modified: pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py ============================================================================== --- pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py (original) +++ pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py Fri May 22 18:53:13 2009 @@ -93,7 +93,7 @@ newint = make_dummy() newlong = make_dummy() newfloat = make_dummy() - def newdict(self, track_builtin_shadowing=False): + def newdict(self, module=False): return self.newfloat() newlist = make_dummy() emptylist = make_dummy() Modified: pypy/branch/speedup-global2/pypy/objspace/reflective.py ============================================================================== --- pypy/branch/speedup-global2/pypy/objspace/reflective.py (original) +++ pypy/branch/speedup-global2/pypy/objspace/reflective.py Fri May 22 18:53:13 2009 @@ -137,8 +137,8 @@ return None if opname == "newdict": # grr grr kwargs - def fn(track_builtin_shadowing=False): - w_obj = parentfn(track_builtin_shadowing) + def fn(module=False): + w_obj = parentfn(module) w_newobj = user_hook(w_obj) if w_newobj is not None: return w_newobj Added: pypy/branch/speedup-global2/pypy/objspace/std/celldict.py ============================================================================== --- (empty file) +++ pypy/branch/speedup-global2/pypy/objspace/std/celldict.py Fri May 22 18:53:13 2009 @@ -0,0 +1,248 @@ +from pypy.objspace.std.dictmultiobject import DictImplementation +from pypy.objspace.std.dictmultiobject import IteratorImplementation +from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash + +class ModuleCell(object): + def __init__(self, w_value=None): + self.w_value = w_value + + def invalidate(self): + w_value = self.w_value + self.w_value = None + return w_value + + def __repr__(self): + return "" % (self.w_value, ) + +class ModuleDictImplementation(DictImplementation): + def __init__(self, space): + self.space = space + self.content = {} + self.unshadowed_builtins = {} + + def getcell(self, key, make_new=True): + try: + return self.content[key] + except KeyError: + if not make_new: + raise + result = self.content[key] = ModuleCell() + return result + + def add_unshadowed_builtin(self, name, builtin_impl): + assert isinstance(builtin_impl, ModuleDictImplementation) + self.unshadowed_builtins[name] = builtin_impl + + def invalidate_unshadowed_builtin(self, name): + impl = self.unshadowed_builtins[name] + try: + cell = impl.content[name] + except KeyError: + pass + else: + w_value = cell.invalidate() + cell = impl.content[name] = ModuleCell(w_value) + + def setitem(self, w_key, w_value): + space = self.space + if space.is_w(space.type(w_key), space.w_str): + return self.setitem_str(w_key, w_value) + else: + return self._as_rdict().setitem(w_key, w_value) + + def setitem_str(self, w_key, w_value, shadows_type=True): + name = self.space.str_w(w_key) + self.getcell(name).w_value = w_value + + if name in self.unshadowed_builtins: + self.invalidate_unshadowed_builtin(name) + del self.unshadowed_builtins[name] + + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + cell = self.getcell(key, False) + cell.invalidate() + del self.content[key] + return self + elif _is_sane_hash(space, w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def length(self): + return len(self.content) + + def get(self, w_lookup): + space = self.space + w_lookup_type = space.type(w_lookup) + if space.is_w(w_lookup_type, space.w_str): + try: + return self.getcell(space.str_w(w_lookup), False).w_value + except KeyError: + return None + elif _is_sane_hash(space, w_lookup_type): + return None + else: + return self._as_rdict().get(w_lookup) + + def iteritems(self): + return ModuleDictItemIteratorImplementation(self.space, self) + + def iterkeys(self): + return ModuleDictKeyIteratorImplementation(self.space, self) + + def itervalues(self): + return ModuleDictValueIteratorImplementation(self.space, self) + + def keys(self): + space = self.space + return [space.wrap(key) for key in self.content.iterkeys()] + + def values(self): + return [cell.w_value for cell in self.content.itervalues()] + + def items(self): + space = self.space + return [space.newtuple([space.wrap(key), cell.w_value]) + for (key, cell) in self.content.iteritems()] + + def _as_rdict(self): + newimpl = self.space.DefaultDictImpl(self.space) + for k, cell in self.content.iteritems(): + newimpl.setitem(self.space.wrap(k), cell.w_value) + cell.invalidate() + for k in self.unshadowed_builtins: + self.invalidate_unshadowed_builtin(k) + return newimpl + +# grrrrr. just a copy-paste from StrKeyIteratorImplementation in dictmultiobject +class ModuleDictKeyIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iterkeys() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key in self.iterator: + return self.space.wrap(key) + else: + return None + +class ModuleDictValueIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.itervalues() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for cell in self.iterator: + return cell.w_value + else: + return None + +class ModuleDictItemIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iteritems() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key, cell in self.iterator: + return self.space.newtuple([self.space.wrap(key), cell.w_value]) + else: + return None + + + + + + + +class State(object): + def __init__(self, space): + self.space = space + self.invalidcell = ModuleCell() + self.always_invalid_cache = [] + self.neverused_dictimpl = ModuleDictImplementation(space) + +class GlobalCacheHolder(object): + def __init__(self, space): + self.cache = None + state = space.fromcache(State) + self.dictimpl = state.neverused_dictimpl + + def getcache(self, space, code, w_globals): + implementation = getimplementation(w_globals) + if self.dictimpl is implementation: + return self.cache + return self.getcache_slow(space, code, w_globals, implementation) + getcache._always_inline_ = True + + def getcache_slow(self, space, code, w_globals, implementation): + state = space.fromcache(State) + if not isinstance(implementation, ModuleDictImplementation): + missing_length = max(len(code.co_names_w) - len(state.always_invalid_cache), 0) + state.always_invalid_cache.extend([state.invalidcell] * missing_length) + cache = state.always_invalid_cache + else: + cache = [state.invalidcell] * len(code.co_names_w) + self.cache = cache + self.dictimpl = implementation + return cache + getcache_slow._dont_inline_ = True + +def init_code(code): + code.globalcacheholder = GlobalCacheHolder(code.space) + + +def get_global_cache(space, code, w_globals): + from pypy.interpreter.pycode import PyCode + if not isinstance(code, PyCode): + return [] + holder = code.globalcacheholder + return holder.getcache(space, code, w_globals) + +def getimplementation(w_dict): + if type(w_dict) is W_DictMultiObject: + return w_dict.implementation + else: + return None + +def LOAD_GLOBAL(f, nameindex, *ignored): + cell = f.cache_for_globals[nameindex] + w_value = cell.w_value + if w_value is None: + # slow path + w_value = load_global_fill_cache(f, nameindex) + f.pushvalue(w_value) +LOAD_GLOBAL._always_inline_ = True + +def find_cell_from_dict(implementation, name): + if isinstance(implementation, ModuleDictImplementation): + try: + return implementation.getcell(name, False) + except KeyError: + return None + return None + +def load_global_fill_cache(f, nameindex): + name = f.space.str_w(f.getname_w(nameindex)) + implementation = getimplementation(f.w_globals) + if isinstance(implementation, ModuleDictImplementation): + cell = find_cell_from_dict(implementation, name) + if cell is None: + builtin_impl = getimplementation(f.get_builtin().getdict()) + cell = find_cell_from_dict(builtin_impl, name) + if cell is not None: + implementation.add_unshadowed_builtin(name, builtin_impl) + + if cell is not None: + f.cache_for_globals[nameindex] = cell + return cell.w_value + return f._load_global(f.getname_w(nameindex)) +load_global_fill_cache._dont_inline_ = True Modified: pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py Fri May 22 18:53:13 2009 @@ -865,7 +865,6 @@ else: return None - import time, py class DictInfo(object): @@ -1038,8 +1037,11 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space, wary=False, sharing=False): - if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: + def __init__(w_self, space, wary=False, sharing=False, module=False): + if space.config.objspace.std.withcelldict and wary: + from pypy.objspace.std.celldict import ModuleDictImplementation + w_self.implementation = ModuleDictImplementation(space) + elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: w_self.implementation = WaryDictImplementation(space) elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) Modified: pypy/branch/speedup-global2/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/speedup-global2/pypy/objspace/std/objspace.py (original) +++ pypy/branch/speedup-global2/pypy/objspace/std/objspace.py Fri May 22 18:53:13 2009 @@ -72,7 +72,16 @@ # Import all the object types and implementations self.model = StdTypeModel(self.config) + from pypy.objspace.std.celldict import get_global_cache + class StdObjSpaceFrame(pyframe.PyFrame): + if self.config.objspace.std.withcelldict: + def __init__(self, space, code, w_globals, closure): + pyframe.PyFrame.__init__(self, space, code, w_globals, closure) + self.cache_for_globals = get_global_cache(space, code, w_globals) + + from pypy.objspace.std.celldict import LOAD_GLOBAL + if self.config.objspace.std.optimized_int_add: if self.config.objspace.std.withsmallint: def BINARY_ADD(f, oparg, *ignored): @@ -580,8 +589,8 @@ from pypy.objspace.std.listobject import W_ListObject return W_ListObject(list_w) - def newdict(self, track_builtin_shadowing=False): - if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing: + def newdict(self, module=False): + if self.config.objspace.std.withmultidict and module: from pypy.objspace.std.dictmultiobject import W_DictMultiObject return W_DictMultiObject(self, wary=True) return self.DictObjectCls(self) Added: pypy/branch/speedup-global2/pypy/objspace/std/test/test_celldict.py ============================================================================== --- (empty file) +++ pypy/branch/speedup-global2/pypy/objspace/std/test/test_celldict.py Fri May 22 18:53:13 2009 @@ -0,0 +1,259 @@ +from pypy.conftest import gettestobjspace +from pypy.objspace.std.celldict import get_global_cache, ModuleCell, ModuleDictImplementation +from pypy.interpreter import gateway + +# this file tests mostly the effects of caching global lookup. The dict +# implementation itself is tested in test_dictmultiobject.py + + +class AppTestCellDict(object): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withcelldict": True}) + cls.w_impl_used = cls.space.appexec([], """(): + import __pypy__ + def impl_used(obj): + assert "ModuleDictImplementation" in __pypy__.internal_repr(obj) + return impl_used + """) + def is_in_cache(space, w_code, w_globals, w_name): + name = space.str_w(w_name) + cache = get_global_cache(space, w_code, w_globals) + index = [space.str_w(w_n) for w_n in w_code.co_names_w].index(name) + return space.wrap(cache[index].w_value is not None) + is_in_cache = gateway.interp2app(is_in_cache) + cls.w_is_in_cache = cls.space.wrap(is_in_cache) + stored_builtins = [] + def rescue_builtins(space): + w_dict = space.builtin.getdict() + content = {} + for key, cell in w_dict.implementation.content.iteritems(): + newcell = ModuleCell() + newcell.w_value = cell.w_value + content[key] = newcell + stored_builtins.append(content) + rescue_builtins = gateway.interp2app(rescue_builtins) + cls.w_rescue_builtins = cls.space.wrap(rescue_builtins) + def restore_builtins(space): + w_dict = space.builtin.getdict() + if not isinstance(w_dict.implementation, ModuleDictImplementation): + w_dict.implementation = ModuleDictImplementation(space) + w_dict.implementation.content = stored_builtins.pop() + restore_builtins = gateway.interp2app(restore_builtins) + cls.w_restore_builtins = cls.space.wrap(restore_builtins) + + def test_same_code_in_different_modules(self): + import sys + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + mod2 = type(sys)("abc") + self.impl_used(mod2.__dict__) + glob2 = mod2.__dict__ + def f(): + return x + 1 + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = 1 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + mod1.x = 2 + assert f1() == 3 + assert self.is_in_cache(code, glob1, "x") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "x") + f2 = type(f)(code, glob2) + mod2.x = 5 + assert not self.is_in_cache(code, glob2, "x") + assert f2() == 6 + assert self.is_in_cache(code, glob2, "x") + assert f2() == 6 + assert self.is_in_cache(code, glob2, "x") + mod2.x = 7 + assert f2() == 8 + assert self.is_in_cache(code, glob2, "x") + assert f2() == 8 + assert self.is_in_cache(code, glob2, "x") + + def test_override_builtins(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + return len(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 0 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + assert f1() == 0 + mod1.x.append(1) + assert f1() == 1 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + mod1.len = lambda x: 15 + assert not self.is_in_cache(code, glob1, "len") + mod1.x.append(1) + assert f1() == 15 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 15 + assert self.is_in_cache(code, glob1, "len") + del mod1.len + mod1.x.append(1) + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "len") + orig_len = __builtins__.len + try: + __builtins__.len = lambda x: 12 + mod1.x.append(1) + assert self.is_in_cache(code, glob1, "len") + assert f1() == 12 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 12 + assert self.is_in_cache(code, glob1, "len") + finally: + __builtins__.len = orig_len + + def test_override_builtins2(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + return l(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + __builtin__.l = len + try: + assert not self.is_in_cache(code, glob1, "l") + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 0 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + assert f1() == 0 + mod1.x.append(1) + assert f1() == 1 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + del __builtin__.l + mod1.l = len + mod1.x.append(1) + assert not self.is_in_cache(code, glob1, "l") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + finally: + if hasattr(__builtins__, "l"): + del __builtins__.l + + def test_generator(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + yield 1 + yield x + yield len(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + gen = f1() + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v == 1 + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v is mod1.x + assert not self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v == 0 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + + def test_degenerate_to_rdict(self): + import sys + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + def f(): + return x + 1 + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = 1 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + glob1[1] = 2 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert not self.is_in_cache(code, glob1, "x") + + def test_degenerate_builtin_to_rdict(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + def f(): + return len(x) + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = [1, 2] + assert not self.is_in_cache(code, glob1, "x") + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + assert self.is_in_cache(code, glob1, "len") + self.rescue_builtins() + try: + __builtin__.__dict__[1] = 2 + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 2 + assert not self.is_in_cache(code, glob1, "len") + finally: + self.restore_builtins() + + def test_mapping_as_locals(self): + import sys + if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'): + skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements") + class M(object): + def __getitem__(self, key): + return key + def __setitem__(self, key, value): + self.result[key] = value + m = M() + m.result = {} + exec "x=m" in {}, m + assert m.result == {'x': 'm'} + exec "y=n" in m # NOTE: this doesn't work in CPython 2.4 + assert m.result == {'x': 'm', 'y': 'n'} + + def test_subclass_of_dict_as_locals(self): + import sys + if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'): + skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements") + class M(dict): + def __getitem__(self, key): + return key + def __setitem__(self, key, value): + dict.__setitem__(self, key, value) + m = M() + exec "x=m" in {}, m + assert m == {'x': 'm'} + exec "y=n" in m # NOTE: this doesn't work in CPython 2.4 + assert m == {'x': 'm', 'y': 'n'} + Modified: pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py Fri May 22 18:53:13 2009 @@ -3,6 +3,8 @@ W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \ EmptyDictImplementation, RDictImplementation, StrDictImplementation, \ SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation + +from pypy.objspace.std.celldict import ModuleDictImplementation from pypy.conftest import gettestobjspace from pypy.objspace.std.test import test_dictobject @@ -58,6 +60,26 @@ a.__dict__.items() == [("abc", 12)] +class AppTestModuleDict(object): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withcelldict": True}) + cls.w_impl_used = cls.space.appexec([], """(): + import __pypy__ + def impl_used(obj): + assert "ModuleDictImplementation" in __pypy__.internal_repr(obj) + return impl_used + """) + + + def test_check_module_uses_module_dict(self): + m = type(__builtins__)("abc") + self.impl_used(m.__dict__) + + def test_key_not_there(self): + d = type(__builtins__)("abc").__dict__ + raises(KeyError, "d['def']") + + class TestW_DictSmall(test_dictobject.TestW_DictObject): def setup_class(cls): @@ -233,3 +255,15 @@ def get_impl(self): return self.ImplementionClass(self.space, self.string, self.string2) + +class TestModuleDictImplementation(TestRDictImplementation): + ImplementionClass = ModuleDictImplementation + EmptyClass = ModuleDictImplementation + +class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation): + ImplementionClass = ModuleDictImplementation + EmptyClass = ModuleDictImplementation + + string = "int" + string2 = "isinstance" + Modified: pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py Fri May 22 18:53:13 2009 @@ -489,6 +489,7 @@ FakeSpace.config.objspace.std.withdictmeasurement = False FakeSpace.config.objspace.std.withsharingdict = False FakeSpace.config.objspace.std.withsmalldicts = False +FakeSpace.config.objspace.std.withcelldict = False FakeSpace.config.objspace.opcodes = Config() FakeSpace.config.objspace.opcodes.CALL_LIKELY_BUILTIN = False Modified: pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py ============================================================================== --- pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py (original) +++ pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py Fri May 22 18:53:13 2009 @@ -201,3 +201,15 @@ y = y + 1 c += 1 +def test_count_with_True(): + x = 0 + n = N + while x < n: + x = x + True + +increment = 1 +def test_count_with_global_increment(): + x = 0 + n = N + while x < n: + x = x + increment From fijal at codespeak.net Fri May 22 21:18:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 22 May 2009 21:18:48 +0200 (CEST) Subject: [pypy-svn] r65361 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/doc Message-ID: <20090522191848.58F19169FEC@codespeak.net> Author: fijal Date: Fri May 22 21:18:45 2009 New Revision: 65361 Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/doc/simple_virtualizables.txt (contents, props changed) Log: start a document explaining simplified approach to virtualizables Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/doc/simple_virtualizables.txt ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/doc/simple_virtualizables.txt Fri May 22 21:18:45 2009 @@ -0,0 +1,24 @@ +Simplified virtualizables +========================= + +As a first step for speeding up code, we plan to implement simplified version +of virtualizables. Simplified in a sense that it won't support virtuals stored +on virtualizables. + +For those unaware: + +* Virtuals are objects which are known not to escape from jit code, hence + they're not allocated at all and their fields are stored in registers and or + on the stack. + +* Virtualizables are objects that are known to escape (for example the frame + object), but they're stored anyway on the stack with a way to access and + modify from outside the jit code. So the jit knows where they're and have + a way to reconstruct them if necessary. + +The way to implement virtualizables would be as follows: + +* During translation, all field accesses to virtualizables are replace by + calls to helpers that read/write fields via the jit. + +XXX From antocuni at codespeak.net Sat May 23 15:10:30 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 15:10:30 +0200 (CEST) Subject: [pypy-svn] r65362 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090523131030.C2139169F4D@codespeak.net> Author: antocuni Date: Sat May 23 15:10:28 2009 New Revision: 65362 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: port tests to ootype Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Sat May 23 15:10:28 2009 @@ -1,95 +1,122 @@ - import py from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.history import ConstAddr, BoxPtr, TreeLoop,\ - ConstInt, BoxInt + ConstInt, BoxInt, BoxObj, ConstObj from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.optimize2 import optimize_loop from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY -node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) -node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) -cpu = runner.LLtypeCPU(None) -vtable_box = ConstAddr(node_vtable_adr, cpu) - -NODE = lltype.GcForwardReference() -NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT), - ('value', lltype.Signed), - ('next', lltype.Ptr(NODE)))) -node = lltype.malloc(NODE) -nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) -nodedescr = cpu.fielddescrof(NODE, 'value') - -def newloop(inputargs, operations): - loop = TreeLoop("test") - loop.inputargs = inputargs - loop.operations = operations - return loop - -def test_remove_guard_class(): - ops = [ - ResOperation(rop.GUARD_CLASS, [nodebox, vtable_box], None), - ResOperation(rop.GUARD_CLASS, [nodebox, vtable_box], None), - ] - ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] - ops[1].suboperations = [ResOperation(rop.FAIL, [], None)] - loop = newloop([nodebox], ops) - optimize_loop(None, [], loop) - assert len(loop.operations) == 1 - -def test_remove_consecutive_guard_value_constfold(): - n = BoxInt(0) - n1 = BoxInt(1) - n2 = BoxInt(3) - ops = [ - ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), - ResOperation(rop.INT_ADD, [n, ConstInt(1)], n1), - ResOperation(rop.GUARD_VALUE, [n1, ConstInt(1)], None), - ResOperation(rop.INT_ADD, [n1, ConstInt(2)], n2), - ] - ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] - ops[2].suboperations = [ResOperation(rop.FAIL, [], None)] - loop = newloop([n], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), - ]) - -def test_remove_consecutive_getfields(): - n1 = BoxInt() - n2 = BoxInt() - n3 = BoxInt() - ops = [ - ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), - ResOperation(rop.GETFIELD_GC, [nodebox], n2, nodedescr), - ResOperation(rop.INT_ADD, [n1, n2], n3), - ] - loop = newloop([nodebox], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), - ResOperation(rop.INT_ADD, [n1, n1], n3), - ]) - -def test_setfield_getfield_clean_cache(): - n1 = BoxInt() - n2 = BoxInt() - n3 = BoxInt() - ops = [ - ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), - ResOperation(rop.SETFIELD_GC, [nodebox, ConstInt(3)], None, nodedescr), - ResOperation(rop.GETFIELD_GC, [nodebox], n2, nodedescr), - ResOperation(rop.CALL, [n2], None), - ] - loop = newloop([nodebox], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GETFIELD_GC, [nodebox], n1, nodedescr), - ResOperation(rop.SETFIELD_GC, [nodebox, ConstInt(3)], None, nodedescr), - ResOperation(rop.CALL, [ConstInt(3)], None), - ]) +class LLtypeMixin(object): + + node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) + node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) + cpu = runner.LLtypeCPU(None) + vtable_box = ConstAddr(node_vtable_adr, cpu) + + NODE = lltype.GcForwardReference() + NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT), + ('value', lltype.Signed), + ('next', lltype.Ptr(NODE)))) + node = lltype.malloc(NODE) + nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) + nodedescr = cpu.fielddescrof(NODE, 'value') + +class OOtypeMixin(object): + cpu = runner.OOtypeCPU(None) + + NODE = ootype.Instance('NODE', ootype.ROOT, {}) + NODE._add_fields({'value': ootype.Signed, + 'next': NODE}) + + node_vtable = ootype.runtimeClass(NODE) + vtable_box = ConstObj(ootype.cast_to_object(node_vtable)) + + node = ootype.new(NODE) + nodebox = BoxObj(ootype.cast_to_object(node)) + nodedescr = cpu.fielddescrof(NODE, 'value') + + + +class BaseTestOptimize2(object): + + @staticmethod + def newloop(inputargs, operations): + loop = TreeLoop("test") + loop.inputargs = inputargs + loop.operations = operations + return loop + + def test_remove_guard_class(self): + ops = [ + ResOperation(rop.GUARD_CLASS, [self.nodebox, self.vtable_box], None), + ResOperation(rop.GUARD_CLASS, [self.nodebox, self.vtable_box], None), + ] + ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] + ops[1].suboperations = [ResOperation(rop.FAIL, [], None)] + loop = self.newloop([self.nodebox], ops) + optimize_loop(None, [], loop) + assert len(loop.operations) == 1 + + def test_remove_consecutive_guard_value_constfold(self): + n = BoxInt(0) + n1 = BoxInt(1) + n2 = BoxInt(3) + ops = [ + ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), + ResOperation(rop.INT_ADD, [n, ConstInt(1)], n1), + ResOperation(rop.GUARD_VALUE, [n1, ConstInt(1)], None), + ResOperation(rop.INT_ADD, [n1, ConstInt(2)], n2), + ] + ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] + ops[2].suboperations = [ResOperation(rop.FAIL, [], None)] + loop = self.newloop([n], ops) + optimize_loop(None, [], loop) + equaloplists(loop.operations, [ + ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), + ]) + + def test_remove_consecutive_getfields(self): + n1 = BoxInt() + n2 = BoxInt() + n3 = BoxInt() + ops = [ + ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), + ResOperation(rop.GETFIELD_GC, [self.nodebox], n2, self.nodedescr), + ResOperation(rop.INT_ADD, [n1, n2], n3), + ] + loop = self.newloop([self.nodebox], ops) + optimize_loop(None, [], loop) + equaloplists(loop.operations, [ + ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), + ResOperation(rop.INT_ADD, [n1, n1], n3), + ]) + + def test_setfield_getfield_clean_cache(self): + n1 = BoxInt() + n2 = BoxInt() + n3 = BoxInt() + ops = [ + ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), + ResOperation(rop.SETFIELD_GC, [self.nodebox, ConstInt(3)], None, self.nodedescr), + ResOperation(rop.GETFIELD_GC, [self.nodebox], n2, self.nodedescr), + ResOperation(rop.CALL, [n2], None), + ] + loop = self.newloop([self.nodebox], ops) + optimize_loop(None, [], loop) + equaloplists(loop.operations, [ + ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), + ResOperation(rop.SETFIELD_GC, [self.nodebox, ConstInt(3)], None, self.nodedescr), + ResOperation(rop.CALL, [ConstInt(3)], None), + ]) + + +class TestLLtype(LLtypeMixin, BaseTestOptimize2): + pass +class TestOOtype(OOtypeMixin, BaseTestOptimize2): + pass From antocuni at codespeak.net Sat May 23 17:49:30 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 17:49:30 +0200 (CEST) Subject: [pypy-svn] r65363 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090523154930.AA41C169E97@codespeak.net> Author: antocuni Date: Sat May 23 17:49:29 2009 New Revision: 65363 Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py - copied, changed from r65361, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py - copied, changed from r65362, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: yet another optimize*.py. The idea is that you can write a new class for each optimization, and methods of the class will be called for each corresponding operation. Copied: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (from r65361, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py) ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 17:49:29 2009 @@ -1,6 +1,3 @@ - -""" Simplified optimize.py -""" from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.jit.metainterp.history import Const, Box @@ -27,6 +24,9 @@ loop = None nodes = None + def __init__(self, optlist): + self.optlist = optlist + def getnode(self, box): try: return self.nodes[box] @@ -75,74 +75,16 @@ newboxes.append(box) return newboxes - def optimize_guard(self, op): - assert len(op.suboperations) == 1 - op_fail = op.suboperations[0] - op_fail.args = self.new_arguments(op_fail) - # modification in place. Reason for this is explained in mirror - # in optimize.py - op.suboperations = [op_fail] - def optimize_operations(self): newoperations = [] for op in self.loop.operations: - if op.is_guard(): - if op.opnum == rop.GUARD_NONVIRTUALIZED: - continue - elif op.opnum == rop.GUARD_CLASS: - node = self.getnode(op.args[0]) - if node.cls is not None: - # assert that they're equal maybe - continue - node.cls = InstanceNode(op.args[1], const=True) - elif op.opnum == rop.GUARD_VALUE: - instnode = self.nodes[op.args[0]] - assert isinstance(op.args[1], Const) - if instnode.const: - continue - self.optimize_guard(op) - instnode.const = True - instnode.source = op.args[0].constbox() - newoperations.append(op) - continue - self.optimize_guard(op) - newoperations.append(op) - continue - elif op.opnum == rop.GETFIELD_GC: - instnode = self.getnode(op.args[0]) - descr = op.descr - node = instnode.cleanfields.get(descr, None) - if node is not None: - self.nodes[op.result] = node - continue - else: - instnode.cleanfields[descr] = self.getnode(op.result) - elif op.opnum == rop.SETFIELD_GC: - instnode = self.getnode(op.args[0]) - descr = op.descr - node = self.getnode(op.args[1]) - instnode.dirtyfields[descr] = node - instnode.cleanfields[descr] = node - l = self.field_caches.setdefault(descr, []) - l.append((instnode, node)) - continue - # default handler - op = op.clone() - op.args = self.new_arguments(op) - if op.is_always_pure(): - for box in op.args: - if isinstance(box, Box): - break - else: - # all constant arguments: constant-fold away - box = op.result - assert box is not None - instnode = InstanceNode(box.constbox(), const=True) - self.nodes[box] = instnode - continue - elif not op.has_no_side_effect(): - self.clean_up_caches(newoperations) - newoperations.append(op) + newop = op + for optimization in self.optlist: + newop = optimization.handle_op(self, newop) + if newop is None: + break + if newop is not None: + newoperations.append(newop) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations @@ -161,7 +103,77 @@ self.find_nodes() self.optimize_operations() -specializer = Specializer() +# ------------------------------------------------------------------- + +class AbstractOptimization(object): + + def __init__(self): + 'NOT_RPYTHON' + operations = [None] * (rop._LAST+1) + for key, value in rop.__dict__.items(): + if key.startswith('_'): + continue + methname = key.lower() + if hasattr(self, methname): + func = getattr(self, methname).im_func + else: + func = getattr(self, 'handle_default_op').im_func + operations[value] = func + self.operations = operations + + def handle_op(self, spec, op): + func = self.operations[op.opnum] + return func(self, spec, op) + + def handle_default_op(self, spec, op): + return op + + +class OptimizeGuards(AbstractOptimization): + + def optimize_guard(self, spec, op): + assert len(op.suboperations) == 1 + op_fail = op.suboperations[0] + op_fail.args = spec.new_arguments(op_fail) + # modification in place. Reason for this is explained in mirror + # in optimize.py + op.suboperations = [op_fail] + return op + + def guard_class(self, spec, op): + node = spec.getnode(op.args[0]) + if node.cls is not None: + # assert that they're equal maybe + return + node.cls = InstanceNode(op.args[1], const=True) + return self.optimize_guard(spec, op) + +## def guard_value(self, spec, op): +## instnode = spec.nodes[op.args[0]] +## assert isinstance(op.args[1], Const) +## if instnode.const: +## return +## self.optimize_guard(spec, op) +## instnode.const = True +## instnode.source = op.args[0].constbox() +## return op + +## def guard_nonvirtualized(self, spec, op): +## return + +## def handle_default_op(self, spec, op): +## if op.is_guard(): +## return self.optimize_guard(op) +## return op + + + +# ------------------------------------------------------------------- + +OPTLIST = [ + OptimizeGuards(), + ] +specializer = Specializer(OPTLIST) def optimize_loop(options, old_loops, loop, cpu=None): if old_loops: Copied: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py (from r65362, pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py) ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Sat May 23 17:49:29 2009 @@ -8,9 +8,31 @@ ConstInt, BoxInt, BoxObj, ConstObj from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp.optimize2 import optimize_loop +from pypy.jit.metainterp.optimize3 import AbstractOptimization +from pypy.jit.metainterp.optimize3 import optimize_loop from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY +def test_AbstractOptimization(): + + class MyOpt(AbstractOptimization): + def int_add(self, spec, op): + return 'hello world', op + + class MyOpt2(MyOpt): + def handle_default_op(self, spec, op): + return 'default op', op + + myopt = MyOpt() + myopt2 = MyOpt2() + op = ResOperation(rop.INT_ADD, [], None) + assert myopt.handle_op(None, op) == ('hello world', op) + assert myopt2.handle_op(None, op) == ('hello world', op) + + op = ResOperation(rop.INT_SUB, [], None) + assert myopt.handle_op(None, op) == op + assert myopt2.handle_op(None, op) == ('default op', op) + + class LLtypeMixin(object): node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) @@ -42,7 +64,7 @@ -class BaseTestOptimize2(object): +class BaseTestOptimize3(object): @staticmethod def newloop(inputargs, operations): @@ -51,6 +73,7 @@ loop.operations = operations return loop + def test_remove_guard_class(self): ops = [ ResOperation(rop.GUARD_CLASS, [self.nodebox, self.vtable_box], None), @@ -63,6 +86,7 @@ assert len(loop.operations) == 1 def test_remove_consecutive_guard_value_constfold(self): + py.test.skip('in-progress') n = BoxInt(0) n1 = BoxInt(1) n2 = BoxInt(3) @@ -81,6 +105,7 @@ ]) def test_remove_consecutive_getfields(self): + py.test.skip('in-progress') n1 = BoxInt() n2 = BoxInt() n3 = BoxInt() @@ -97,6 +122,7 @@ ]) def test_setfield_getfield_clean_cache(self): + py.test.skip('in-progress') n1 = BoxInt() n2 = BoxInt() n3 = BoxInt() @@ -115,8 +141,8 @@ ]) -class TestLLtype(LLtypeMixin, BaseTestOptimize2): +class TestLLtype(LLtypeMixin, BaseTestOptimize3): pass -class TestOOtype(OOtypeMixin, BaseTestOptimize2): +class TestOOtype(OOtypeMixin, BaseTestOptimize3): pass From antocuni at codespeak.net Sat May 23 18:05:45 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 18:05:45 +0200 (CEST) Subject: [pypy-svn] r65364 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090523160545.D58E3169EAB@codespeak.net> Author: antocuni Date: Sat May 23 18:05:43 2009 New Revision: 65364 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Log: implement constant folding, and add a test for it Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 18:05:43 2009 @@ -129,6 +129,29 @@ return op +class ConstFold(AbstractOptimization): + + def handle_default_op(self, spec, op): + op = op.clone() + op.args = spec.new_arguments(op) + if op.is_always_pure(): + for box in op.args: + if isinstance(box, Box): + break + else: + # all constant arguments: constant-fold away + box = op.result + assert box is not None + instnode = InstanceNode(box.constbox(), const=True) + spec.nodes[box] = instnode + return + elif not op.has_no_side_effect(): + # XXX + pass + #spec.clean_up_caches(newoperations) + return op + + class OptimizeGuards(AbstractOptimization): def optimize_guard(self, spec, op): @@ -172,6 +195,7 @@ OPTLIST = [ OptimizeGuards(), + ConstFold(), ] specializer = Specializer(OPTLIST) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Sat May 23 18:05:43 2009 @@ -73,6 +73,13 @@ loop.operations = operations return loop + def test_constfold(self): + ops = [ + ResOperation(rop.INT_ADD, [ConstInt(10), ConstInt(20)], ConstInt(30)), + ] + loop = self.newloop([], ops) + optimize_loop(None, [], loop) + assert len(loop.operations) == 0 def test_remove_guard_class(self): ops = [ From antocuni at codespeak.net Sat May 23 18:33:23 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 18:33:23 +0200 (CEST) Subject: [pypy-svn] r65365 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090523163323.A837A168464@codespeak.net> Author: antocuni Date: Sat May 23 18:33:23 2009 New Revision: 65365 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Log: (antocuni, after discussion with fijal): move op.clone/spec.new_arguments to the main optimization loop, as it is something which needs to be done in general, not only for constant folding. Tests still pass Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 18:33:23 2009 @@ -83,6 +83,8 @@ newop = optimization.handle_op(self, newop) if newop is None: break + newop = newop.clone() + newop.args = self.new_arguments(op) if newop is not None: newoperations.append(newop) print "Length of the loop:", len(newoperations) @@ -132,8 +134,6 @@ class ConstFold(AbstractOptimization): def handle_default_op(self, spec, op): - op = op.clone() - op.args = spec.new_arguments(op) if op.is_always_pure(): for box in op.args: if isinstance(box, Box): From fijal at codespeak.net Sat May 23 18:37:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 23 May 2009 18:37:21 +0200 (CEST) Subject: [pypy-svn] r65366 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090523163721.8B7EE16850F@codespeak.net> Author: fijal Date: Sat May 23 18:37:20 2009 New Revision: 65366 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Log: I think this is what you meant Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 18:37:20 2009 @@ -83,9 +83,9 @@ newop = optimization.handle_op(self, newop) if newop is None: break + if newop is not None: newop = newop.clone() newop.args = self.new_arguments(op) - if newop is not None: newoperations.append(newop) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations From antocuni at codespeak.net Sat May 23 19:09:46 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 19:09:46 +0200 (CEST) Subject: [pypy-svn] r65367 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090523170946.71AE3169EFD@codespeak.net> Author: antocuni Date: Sat May 23 19:09:44 2009 New Revision: 65367 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Log: move new_arguments back to ConstFold, which has been renamed. The specializer relies on it to be the last item of the list to work correctly. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 19:09:44 2009 @@ -25,6 +25,9 @@ nodes = None def __init__(self, optlist): + for opt in optlist: + assert not isinstance(opt, CloneAndConstFold), 'automatically added' + optlist.append(CloneAndConstFold()) self.optlist = optlist def getnode(self, box): @@ -84,8 +87,6 @@ if newop is None: break if newop is not None: - newop = newop.clone() - newop.args = self.new_arguments(op) newoperations.append(newop) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations @@ -131,9 +132,16 @@ return op -class ConstFold(AbstractOptimization): +class CloneAndConstFold(AbstractOptimization): + """ + Automatically inserted as the last optimization of the list. + """ def handle_default_op(self, spec, op): + if op.is_guard(): + return op # TODO + op = op.clone() + op.args = spec.new_arguments(op) if op.is_always_pure(): for box in op.args: if isinstance(box, Box): @@ -145,10 +153,6 @@ instnode = InstanceNode(box.constbox(), const=True) spec.nodes[box] = instnode return - elif not op.has_no_side_effect(): - # XXX - pass - #spec.clean_up_caches(newoperations) return op @@ -195,7 +199,6 @@ OPTLIST = [ OptimizeGuards(), - ConstFold(), ] specializer = Specializer(OPTLIST) From antocuni at codespeak.net Sat May 23 19:10:29 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 19:10:29 +0200 (CEST) Subject: [pypy-svn] r65368 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090523171029.21CD6169EFC@codespeak.net> Author: antocuni Date: Sat May 23 19:10:29 2009 New Revision: 65368 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Log: implement guard_value, test passes Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 19:10:29 2009 @@ -175,15 +175,15 @@ node.cls = InstanceNode(op.args[1], const=True) return self.optimize_guard(spec, op) -## def guard_value(self, spec, op): -## instnode = spec.nodes[op.args[0]] -## assert isinstance(op.args[1], Const) -## if instnode.const: -## return -## self.optimize_guard(spec, op) -## instnode.const = True -## instnode.source = op.args[0].constbox() -## return op + def guard_value(self, spec, op): + instnode = spec.nodes[op.args[0]] + assert isinstance(op.args[1], Const) + if instnode.const: + return + self.optimize_guard(spec, op) + instnode.const = True + instnode.source = op.args[0].constbox() + return op ## def guard_nonvirtualized(self, spec, op): ## return Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Sat May 23 19:10:29 2009 @@ -93,7 +93,6 @@ assert len(loop.operations) == 1 def test_remove_consecutive_guard_value_constfold(self): - py.test.skip('in-progress') n = BoxInt(0) n1 = BoxInt(1) n2 = BoxInt(3) From antocuni at codespeak.net Sat May 23 19:11:38 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 May 2009 19:11:38 +0200 (CEST) Subject: [pypy-svn] r65369 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090523171138.719E4169EFC@codespeak.net> Author: antocuni Date: Sat May 23 19:11:37 2009 New Revision: 65369 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Log: remove all references to the getfield optimizations, as fijal says it's broken Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize3.py Sat May 23 19:11:37 2009 @@ -8,8 +8,6 @@ assert isinstance(source, Const) self.const = const self.cls = None - self.cleanfields = {} - self.dirtyfields = {} def __repr__(self): flags = '' @@ -90,14 +88,6 @@ newoperations.append(newop) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations - - def clean_up_caches(self, newoperations): - for descr, v in self.field_caches.iteritems(): - for instnode, fieldnode in v: - newoperations.append(ResOperation(rop.SETFIELD_GC, - [instnode.source, fieldnode.source], None, descr)) - del instnode.cleanfields[descr] - del instnode.dirtyfields[descr] def optimize_loop(self, loop): self.nodes = {} Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize3.py Sat May 23 19:11:37 2009 @@ -110,42 +110,6 @@ ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), ]) - def test_remove_consecutive_getfields(self): - py.test.skip('in-progress') - n1 = BoxInt() - n2 = BoxInt() - n3 = BoxInt() - ops = [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.GETFIELD_GC, [self.nodebox], n2, self.nodedescr), - ResOperation(rop.INT_ADD, [n1, n2], n3), - ] - loop = self.newloop([self.nodebox], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.INT_ADD, [n1, n1], n3), - ]) - - def test_setfield_getfield_clean_cache(self): - py.test.skip('in-progress') - n1 = BoxInt() - n2 = BoxInt() - n3 = BoxInt() - ops = [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.SETFIELD_GC, [self.nodebox, ConstInt(3)], None, self.nodedescr), - ResOperation(rop.GETFIELD_GC, [self.nodebox], n2, self.nodedescr), - ResOperation(rop.CALL, [n2], None), - ] - loop = self.newloop([self.nodebox], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.SETFIELD_GC, [self.nodebox, ConstInt(3)], None, self.nodedescr), - ResOperation(rop.CALL, [ConstInt(3)], None), - ]) - class TestLLtype(LLtypeMixin, BaseTestOptimize3): pass From fijal at codespeak.net Sat May 23 19:22:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 23 May 2009 19:22:01 +0200 (CEST) Subject: [pypy-svn] r65370 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090523172201.26DBA168556@codespeak.net> Author: fijal Date: Sat May 23 19:22:00 2009 New Revision: 65370 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: kill all optimizations for now, will try to readd them in a modular manner Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Sat May 23 19:22:00 2009 @@ -87,45 +87,9 @@ newoperations = [] for op in self.loop.operations: if op.is_guard(): - if op.opnum == rop.GUARD_NONVIRTUALIZED: - continue - elif op.opnum == rop.GUARD_CLASS: - node = self.getnode(op.args[0]) - if node.cls is not None: - # assert that they're equal maybe - continue - node.cls = InstanceNode(op.args[1], const=True) - elif op.opnum == rop.GUARD_VALUE: - instnode = self.nodes[op.args[0]] - assert isinstance(op.args[1], Const) - if instnode.const: - continue - self.optimize_guard(op) - instnode.const = True - instnode.source = op.args[0].constbox() - newoperations.append(op) - continue self.optimize_guard(op) newoperations.append(op) continue - elif op.opnum == rop.GETFIELD_GC: - instnode = self.getnode(op.args[0]) - descr = op.descr - node = instnode.cleanfields.get(descr, None) - if node is not None: - self.nodes[op.result] = node - continue - else: - instnode.cleanfields[descr] = self.getnode(op.result) - elif op.opnum == rop.SETFIELD_GC: - instnode = self.getnode(op.args[0]) - descr = op.descr - node = self.getnode(op.args[1]) - instnode.dirtyfields[descr] = node - instnode.cleanfields[descr] = node - l = self.field_caches.setdefault(descr, []) - l.append((instnode, node)) - continue # default handler op = op.clone() op.args = self.new_arguments(op) @@ -140,19 +104,9 @@ instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue - elif not op.has_no_side_effect(): - self.clean_up_caches(newoperations) newoperations.append(op) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations - - def clean_up_caches(self, newoperations): - for descr, v in self.field_caches.iteritems(): - for instnode, fieldnode in v: - newoperations.append(ResOperation(rop.SETFIELD_GC, - [instnode.source, fieldnode.source], None, descr)) - del instnode.cleanfields[descr] - del instnode.dirtyfields[descr] def optimize_loop(self, loop): self.nodes = {} From benjamin at codespeak.net Sat May 23 20:11:39 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sat, 23 May 2009 20:11:39 +0200 (CEST) Subject: [pypy-svn] r65371 - in pypy/trunk/pypy/interpreter: astcompiler/test pyparser/test pyparser/test/samples stablecompiler Message-ID: <20090523181139.BDC4C169DFF@codespeak.net> Author: benjamin Date: Sat May 23 20:11:37 2009 New Revision: 65371 Added: pypy/trunk/pypy/interpreter/pyparser/test/support.py - copied, changed from r65367, pypy/trunk/pypy/interpreter/pyparser/test/fakes.py Removed: pypy/trunk/pypy/interpreter/pyparser/test/fakes.py pypy/trunk/pypy/interpreter/pyparser/test/samples/ pypy/trunk/pypy/interpreter/pyparser/test/test_astbuilder.py pypy/trunk/pypy/interpreter/pyparser/test/test_samples.py pypy/trunk/pypy/interpreter/stablecompiler/ Modified: pypy/trunk/pypy/interpreter/astcompiler/test/test_ast.py pypy/trunk/pypy/interpreter/astcompiler/test/test_compiler.py Log: remove stablecompiler and the tests that relied upon it Modified: pypy/trunk/pypy/interpreter/astcompiler/test/test_ast.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/test/test_ast.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/test/test_ast.py Sat May 23 20:11:37 2009 @@ -1,5 +1,5 @@ from pypy.interpreter.astcompiler import ast#_temp as ast -from pypy.interpreter.pyparser.test.test_astbuilder import source2ast +from pypy.interpreter.pyparser.test.support import source2ast class BaseVisitor(ast.ASTVisitor): def default(self, node): 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 Sat May 23 20:11:37 2009 @@ -1,6 +1,6 @@ import py from pypy.interpreter.astcompiler import misc, pycodegen, opt -from pypy.interpreter.pyparser.test.test_astbuilder import source2ast +from pypy.interpreter.pyparser.test.support import source2ast from pypy.interpreter.pyparser.test import expressions from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.error import SyntaxError, IndentationError Copied: pypy/trunk/pypy/interpreter/pyparser/test/support.py (from r65367, pypy/trunk/pypy/interpreter/pyparser/test/fakes.py) ============================================================================== --- pypy/trunk/pypy/interpreter/pyparser/test/fakes.py (original) +++ pypy/trunk/pypy/interpreter/pyparser/test/support.py Sat May 23 20:11:37 2009 @@ -1,3 +1,5 @@ +from pypy.interpreter.pyparser import pythonparse +from pypy.interpreter.pyparser.astbuilder import AstBuilder class FakeSpace: w_None = None @@ -40,3 +42,10 @@ def call_function(self, func, *args): return func(*args) + +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] + From benjamin at codespeak.net Sat May 23 23:10:08 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Sat, 23 May 2009 23:10:08 +0200 (CEST) Subject: [pypy-svn] r65372 - in pypy/trunk/pypy: module/posix module/posix/test rpython/module Message-ID: <20090523211008.0B663169EC5@codespeak.net> Author: benjamin Date: Sat May 23 23:10:06 2009 New Revision: 65372 Modified: pypy/trunk/pypy/module/posix/__init__.py pypy/trunk/pypy/module/posix/interp_posix.py pypy/trunk/pypy/module/posix/test/test_posix2.py pypy/trunk/pypy/rpython/module/ll_os.py Log: implement os.fsync() and os.fdatasync() Modified: pypy/trunk/pypy/module/posix/__init__.py ============================================================================== --- pypy/trunk/pypy/module/posix/__init__.py (original) +++ pypy/trunk/pypy/module/posix/__init__.py Sat May 23 23:10:06 2009 @@ -69,6 +69,10 @@ interpleveldefs['chown'] = 'interp_posix.chown' if hasattr(os, 'ftruncate'): interpleveldefs['ftruncate'] = 'interp_posix.ftruncate' + if hasattr(os, 'fsync'): + interpleveldefs['fsync'] = 'interp_posix.fsync' + if hasattr(os, 'fdatasync'): + interpleveldefs['fdatasync'] = 'interp_posix.fdatasync' if hasattr(os, 'putenv'): interpleveldefs['putenv'] = 'interp_posix.putenv' if hasattr(posix, 'unsetenv'): # note: emulated in os Modified: pypy/trunk/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/trunk/pypy/module/posix/interp_posix.py (original) +++ pypy/trunk/pypy/module/posix/interp_posix.py Sat May 23 23:10:06 2009 @@ -87,6 +87,20 @@ raise wrap_oserror(space, e) ftruncate.unwrap_spec = [ObjSpace, int, r_longlong] +def fsync(space, fd): + try: + os.fsync(fd) + except OSError, e: + raise wrap_oserror(space, e) +fsync.unwrap_spec = [ObjSpace, int] + +def fdatasync(space, fd): + try: + os.fdatasync(fd) + except OSError, e: + raise wrap_oserror(space, e) +fdatasync.unwrap_spec = [ObjSpace, int] + # ____________________________________________________________ # For LL backends, expose all fields. 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 Sat May 23 23:10:06 2009 @@ -365,6 +365,38 @@ os = self.posix raises(ValueError, os.sysconf, "!@#$%!#$!@#") + if hasattr(os, 'fsync'): + def test_fsync(self): + os = self.posix + f = open(self.path2, "w") + try: + fd = f.fileno() + os.fsync(fd) + finally: + f.close() + try: + os.fsync(fd) + except OSError: + pass + else: + raise AssertionError("os.fsync didn't raise") + + if hasattr(os, 'fdatasync'): + def test_fdatasync(self): + os = self.posix + f = open(self.path2) + try: + fd = f.fileno() + os.fdatasync(fd) + finally: + f.close() + try: + os.fdatasync(fd) + except OSError: + pass + else: + raise AssertionError("os.fdatasync didn't raise") + def test_largefile(self): os = self.posix fd = os.open(self.path2 + 'test_largefile', os.O_RDWR | os.O_CREAT, 0666) 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 Sat May 23 23:10:06 2009 @@ -830,6 +830,30 @@ llimpl = ftruncate_llimpl, export_name = "ll_os.ll_os_ftruncate") + @registering_if(os, 'fsync') + def register_os_fsync(self): + os_fsync = self.llexternal('fsync', [rffi.INT], rffi.INT) + + def fsync_llimpl(fd): + res = rffi.cast(rffi.LONG, os_fsync(rffi.cast(rffi.INT, fd))) + if res < 0: + raise OSError(rposix.get_errno(), "fsync failed") + return extdef([int], s_None, + llimpl=fsync_llimpl, + export_name="ll_os.ll_os_fsync") + + @registering_if(os, 'fdatasync') + def register_os_fdatasync(self): + os_fdatasync = self.llexternal('fdatasync', [rffi.INT], rffi.INT) + + def fdatasync_llimpl(fd): + res = rffi.cast(rffi.LONG, os_fdatasync(rffi.cast(rffi.INT, fd))) + if res < 0: + raise OSError(rposix.get_errno(), "fdatasync failed") + return extdef([int], s_None, + llimpl=fdatasync_llimpl, + export_name="ll_os.ll_os_fdatasync") + @registering(os.access) def register_os_access(self): os_access = self.llexternal(underscore_on_windows + 'access', From fijal at codespeak.net Sat May 23 23:33:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 23 May 2009 23:33:19 +0200 (CEST) Subject: [pypy-svn] r65373 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090523213319.34282168556@codespeak.net> Author: fijal Date: Sat May 23 23:33:18 2009 New Revision: 65373 Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (contents, props changed) pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (contents, props changed) Log: A start of framework for a reasonable writing of tests Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Sat May 23 23:33:18 2009 @@ -0,0 +1,110 @@ + +""" Simplify optimize tests by allowing to write them +in a nicer fashion +""" + +from pypy.jit.metainterp.history import TreeLoop, BoxInt, BoxPtr, ConstInt +from pypy.jit.metainterp.resoperation import rop, ResOperation + +class ParseError(Exception): + pass + +class OpParser(object): + def __init__(self, descr): + self.descr = descr + self.vars = {} + + def box_for_var(self, elem): + if elem.startswith('i'): + # integer + box = BoxInt() + elif elem.startswith('p'): + # pointer + box = BoxPtr() + else: + raise ParseError("Unknown variable type: %s" % elem) + return box + + def parse_header_line(self, line): + elements = line.split(",") + vars = [] + for elem in elements: + elem = elem.strip() + box = self.box_for_var(elem) + vars.append(box) + self.vars[elem] = box + return vars + + def getvar(self, arg): + try: + return ConstInt(int(arg)) + except ValueError: + return self.vars[arg] + + def parse_op(self, line): + num = line.find('(') + if num == -1: + raise ParseError("invalid line: %s" % line) + opname = line[:num] + try: + opnum = getattr(rop, opname.upper()) + except AttributeError: + raise ParseError("unknown op: %s" % opname) + endnum = line.find(')') + if endnum == -1: + raise ParseError("invalid line: %s" % line) + argspec = line[num + 1:endnum] + if not argspec.strip(): + return opnum, [], None + allargs = argspec.split(",") + args = [] + for arg in allargs: + arg = arg.strip() + try: + args.append(self.getvar(arg)) + except KeyError: + raise ParseError("Unknown var: %s" % arg) + return opnum, args, None + + def parse_result_op(self, line): + res, op = line.split("=") + res = res.strip() + op = op.strip() + opnum, args, descr = self.parse_op(op) + if res in self.vars: + raise ParseError("Double assign to var %s in line: %s" % (res, line)) + rvar = self.box_for_var(res) + self.vars[res] = rvar + return ResOperation(opnum, args, rvar, descr) + + def parse_op_no_result(self, line): + opnum, args, descr = self.parse_op(line) + return ResOperation(opnum, args, None, descr) + + def parse_next_op(self, line): + if "=" in line: + return self.parse_result_op(line) + else: + return self.parse_op_no_result(line) + + def parse(self): + lines = self.descr.split("\n") + inpargs = None + ops = [] + for line in lines: + line = line.strip() + if not line or line.startswith("#"): + continue # a comment + if inpargs is None: + if not line.startswith('[') or not line.endswith(']'): + raise ParseError("Wrong header: %s" % line) + inpargs = self.parse_header_line(line[1:-1]) + else: + ops.append(self.parse_next_op(line)) + loop = TreeLoop("loop") + loop.operations = ops + loop.inputargs = inpargs + return loop + +def parse(descr): + return OpParser(descr).parse() Added: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Sat May 23 23:33:18 2009 @@ -0,0 +1,17 @@ + +from pypy.jit.metainterp.test.oparser import parse +from pypy.jit.metainterp.resoperation import rop + +def test_basic_parse(): + x = """ + [i0, i1] + i2 = int_add(i0, i1) + # a comment + i3 = int_sub(i2, 3) + fail() + """ + loop = parse(x) + assert len(loop.operations) == 3 + assert [op.opnum for op in loop.operations] == [rop.INT_ADD, rop.INT_SUB, + rop.FAIL] + assert len(loop.inputargs) == 2 From fijal at codespeak.net Sun May 24 02:41:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 02:41:36 +0200 (CEST) Subject: [pypy-svn] r65374 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524004136.34439169E97@codespeak.net> Author: fijal Date: Sun May 24 02:41:34 2009 New Revision: 65374 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Log: Progress on a parser Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Sun May 24 02:41:34 2009 @@ -3,16 +3,20 @@ in a nicer fashion """ -from pypy.jit.metainterp.history import TreeLoop, BoxInt, BoxPtr, ConstInt +from pypy.jit.metainterp.history import TreeLoop, BoxInt, BoxPtr, ConstInt,\ + ConstAddr from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.rpython.lltypesystem import lltype, llmemory class ParseError(Exception): pass class OpParser(object): - def __init__(self, descr): + def __init__(self, descr, cpu, namespace): self.descr = descr self.vars = {} + self.cpu = cpu + self.consts = namespace def box_for_var(self, elem): if elem.startswith('i'): @@ -39,6 +43,10 @@ try: return ConstInt(int(arg)) except ValueError: + if arg.startswith('ConstAddr('): + name = arg[len('ConstAddr('):-1] + return ConstAddr(llmemory.cast_ptr_to_adr(self.consts[name]), + self.cpu) return self.vars[arg] def parse_op(self, line): @@ -50,7 +58,7 @@ opnum = getattr(rop, opname.upper()) except AttributeError: raise ParseError("unknown op: %s" % opname) - endnum = line.find(')') + endnum = line.rfind(')') if endnum == -1: raise ParseError("invalid line: %s" % line) argspec = line[num + 1:endnum] @@ -89,22 +97,47 @@ def parse(self): lines = self.descr.split("\n") - inpargs = None ops = [] + newlines = [] for line in lines: - line = line.strip() - if not line or line.startswith("#"): + if not line.strip() or line.strip().startswith("#"): continue # a comment - if inpargs is None: - if not line.startswith('[') or not line.endswith(']'): - raise ParseError("Wrong header: %s" % line) - inpargs = self.parse_header_line(line[1:-1]) - else: - ops.append(self.parse_next_op(line)) + newlines.append(line) + base_indent, inpargs = self.parse_inpargs(newlines[0]) + newlines = newlines[1:] + num, ops = self.parse_ops(base_indent, newlines, 0) + if num < len(newlines): + raise ParseError("unexpected dedent at line: %s" % newlines[num]) loop = TreeLoop("loop") loop.operations = ops loop.inputargs = inpargs return loop -def parse(descr): - return OpParser(descr).parse() + def parse_ops(self, indent, lines, start): + num = start + ops = [] + while num < len(lines): + line = lines[num] + if not line.startswith(" " * indent): + # dedent + return num, ops + elif line.startswith(" "*(indent + 1)): + # suboperations + new_indent = len(line) - len(line.lstrip()) + num, suboperations = self.parse_ops(new_indent, lines, num) + ops[-1].suboperations = suboperations + else: + ops.append(self.parse_next_op(lines[num].strip())) + num += 1 + return num, ops + + def parse_inpargs(self, line): + base_indent = line.find('[') + line = line.strip() + if base_indent == -1 or not line.endswith(']'): + raise ParseError("Wrong header: %s" % line) + inpargs = self.parse_header_line(line[1:-1]) + return base_indent, inpargs + +def parse(descr, cpu=None, namespace={}): + return OpParser(descr, cpu, namespace).parse() Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Sun May 24 02:41:34 2009 @@ -1,4 +1,6 @@ +from pypy.rpython.lltypesystem import lltype + from pypy.jit.metainterp.test.oparser import parse from pypy.jit.metainterp.resoperation import rop @@ -15,3 +17,16 @@ assert [op.opnum for op in loop.operations] == [rop.INT_ADD, rop.INT_SUB, rop.FAIL] assert len(loop.inputargs) == 2 + +def test_const_ptr_subops(): + x = """ + [p0] + guard_class(p0, ConstAddr(vtable)) + fail() + """ + S = lltype.Struct('S') + vtable = lltype.nullptr(S) + loop = parse(x, None, locals()) + assert len(loop.operations) == 1 + assert len(loop.operations[0].suboperations) == 1 + From fijal at codespeak.net Sun May 24 02:50:32 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 02:50:32 +0200 (CEST) Subject: [pypy-svn] r65375 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090524005032.99CFF169E97@codespeak.net> Author: fijal Date: Sun May 24 02:50:32 2009 New Revision: 65375 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: Start using new framework for basic optimizations. Right now only constant folding Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Sun May 24 02:50:32 2009 @@ -1,7 +1,7 @@ """ Simplified optimize.py """ -from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.metainterp.resoperation import rop, ResOperation, opname from pypy.jit.metainterp.history import Const, Box class InstanceNode(object): @@ -27,6 +27,15 @@ loop = None nodes = None + def __init__(self, opts): + # NOT_RPYTHON + self.optimizations = [[] for i in range(rop._LAST)] + for opt in opts: + for name, opnum in opname.iteritems(): + meth = getattr(opt, 'optimize_' + name, None) + if meth is not None: + self.optimizations[opnum].append(meth) + def getnode(self, box): try: return self.nodes[box] @@ -86,6 +95,9 @@ def optimize_operations(self): newoperations = [] for op in self.loop.operations: + for opt in self.optimizations[op.opnum]: + if opt(op, self) is None: + continue if op.is_guard(): self.optimize_guard(op) newoperations.append(op) @@ -115,18 +127,18 @@ self.find_nodes() self.optimize_operations() -specializer = Specializer() +specializer = Specializer([]) -def optimize_loop(options, old_loops, loop, cpu=None): +def optimize_loop(options, old_loops, loop, cpu=None, spec=specializer): if old_loops: assert len(old_loops) == 1 return old_loops[0] else: - specializer.optimize_loop(loop) + spec.optimize_loop(loop) return None -def optimize_bridge(options, old_loops, loop, cpu=None): - optimize_loop(options, [], loop, cpu) +def optimize_bridge(options, old_loops, loop, cpu=None, spec=specializer): + optimize_loop(options, [], loop, cpu, spec) return old_loops[0] class Optimizer: Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Sun May 24 02:50:32 2009 @@ -11,6 +11,8 @@ from pypy.jit.metainterp.optimize2 import optimize_loop from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY +from pypy.jit.metainterp.test.oparser import parse + class LLtypeMixin(object): node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) @@ -44,25 +46,41 @@ class BaseTestOptimize2(object): - @staticmethod - def newloop(inputargs, operations): - loop = TreeLoop("test") - loop.inputargs = inputargs - loop.operations = operations - return loop + def optimize(self, lst): + loop = parse(lst, self.cpu, self.__dict__) + optimize_loop(None, [], loop) + return loop.operations + def assert_equal(self, optimized, expected): + equaloplists(optimized, + parse(expected, self.cpu, self.__dict__).operations) + + def test_basic_constant_folding(self): + pre_op = """ + [] + i1 = int_add(3, 2) + """ + expected = "[]" + self.assert_equal(self.optimize(pre_op), expected) + def test_remove_guard_class(self): - ops = [ - ResOperation(rop.GUARD_CLASS, [self.nodebox, self.vtable_box], None), - ResOperation(rop.GUARD_CLASS, [self.nodebox, self.vtable_box], None), - ] - ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] - ops[1].suboperations = [ResOperation(rop.FAIL, [], None)] - loop = self.newloop([self.nodebox], ops) - optimize_loop(None, [], loop) - assert len(loop.operations) == 1 + py.test.skip("not yet") + pre_op = """ + [p0] + guard_class(p0, Const(vtable)) + fail() + guard_class(p0, Const(vtable)) + fail() + """ + expected = """ + [p0] + guard_class(p0, Const(vtable)) + fail() + """ + self.equal(self.optimize(pre_op, []), expected) def test_remove_consecutive_guard_value_constfold(self): + py.test.skip("not yet") n = BoxInt(0) n1 = BoxInt(1) n2 = BoxInt(3) @@ -81,6 +99,7 @@ ]) def test_remove_consecutive_getfields(self): + py.test.skip("not yet") n1 = BoxInt() n2 = BoxInt() n3 = BoxInt() @@ -97,6 +116,7 @@ ]) def test_setfield_getfield_clean_cache(self): + py.test.skip("not yet") n1 = BoxInt() n2 = BoxInt() n3 = BoxInt() From fijal at codespeak.net Sun May 24 03:06:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 03:06:00 +0200 (CEST) Subject: [pypy-svn] r65376 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524010600.AC1A2169EB6@codespeak.net> Author: fijal Date: Sun May 24 03:05:56 2009 New Revision: 65376 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Log: * Fix trivial bug * Add a cache for names, so the same name will have the same box. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Sun May 24 03:05:56 2009 @@ -8,6 +8,8 @@ from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.rpython.lltypesystem import lltype, llmemory +_cache = {} + class ParseError(Exception): pass @@ -19,6 +21,10 @@ self.consts = namespace def box_for_var(self, elem): + try: + return _cache[elem] + except KeyError: + pass if elem.startswith('i'): # integer box = BoxInt() @@ -27,6 +33,7 @@ box = BoxPtr() else: raise ParseError("Unknown variable type: %s" % elem) + _cache[elem] = box return box def parse_header_line(self, line): @@ -134,6 +141,8 @@ def parse_inpargs(self, line): base_indent = line.find('[') line = line.strip() + if line == '[]': + return base_indent, [] if base_indent == -1 or not line.endswith(']'): raise ParseError("Wrong header: %s" % line) inpargs = self.parse_header_line(line[1:-1]) From fijal at codespeak.net Sun May 24 03:06:55 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 03:06:55 +0200 (CEST) Subject: [pypy-svn] r65377 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090524010655.79D80169ECE@codespeak.net> Author: fijal Date: Sun May 24 03:06:55 2009 New Revision: 65377 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: Add a guard_class removal Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Sun May 24 03:06:55 2009 @@ -31,8 +31,8 @@ # NOT_RPYTHON self.optimizations = [[] for i in range(rop._LAST)] for opt in opts: - for name, opnum in opname.iteritems(): - meth = getattr(opt, 'optimize_' + name, None) + for opnum, name in opname.iteritems(): + meth = getattr(opt, 'optimize_' + name.lower(), None) if meth is not None: self.optimizations[opnum].append(meth) @@ -127,6 +127,14 @@ self.find_nodes() self.optimize_operations() +class ConsecutiveGuardClassRemoval(object): + def optimize_guard_class(self, op, spec): + instnode = spec.getnode(op.args[0]) + if instnode.cls is not None: + return None + instnode.cls = op.args[1] + return op + specializer = Specializer([]) def optimize_loop(options, old_loops, loop, cpu=None, spec=specializer): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Sun May 24 03:06:55 2009 @@ -8,7 +8,8 @@ ConstInt, BoxInt, BoxObj, ConstObj from pypy.jit.backend.llgraph import runner -from pypy.jit.metainterp.optimize2 import optimize_loop +from pypy.jit.metainterp.optimize2 import (optimize_loop, + ConsecutiveGuardClassRemoval, Specializer) from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY from pypy.jit.metainterp.test.oparser import parse @@ -28,6 +29,8 @@ nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) nodedescr = cpu.fielddescrof(NODE, 'value') + namespace = locals() + class OOtypeMixin(object): cpu = runner.OOtypeCPU(None) @@ -42,18 +45,19 @@ nodebox = BoxObj(ootype.cast_to_object(node)) nodedescr = cpu.fielddescrof(NODE, 'value') - + namespace = locals() class BaseTestOptimize2(object): - def optimize(self, lst): - loop = parse(lst, self.cpu, self.__dict__) - optimize_loop(None, [], loop) + def optimize(self, lst, optimizations_enabled=[]): + loop = parse(lst, self.cpu, self.namespace) + optimize_loop(None, [], loop, self.cpu, + spec=Specializer(optimizations_enabled)) return loop.operations def assert_equal(self, optimized, expected): equaloplists(optimized, - parse(expected, self.cpu, self.__dict__).operations) + parse(expected, self.cpu, self.namespace).operations) def test_basic_constant_folding(self): pre_op = """ @@ -64,20 +68,21 @@ self.assert_equal(self.optimize(pre_op), expected) def test_remove_guard_class(self): - py.test.skip("not yet") pre_op = """ [p0] - guard_class(p0, Const(vtable)) + guard_class(p0, ConstAddr(node_vtable)) fail() - guard_class(p0, Const(vtable)) + guard_class(p0, ConstAddr(node_vtable)) fail() """ expected = """ [p0] - guard_class(p0, Const(vtable)) + guard_class(p0, ConstAddr(node_vtable)) fail() """ - self.equal(self.optimize(pre_op, []), expected) + self.assert_equal(self.optimize(pre_op, + [ConsecutiveGuardClassRemoval()]), + expected) def test_remove_consecutive_guard_value_constfold(self): py.test.skip("not yet") @@ -139,4 +144,5 @@ pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - pass + def setup_class(cls): + py.test.skip("XXX Fix me") From fijal at codespeak.net Sun May 24 05:06:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 05:06:19 +0200 (CEST) Subject: [pypy-svn] r65378 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524030619.90F0316851C@codespeak.net> Author: fijal Date: Sun May 24 05:06:15 2009 New Revision: 65378 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Log: Support for descrs Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Sun May 24 05:06:15 2009 @@ -73,16 +73,21 @@ return opnum, [], None allargs = argspec.split(",") args = [] + descr = None + poss_descr = allargs[-1].strip() + if poss_descr.startswith('descr='): + descr = self.consts[poss_descr[len('descr='):]] + allargs = allargs[:-1] for arg in allargs: arg = arg.strip() try: args.append(self.getvar(arg)) except KeyError: raise ParseError("Unknown var: %s" % arg) - return opnum, args, None + return opnum, args, descr def parse_result_op(self, line): - res, op = line.split("=") + res, op = line.split("=", 1) res = res.strip() op = op.strip() opnum, args, descr = self.parse_op(op) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Sun May 24 05:06:15 2009 @@ -3,6 +3,7 @@ from pypy.jit.metainterp.test.oparser import parse from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp.history import AbstractDescr def test_basic_parse(): x = """ @@ -30,3 +31,14 @@ assert len(loop.operations) == 1 assert len(loop.operations[0].suboperations) == 1 +def test_descr(): + class Xyz(AbstractDescr): + pass + + x = """ + [p0] + i1 = getfield_gc(p0, descr=stuff) + """ + stuff = Xyz() + loop = parse(x, None, locals()) + assert loop.operations[0].descr is stuff From fijal at codespeak.net Sun May 24 16:44:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 16:44:11 +0200 (CEST) Subject: [pypy-svn] r65379 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524144411.8AF0716840E@codespeak.net> Author: fijal Date: Sun May 24 16:44:09 2009 New Revision: 65379 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Log: A test and a fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Sun May 24 16:44:09 2009 @@ -140,7 +140,7 @@ ops[-1].suboperations = suboperations else: ops.append(self.parse_next_op(lines[num].strip())) - num += 1 + num += 1 return num, ops def parse_inpargs(self, line): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Sun May 24 16:44:09 2009 @@ -42,3 +42,13 @@ stuff = Xyz() loop = parse(x, None, locals()) assert loop.operations[0].descr is stuff + +def test_after_fail(): + x = """ + [i0] + guard_value(i0, 3) + fail() + i1 = int_add(1, 2) + """ + loop = parse(x, None, {}) + assert len(loop.operations) == 2 From fijal at codespeak.net Sun May 24 16:51:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 16:51:28 +0200 (CEST) Subject: [pypy-svn] r65380 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090524145128.23E67169F34@codespeak.net> Author: fijal Date: Sun May 24 16:51:27 2009 New Revision: 65380 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: After fixing the runner logic, test started failing, fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Sun May 24 16:51:27 2009 @@ -95,9 +95,13 @@ def optimize_operations(self): newoperations = [] for op in self.loop.operations: + newop = op for opt in self.optimizations[op.opnum]: - if opt(op, self) is None: - continue + newop = opt(op, self) + if newop is None: + break + if newop is None: + continue if op.is_guard(): self.optimize_guard(op) newoperations.append(op) @@ -135,6 +139,10 @@ instnode.cls = op.args[1] return op +class SimpleVirtualizableOpt(object): + def optimize_guard_nonvirtualized(self, op, spec): + xxx + specializer = Specializer([]) def optimize_loop(options, old_loops, loop, cpu=None, spec=specializer): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Sun May 24 16:51:27 2009 @@ -9,7 +9,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.optimize2 import (optimize_loop, - ConsecutiveGuardClassRemoval, Specializer) + ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt) from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY from pypy.jit.metainterp.test.oparser import parse @@ -29,6 +29,10 @@ nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) nodedescr = cpu.fielddescrof(NODE, 'value') + XY = lltype.GcStruct('XY', ('field', lltype.Signed), + hints= {'virtualizable2': True}) + field_desc = cpu.fielddescrof(XY, 'field') + namespace = locals() class OOtypeMixin(object): @@ -84,6 +88,25 @@ [ConsecutiveGuardClassRemoval()]), expected) + def test_basic_virtualizable(self): + py.test.skip("xxx") + pre_op = """ + [p0] + guard_nonvirtualized(p0) + fail() + i1 = getfield_gc(p0, descr=field_desc) + i2 = getfield_gc(p0, descr=field_desc) + i3 = int_add(i1, i2) + """ + expected = """ + [p0] + i1 = getfield_gc(p0, descr=field_desc) + i3 = int_add(i1, i1) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), + expected) + + def test_remove_consecutive_guard_value_constfold(self): py.test.skip("not yet") n = BoxInt(0) From pedronis at codespeak.net Sun May 24 17:04:35 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 24 May 2009 17:04:35 +0200 (CEST) Subject: [pypy-svn] r65381 - pypy/build/bot2/pypybuildbot Message-ID: <20090524150435.20FB0169E3F@codespeak.net> Author: pedronis Date: Sun May 24 17:04:32 2009 New Revision: 65381 Modified: pypy/build/bot2/pypybuildbot/master.py Log: don't run these anymore, doesn't seem will need a micro-release soon Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sun May 24 17:04:32 2009 @@ -51,10 +51,6 @@ 'change_source': [], 'schedulers': [ - Nightly("nightly-1.1.x", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, - STACKLESSAPPLVLLINUX32], - hour=0, minute=45, branch="release/1.1.x", - ), Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, STACKLESSAPPLVLLINUX32], hour=4, minute=45), From afa at codespeak.net Sun May 24 18:13:22 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 24 May 2009 18:13:22 +0200 (CEST) Subject: [pypy-svn] r65382 - pypy/trunk/pypy/module/posix/test Message-ID: <20090524161322.16A9C169F3C@codespeak.net> Author: afa Date: Sun May 24 18:13:20 2009 New Revision: 65382 Modified: pypy/trunk/pypy/module/posix/test/test_posix2.py Log: "import os.path" masks the previous value of "os". Be sure to test the right module. 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 Sun May 24 18:13:20 2009 @@ -286,9 +286,9 @@ def test_utime(self): os = self.posix - import os.path + from os.path import join # XXX utimes & float support - path = os.path.join(self.pdir, "test_utime.txt") + path = join(self.pdir, "test_utime.txt") fh = open(path, "w") fh.write("x") fh.close() From afa at codespeak.net Sun May 24 19:33:13 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 24 May 2009 19:33:13 +0200 (CEST) Subject: [pypy-svn] r65383 - pypy/trunk/pypy/rpython/module Message-ID: <20090524173313.0335A16847C@codespeak.net> Author: afa Date: Sun May 24 19:33:11 2009 New Revision: 65383 Modified: pypy/trunk/pypy/rpython/module/ll_os.py Log: On Windows, fsync() spells _commit() 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 Sun May 24 19:33:11 2009 @@ -832,7 +832,10 @@ @registering_if(os, 'fsync') def register_os_fsync(self): - os_fsync = self.llexternal('fsync', [rffi.INT], rffi.INT) + if not _WIN32: + os_fsync = self.llexternal('fsync', [rffi.INT], rffi.INT) + else: + os_fsync = self.llexternal('_commit', [rffi.INT], rffi.INT) def fsync_llimpl(fd): res = rffi.cast(rffi.LONG, os_fsync(rffi.cast(rffi.INT, fd))) From fijal at codespeak.net Sun May 24 23:18:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 23:18:19 +0200 (CEST) Subject: [pypy-svn] r65387 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524211819.5E6FC169F35@codespeak.net> Author: fijal Date: Sun May 24 23:18:16 2009 New Revision: 65387 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Log: A test and a fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Sun May 24 23:18:16 2009 @@ -102,7 +102,7 @@ return ResOperation(opnum, args, None, descr) def parse_next_op(self, line): - if "=" in line: + if "=" in line and line.find('(') > line.find('='): return self.parse_result_op(line) else: return self.parse_op_no_result(line) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Sun May 24 23:18:16 2009 @@ -52,3 +52,15 @@ """ loop = parse(x, None, {}) assert len(loop.operations) == 2 + +def test_descr_setfield(): + class Xyz(AbstractDescr): + pass + + x = """ + [p0] + setfield_gc(p0, 3, descr=stuff) + """ + stuff = Xyz() + loop = parse(x, None, locals()) + assert loop.operations[0].descr is stuff From fijal at codespeak.net Sun May 24 23:18:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 24 May 2009 23:18:52 +0200 (CEST) Subject: [pypy-svn] r65388 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090524211852.73316169F40@codespeak.net> Author: fijal Date: Sun May 24 23:18:51 2009 New Revision: 65388 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/virtualizable.py Log: fix mro Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/virtualizable.py Sun May 24 23:18:51 2009 @@ -7,7 +7,7 @@ from pypy.annotation.model import lltype_to_annotation from pypy.rlib.objectmodel import we_are_translated -class VirtualizableDesc(history.AbstractValue): +class VirtualizableDesc(history.AbstractDescr): hash = 0 def __init__(self, cpu, TOPSTRUCT, STRUCTTYPE): From fijal at codespeak.net Mon May 25 00:37:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:37:21 +0200 (CEST) Subject: [pypy-svn] r65389 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090524223721.AF255169F4F@codespeak.net> Author: fijal Date: Mon May 25 00:37:16 2009 New Revision: 65389 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: implement setfield/getfield optimization for fields marked as virtuals Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 00:37:16 2009 @@ -13,6 +13,7 @@ self.cls = None self.cleanfields = {} self.dirtyfields = {} + self.virtualized = False def __repr__(self): flags = '' @@ -20,7 +21,7 @@ #if self.startbox: flags += 's' if self.const: flags += 'c' #if self.virtual: flags += 'v' - #if self.virtualized: flags += 'V' + if self.virtualized: flags += 'V' return "" % (self.source, flags) class Specializer(object): @@ -62,7 +63,7 @@ if is_pure: box = op.result assert box is not None - self.nodes[box] = InstanceNode(box.constbox(), const=True) + self.nodes[box] = self.getnode(box.constbox()) continue else: if op.is_guard(): @@ -73,7 +74,7 @@ self.getnode(box) box = op.result if box is not None: - self.nodes[box] = InstanceNode(box) + self.nodes[box] = self.getnode(box) def new_arguments(self, op): newboxes = [] @@ -90,9 +91,15 @@ op_fail.args = self.new_arguments(op_fail) # modification in place. Reason for this is explained in mirror # in optimize.py - op.suboperations = [op_fail] + op.suboperations = [] + for node, field in self.additional_stores: + op.suboperations.append(ResOperation(rop.SETFIELD_GC, + [node.source, node.cleanfields[field].source], None, field)) + op.suboperations.append(op_fail) + op.args = self.new_arguments(op) def optimize_operations(self): + self.additional_stores = [] newoperations = [] for op in self.loop.operations: newop = op @@ -141,7 +148,36 @@ class SimpleVirtualizableOpt(object): def optimize_guard_nonvirtualized(self, op, spec): - xxx + instnode = spec.getnode(op.args[0]) + instnode.virtualized = True + instnode.vdesc = op.descr + return None + + def optimize_getfield_gc(self, op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtualized: + return op + field = op.descr + if field not in instnode.vdesc.virtuals: + return op + node = instnode.cleanfields.get(field, None) + if node is not None: + spec.nodes[op.result] = node + return None + instnode.cleanfields[field] = spec.getnode(op.result) + return op + + def optimize_setfield_gc(self, op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtualized: + return op + field = op.descr + if field not in instnode.vdesc.virtuals: + return op + instnode.cleanfields[field] = spec.getnode(op.args[1]) + # we never set it here + spec.additional_stores.append((instnode, field)) + return None specializer = Specializer([]) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Mon May 25 00:37:16 2009 @@ -10,9 +10,36 @@ from pypy.jit.metainterp.optimize2 import (optimize_loop, ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt) -from pypy.jit.metainterp.test.test_optimize import equaloplists, ANY +from pypy.jit.metainterp.test.test_optimize import ANY from pypy.jit.metainterp.test.oparser import parse +from pypy.jit.metainterp.virtualizable import VirtualizableDesc + +def equaloplists(oplist1, oplist2): + #saved = Box._extended_display + #try: + # Box._extended_display = False + print '-'*20, 'Comparing lists', '-'*20 + for op1, op2 in zip(oplist1, oplist2): + txt1 = str(op1) + txt2 = str(op2) + while txt1 or txt2: + print '%-39s| %s' % (txt1[:39], txt2[:39]) + txt1 = txt1[39:] + txt2 = txt2[39:] + assert op1.opnum == op2.opnum + assert len(op1.args) == len(op2.args) + for x, y in zip(op1.args, op2.args): + assert x == y or y == x # for ANY object :-( + assert op1.result == op2.result + assert op1.descr == op2.descr + if op1.suboperations or op2.suboperations: + equaloplists(op1.suboperations, op2.suboperations) + assert len(oplist1) == len(oplist2) + print '-'*57 + #finally: + # Box._extended_display = saved + return True class LLtypeMixin(object): @@ -29,9 +56,13 @@ nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) nodedescr = cpu.fielddescrof(NODE, 'value') - XY = lltype.GcStruct('XY', ('field', lltype.Signed), - hints= {'virtualizable2': True}) - field_desc = cpu.fielddescrof(XY, 'field') + XY = lltype.GcStruct('XY', ('inst_field', lltype.Signed), + ('inst_other_field', lltype.Signed), + hints= {'virtualizable2': True, + 'virtuals': ('field',)}) + field_desc = cpu.fielddescrof(XY, 'inst_field') + other_field_desc = cpu.fielddescrof(XY, 'inst_other_field') + vdesc = VirtualizableDesc(cpu, XY, XY) namespace = locals() @@ -89,10 +120,9 @@ expected) def test_basic_virtualizable(self): - py.test.skip("xxx") pre_op = """ [p0] - guard_nonvirtualized(p0) + guard_nonvirtualized(p0, descr=vdesc) fail() i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=field_desc) @@ -105,6 +135,31 @@ """ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), expected) + + def test_virtualizable_setfield_rebuild_ops(self): + pre_op = """ + [p0] + guard_nonvirtualized(p0, descr=vdesc) + fail() + i1 = getfield_gc(p0, descr=field_desc) + i2 = getfield_gc(p0, descr=other_field_desc) + setfield_gc(p0, i2, descr=field_desc) + # ^^^ this should be gone + i3 = getfield_gc(p0, descr=field_desc) + # ^^^ this one as well + guard_true(i3) + fail() + """ + expected = """ + [p0] + i1 = getfield_gc(p0, descr=field_desc) + i2 = getfield_gc(p0, descr=other_field_desc) + guard_true(i2) + setfield_gc(p0, i2, descr=field_desc) + fail() + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), + expected) def test_remove_consecutive_guard_value_constfold(self): From fijal at codespeak.net Mon May 25 00:45:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:45:21 +0200 (CEST) Subject: [pypy-svn] r65390 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524224521.2CD21169F53@codespeak.net> Author: fijal Date: Mon May 25 00:45:20 2009 New Revision: 65390 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Log: fix for vdesc Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Mon May 25 00:45:20 2009 @@ -70,13 +70,18 @@ raise ParseError("invalid line: %s" % line) argspec = line[num + 1:endnum] if not argspec.strip(): - return opnum, [], None + return opnum, [], None, None allargs = argspec.split(",") args = [] descr = None + vdesc = None poss_descr = allargs[-1].strip() if poss_descr.startswith('descr='): descr = self.consts[poss_descr[len('descr='):]] + allargs = allargs[:-1] + poss_vdesc = allargs[-1].strip() + if poss_vdesc.startswith('vdesc='): + descr = self.consts[poss_descr[len('vdesc='):]] allargs = allargs[:-1] for arg in allargs: arg = arg.strip() @@ -84,22 +89,26 @@ args.append(self.getvar(arg)) except KeyError: raise ParseError("Unknown var: %s" % arg) - return opnum, args, descr + return opnum, args, descr, vdesc def parse_result_op(self, line): res, op = line.split("=", 1) res = res.strip() op = op.strip() - opnum, args, descr = self.parse_op(op) + opnum, args, descr, vdesc = self.parse_op(op) if res in self.vars: raise ParseError("Double assign to var %s in line: %s" % (res, line)) rvar = self.box_for_var(res) self.vars[res] = rvar - return ResOperation(opnum, args, rvar, descr) + res = ResOperation(opnum, args, rvar, descr) + res.vdesc = vdesc + return res def parse_op_no_result(self, line): - opnum, args, descr = self.parse_op(line) - return ResOperation(opnum, args, None, descr) + opnum, args, descr, vdesc = self.parse_op(line) + res = ResOperation(opnum, args, None, descr) + res.vdesc = vdesc + return res def parse_next_op(self, line): if "=" in line and line.find('(') > line.find('='): From fijal at codespeak.net Mon May 25 00:47:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:47:26 +0200 (CEST) Subject: [pypy-svn] r65391 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524224726.7494F168031@codespeak.net> Author: fijal Date: Mon May 25 00:47:25 2009 New Revision: 65391 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Log: A test and a proper fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Mon May 25 00:47:25 2009 @@ -81,7 +81,7 @@ allargs = allargs[:-1] poss_vdesc = allargs[-1].strip() if poss_vdesc.startswith('vdesc='): - descr = self.consts[poss_descr[len('vdesc='):]] + vdesc = self.consts[poss_descr[len('vdesc='):]] allargs = allargs[:-1] for arg in allargs: arg = arg.strip() Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Mon May 25 00:47:25 2009 @@ -64,3 +64,18 @@ stuff = Xyz() loop = parse(x, None, locals()) assert loop.operations[0].descr is stuff + +def test_vdesc(): + class Xyz(AbstractDescr): + pass + + x = """ + [p0] + guard_nonvirtualized(p0, vdesc=stuff) + fail() + """ + stuff = Xyz() + loop = parse(x, None, locals()) + assert loop.operations[0].vdesc is stuff + + From fijal at codespeak.net Mon May 25 00:50:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:50:43 +0200 (CEST) Subject: [pypy-svn] r65392 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090524225043.0A2D9169F0D@codespeak.net> Author: fijal Date: Mon May 25 00:50:42 2009 New Revision: 65392 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Log: harmless change Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Mon May 25 00:50:42 2009 @@ -81,7 +81,7 @@ allargs = allargs[:-1] poss_vdesc = allargs[-1].strip() if poss_vdesc.startswith('vdesc='): - vdesc = self.consts[poss_descr[len('vdesc='):]] + vdesc = self.consts[poss_vdesc[len('vdesc='):]] allargs = allargs[:-1] for arg in allargs: arg = arg.strip() From fijal at codespeak.net Mon May 25 00:52:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:52:54 +0200 (CEST) Subject: [pypy-svn] r65393 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090524225254.D475E169F52@codespeak.net> Author: fijal Date: Mon May 25 00:52:54 2009 New Revision: 65393 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a fix how it works in RL Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 00:52:54 2009 @@ -150,7 +150,7 @@ def optimize_guard_nonvirtualized(self, op, spec): instnode = spec.getnode(op.args[0]) instnode.virtualized = True - instnode.vdesc = op.descr + instnode.vdesc = op.vdesc return None def optimize_getfield_gc(self, op, spec): @@ -179,7 +179,8 @@ spec.additional_stores.append((instnode, field)) return None -specializer = Specializer([]) +specializer = Specializer([SimpleVirtualizableOpt(), + ConsecutiveGuardClassRemoval()]) def optimize_loop(options, old_loops, loop, cpu=None, spec=specializer): if old_loops: Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Mon May 25 00:52:54 2009 @@ -122,7 +122,7 @@ def test_basic_virtualizable(self): pre_op = """ [p0] - guard_nonvirtualized(p0, descr=vdesc) + guard_nonvirtualized(p0, vdesc=vdesc) fail() i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=field_desc) @@ -139,7 +139,7 @@ def test_virtualizable_setfield_rebuild_ops(self): pre_op = """ [p0] - guard_nonvirtualized(p0, descr=vdesc) + guard_nonvirtualized(p0, vdesc=vdesc) fail() i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=other_field_desc) From fijal at codespeak.net Mon May 25 00:55:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:55:26 +0200 (CEST) Subject: [pypy-svn] r65394 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090524225526.2AB3D169F55@codespeak.net> Author: fijal Date: Mon May 25 00:55:25 2009 New Revision: 65394 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Log: I suppose we're mature enough to print a dot per graph instead :) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Mon May 25 00:55:25 2009 @@ -293,7 +293,7 @@ if self.debug: self.bytecode.dump() else: - print repr(self.bytecode) + log.dot() dir = udir.ensure("jitcodes", dir=1) if self.portal: name = "portal_runner" From fijal at codespeak.net Mon May 25 00:59:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 00:59:54 +0200 (CEST) Subject: [pypy-svn] r65395 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090524225954.7068D169F5B@codespeak.net> Author: fijal Date: Mon May 25 00:59:54 2009 New Revision: 65395 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Log: print info each 500 jitcodes Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Mon May 25 00:59:54 2009 @@ -92,6 +92,7 @@ self.cpu = metainterp_sd.cpu self.policy = policy self.ts = ts + self.counter = 0 def make_portal_bytecode(self, graph): log.info("making JitCodes...") @@ -111,6 +112,9 @@ maker = BytecodeMaker(self, graph_key, portal) if not hasattr(maker.bytecode, 'code'): maker.assemble() + self.counter += 1 + if not self.counter % 500: + log.info("Produced %d jitcodes" % self.counter) return maker.bytecode def get_jitcode(self, graph, called_from=None, oosend_methdescr=None): From fijal at codespeak.net Mon May 25 02:04:50 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 02:04:50 +0200 (CEST) Subject: [pypy-svn] r65396 - pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit Message-ID: <20090525000450.4686A169F28@codespeak.net> Author: fijal Date: Mon May 25 02:04:47 2009 New Revision: 65396 Modified: pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/interp_jit.py Log: change a bit fields. They have different meaning right now though Modified: pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/interp_jit.py Mon May 25 02:04:47 2009 @@ -17,7 +17,7 @@ from pypy.interpreter.pyopcode import ExitFrame PyFrame._virtualizable2_ = True -PyFrame._always_virtual_ = ['valuestack_w', 'fastlocals_w'] +PyFrame._always_virtual_ = ['valuestack_w', 'valuestackdepth'] class PyPyJitDriver(JitDriver): reds = ['frame', 'ec'] @@ -70,7 +70,7 @@ # ____________________________________________________________ # -# Public interface +# Public interface def set_param(space, args): '''Configure the tunable JIT parameters. From fijal at codespeak.net Mon May 25 02:15:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 02:15:49 +0200 (CEST) Subject: [pypy-svn] r65397 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090525001549.7DE36169E82@codespeak.net> Author: fijal Date: Mon May 25 02:15:44 2009 New Revision: 65397 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: oops, avoid consecutive stores Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 02:15:44 2009 @@ -92,14 +92,14 @@ # modification in place. Reason for this is explained in mirror # in optimize.py op.suboperations = [] - for node, field in self.additional_stores: + for (node, field), fieldnode in self.additional_stores.iteritems(): op.suboperations.append(ResOperation(rop.SETFIELD_GC, [node.source, node.cleanfields[field].source], None, field)) op.suboperations.append(op_fail) op.args = self.new_arguments(op) def optimize_operations(self): - self.additional_stores = [] + self.additional_stores = {} newoperations = [] for op in self.loop.operations: newop = op @@ -174,9 +174,10 @@ field = op.descr if field not in instnode.vdesc.virtuals: return op - instnode.cleanfields[field] = spec.getnode(op.args[1]) + node = spec.getnode(op.args[1]) + instnode.cleanfields[field] = node # we never set it here - spec.additional_stores.append((instnode, field)) + spec.additional_stores[instnode, field] = node return None specializer = Specializer([SimpleVirtualizableOpt(), From fijal at codespeak.net Mon May 25 04:31:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 04:31:47 +0200 (CEST) Subject: [pypy-svn] r65398 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090525023147.B6744169F64@codespeak.net> Author: fijal Date: Mon May 25 04:31:44 2009 New Revision: 65398 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: move constant folding of guards into specializer Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 04:31:44 2009 @@ -4,6 +4,9 @@ from pypy.jit.metainterp.resoperation import rop, ResOperation, opname from pypy.jit.metainterp.history import Const, Box +class VirtualizedListAccessedWithVariableArg(Exception): + pass + class InstanceNode(object): def __init__(self, source, const=False): self.source = source @@ -14,6 +17,7 @@ self.cleanfields = {} self.dirtyfields = {} self.virtualized = False + self.possibly_virtualized_list = False def __repr__(self): flags = '' @@ -86,6 +90,11 @@ return newboxes def optimize_guard(self, op): + for arg in op.args: + if not self.getnode(arg).const: + break + else: + return None assert len(op.suboperations) == 1 op_fail = op.suboperations[0] op_fail.args = self.new_arguments(op_fail) @@ -95,11 +104,16 @@ for (node, field), fieldnode in self.additional_stores.iteritems(): op.suboperations.append(ResOperation(rop.SETFIELD_GC, [node.source, node.cleanfields[field].source], None, field)) + for (node, field), (fieldnode, descr) in self.additional_setarrayitems.iteritems(): + op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, + [node.source, field, node.cleanfields[field].source], None, descr)) op.suboperations.append(op_fail) op.args = self.new_arguments(op) + return op def optimize_operations(self): self.additional_stores = {} + self.additional_setarrayitems = {} newoperations = [] for op in self.loop.operations: newop = op @@ -110,13 +124,14 @@ if newop is None: continue if op.is_guard(): - self.optimize_guard(op) - newoperations.append(op) + op = self.optimize_guard(op) + if op is not None: + newoperations.append(op) continue # default handler op = op.clone() op.args = self.new_arguments(op) - if op.is_always_pure(): + if op.is_always_pure() or op.is_guard(): for box in op.args: if isinstance(box, Box): break @@ -164,7 +179,9 @@ if node is not None: spec.nodes[op.result] = node return None - instnode.cleanfields[field] = spec.getnode(op.result) + node = spec.getnode(op.result) + node.possibly_virtualized_list = True + instnode.cleanfields[field] = node return op def optimize_setfield_gc(self, op, spec): @@ -180,6 +197,35 @@ spec.additional_stores[instnode, field] = node return None + def optimize_getarrayitem_gc(self, op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.possibly_virtualized_list: + return op + if not spec.getnode(op.args[1]).const: + raise VirtualizedListAccessedWithVariableArg() + field = spec.getnode(op.args[1]).source + node = instnode.cleanfields.get(field, None) + if node is not None: + spec.nodes[op.result] = node + return None + node = spec.getnode(op.result) + instnode.cleanfields[field] = node + return op + + + def optimize_setarrayitem_gc(self, op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.possibly_virtualized_list: + return op + fieldnode = spec.getnode(op.args[1]) + if not fieldnode.const: + raise VirtualizedListAccessedWithVariableArg() + node = spec.getnode(op.args[2]) + field = fieldnode.source + instnode.cleanfields[field] = node + spec.additional_setarrayitems[instnode, field] = (node, op.descr) + return None + specializer = Specializer([SimpleVirtualizableOpt(), ConsecutiveGuardClassRemoval()]) @@ -200,3 +246,4 @@ optimize_bridge = staticmethod(optimize_bridge) + Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Mon May 25 04:31:44 2009 @@ -56,11 +56,16 @@ nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) nodedescr = cpu.fielddescrof(NODE, 'value') + TP = lltype.GcArray(lltype.Signed) + XY = lltype.GcStruct('XY', ('inst_field', lltype.Signed), ('inst_other_field', lltype.Signed), + ('inst_list', lltype.Ptr(TP)), hints= {'virtualizable2': True, - 'virtuals': ('field',)}) + 'virtuals': ('field','list')}) field_desc = cpu.fielddescrof(XY, 'inst_field') + array_descr = cpu.arraydescrof(TP) + list_desc = cpu.fielddescrof(XY, 'inst_list') other_field_desc = cpu.fielddescrof(XY, 'inst_other_field') vdesc = VirtualizableDesc(cpu, XY, XY) @@ -85,7 +90,10 @@ class BaseTestOptimize2(object): def optimize(self, lst, optimizations_enabled=[]): - loop = parse(lst, self.cpu, self.namespace) + if not isinstance(lst, TreeLoop): + loop = parse(lst, self.cpu, self.namespace) + else: + loop = lst optimize_loop(None, [], loop, self.cpu, spec=Specializer(optimizations_enabled)) return loop.operations @@ -160,7 +168,67 @@ """ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), expected) - + + def test_const_guard_value(self): + pre_op = """ + [] + guard_value(0, 0) + fail() + """ + expected = "[]" + self.assert_equal(self.optimize(pre_op, []), expected) + + def test_virtualized_list_on_virtualizable(self): + pre_op = """ + [p0] + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + p1 = getfield_gc(p0, descr=list_desc) + setarrayitem_gc(p1, 0, 1, descr=array_descr) + i1 = getarrayitem_gc(p1, 0) + i2 = int_add(i1, i1) + i3 = int_is_true(i2) + guard_true(i3) + fail() + """ + pre_op = parse(pre_op, self.cpu, self.namespace) + # cheat + pre_op.operations[-2].result.value = 1 + expected = """ + [p0] + p1 = getfield_gc(p0, descr=list_desc) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), + expected) + + + def test_virtualized_list_on_virtualizable_2(self): + pre_op = """ + [p0, i0] + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + p1 = getfield_gc(p0, descr=list_desc) + setarrayitem_gc(p1, 0, i0, descr=array_descr) + i1 = getarrayitem_gc(p1, 0) + i2 = int_add(i1, i1) + i3 = int_is_true(i2) + guard_true(i3) + fail() + """ + pre_op = parse(pre_op, self.cpu, self.namespace) + # cheat + pre_op.operations[-2].result.value = 1 + expected = """ + [p0, i0] + p1 = getfield_gc(p0, descr=list_desc) + i2 = int_add(i0, i0) + i3 = int_is_true(i2) + guard_true(i3) + setarrayitem_gc(p1, 0, i0, descr=array_descr) + fail() + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), + expected) def test_remove_consecutive_guard_value_constfold(self): py.test.skip("not yet") From fijal at codespeak.net Mon May 25 04:48:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 04:48:15 +0200 (CEST) Subject: [pypy-svn] r65399 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090525024815.3A220169F55@codespeak.net> Author: fijal Date: Mon May 25 04:48:12 2009 New Revision: 65399 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: oops. This element of if is always false, but kill it anyway to avoid confusion Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 04:48:12 2009 @@ -131,7 +131,7 @@ # default handler op = op.clone() op.args = self.new_arguments(op) - if op.is_always_pure() or op.is_guard(): + if op.is_always_pure(): for box in op.args: if isinstance(box, Box): break From fijal at codespeak.net Mon May 25 04:49:12 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 04:49:12 +0200 (CEST) Subject: [pypy-svn] r65400 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090525024912.AED5F169F55@codespeak.net> Author: fijal Date: Mon May 25 04:49:12 2009 New Revision: 65400 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py Log: improve repr Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py Mon May 25 04:49:12 2009 @@ -42,13 +42,18 @@ return self.repr() def repr(self): + from pypy.rlib.objectmodel import we_are_translated # RPython-friendly version if self.result is not None: sres = '%s = ' % (self.result,) else: sres = '' - return '%s%s(%s)' % (sres, self.getopname(), - ', '.join([str(a) for a in self.args])) + if self.descr is None or we_are_translated(): + return '%s%s(%s)' % (sres, self.getopname(), + ', '.join([str(a) for a in self.args])) + else: + return '%s%s(%s, descr=%r)' % (sres, self.getopname(), + ', '.join([str(a) for a in self.args]), self.descr) def getopname(self): try: From fijal at codespeak.net Mon May 25 05:42:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 05:42:33 +0200 (CEST) Subject: [pypy-svn] r65401 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090525034233.16C78169F28@codespeak.net> Author: fijal Date: Mon May 25 05:42:31 2009 New Revision: 65401 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: Fix annotation by providing a common superclass Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 05:42:31 2009 @@ -153,7 +153,10 @@ self.find_nodes() self.optimize_operations() -class ConsecutiveGuardClassRemoval(object): +class AbstractOptimization(object): + pass + +class ConsecutiveGuardClassRemoval(AbstractOptimization): def optimize_guard_class(self, op, spec): instnode = spec.getnode(op.args[0]) if instnode.cls is not None: @@ -161,7 +164,7 @@ instnode.cls = op.args[1] return op -class SimpleVirtualizableOpt(object): +class SimpleVirtualizableOpt(AbstractOptimization): def optimize_guard_nonvirtualized(self, op, spec): instnode = spec.getnode(op.args[0]) instnode.virtualized = True From fijal at codespeak.net Mon May 25 05:47:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 05:47:00 +0200 (CEST) Subject: [pypy-svn] r65402 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090525034700.C4B1C169F28@codespeak.net> Author: fijal Date: Mon May 25 05:46:59 2009 New Revision: 65402 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: hack differently Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 05:46:59 2009 @@ -153,25 +153,25 @@ self.find_nodes() self.optimize_operations() -class AbstractOptimization(object): - pass - -class ConsecutiveGuardClassRemoval(AbstractOptimization): - def optimize_guard_class(self, op, spec): +class ConsecutiveGuardClassRemoval(object): + @staticmethod + def optimize_guard_class(op, spec): instnode = spec.getnode(op.args[0]) if instnode.cls is not None: return None instnode.cls = op.args[1] return op -class SimpleVirtualizableOpt(AbstractOptimization): - def optimize_guard_nonvirtualized(self, op, spec): +class SimpleVirtualizableOpt(object): + @staticmethod + def optimize_guard_nonvirtualized(op, spec): instnode = spec.getnode(op.args[0]) instnode.virtualized = True instnode.vdesc = op.vdesc return None - def optimize_getfield_gc(self, op, spec): + @staticmethod + def optimize_getfield_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.virtualized: return op @@ -187,7 +187,8 @@ instnode.cleanfields[field] = node return op - def optimize_setfield_gc(self, op, spec): + @staticmethod + def optimize_setfield_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.virtualized: return op @@ -200,7 +201,8 @@ spec.additional_stores[instnode, field] = node return None - def optimize_getarrayitem_gc(self, op, spec): + @staticmethod + def optimize_getarrayitem_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.possibly_virtualized_list: return op @@ -214,9 +216,9 @@ node = spec.getnode(op.result) instnode.cleanfields[field] = node return op - - def optimize_setarrayitem_gc(self, op, spec): + @staticmethod + def optimize_setarrayitem_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.possibly_virtualized_list: return op From fijal at codespeak.net Mon May 25 06:57:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 06:57:36 +0200 (CEST) Subject: [pypy-svn] r65403 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090525045736.B3BF0169F35@codespeak.net> Author: fijal Date: Mon May 25 06:57:34 2009 New Revision: 65403 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: rpython fixes and minor cleanup Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Mon May 25 06:57:34 2009 @@ -101,12 +101,15 @@ # modification in place. Reason for this is explained in mirror # in optimize.py op.suboperations = [] - for (node, field), fieldnode in self.additional_stores.iteritems(): - op.suboperations.append(ResOperation(rop.SETFIELD_GC, - [node.source, node.cleanfields[field].source], None, field)) - for (node, field), (fieldnode, descr) in self.additional_setarrayitems.iteritems(): - op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, - [node.source, field, node.cleanfields[field].source], None, descr)) + for node, d in self.additional_stores.iteritems(): + for field, fieldnode in d.iteritems(): + op.suboperations.append(ResOperation(rop.SETFIELD_GC, + [node.source, fieldnode.source], None, field)) + for node, d in self.additional_setarrayitems.iteritems(): + for field, (fieldnode, descr) in d.iteritems(): + box = fieldnode.source + op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, + [node.source, field, box], None, descr)) op.suboperations.append(op_fail) op.args = self.new_arguments(op) return op @@ -198,7 +201,8 @@ node = spec.getnode(op.args[1]) instnode.cleanfields[field] = node # we never set it here - spec.additional_stores[instnode, field] = node + d = spec.additional_stores.setdefault(instnode, {}) + d[field] = node return None @staticmethod @@ -222,13 +226,14 @@ instnode = spec.getnode(op.args[0]) if not instnode.possibly_virtualized_list: return op - fieldnode = spec.getnode(op.args[1]) - if not fieldnode.const: + argnode = spec.getnode(op.args[1]) + if not argnode.const: raise VirtualizedListAccessedWithVariableArg() - node = spec.getnode(op.args[2]) - field = fieldnode.source - instnode.cleanfields[field] = node - spec.additional_setarrayitems[instnode, field] = (node, op.descr) + fieldnode = spec.getnode(op.args[2]) + field = argnode.source + instnode.cleanfields[field] = fieldnode + d = spec.additional_setarrayitems.setdefault(instnode, {}) + d[field] = (fieldnode, op.descr) return None specializer = Specializer([SimpleVirtualizableOpt(), From fijal at codespeak.net Mon May 25 07:07:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 25 May 2009 07:07:51 +0200 (CEST) Subject: [pypy-svn] r65404 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86 Message-ID: <20090525050751.C0E0A169F94@codespeak.net> Author: fijal Date: Mon May 25 07:07:49 2009 New Revision: 65404 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py Log: for unclear reason this sometimes explodes when annotating (saying that it cannot run compute_unique_id on None). Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py Mon May 25 07:07:49 2009 @@ -188,7 +188,11 @@ if op.is_guard(): self.eventually_log_operations(None, op.suboperations, memo) if operations[-1].opnum == rop.JUMP: - jump_target = compute_unique_id(operations[-1].jump_target) + if operations[-1].jump_target is not None: + jump_target = compute_unique_id(operations[-1].jump_target) + else: + # XXX hack for the annotator + jump_target = 13 os.write(self._log_fd, 'JUMPTO:%s\n' % jump_target) if inputargs is None: os.write(self._log_fd, "END\n") From antocuni at codespeak.net Mon May 25 10:34:19 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 25 May 2009 10:34:19 +0200 (CEST) Subject: [pypy-svn] r65405 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090525083419.CFCF5169FA1@codespeak.net> Author: antocuni Date: Mon May 25 10:34:18 2009 New Revision: 65405 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: start to port test_optimize2.py to ootype Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Mon May 25 10:34:18 2009 @@ -4,9 +4,10 @@ """ from pypy.jit.metainterp.history import TreeLoop, BoxInt, BoxPtr, ConstInt,\ - ConstAddr + ConstAddr, ConstObj from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype _cache = {} @@ -14,11 +15,12 @@ pass class OpParser(object): - def __init__(self, descr, cpu, namespace): + def __init__(self, descr, cpu, namespace, type_system): self.descr = descr self.vars = {} self.cpu = cpu self.consts = namespace + self.type_system = type_system def box_for_var(self, elem): try: @@ -50,10 +52,13 @@ try: return ConstInt(int(arg)) except ValueError: - if arg.startswith('ConstAddr('): - name = arg[len('ConstAddr('):-1] - return ConstAddr(llmemory.cast_ptr_to_adr(self.consts[name]), - self.cpu) + if arg.startswith('ConstClass('): + name = arg[len('ConstClass('):-1] + if self.type_system == 'lltype': + return ConstAddr(llmemory.cast_ptr_to_adr(self.consts[name]), + self.cpu) + else: + return ConstObj(ootype.cast_to_object(self.consts[name])) return self.vars[arg] def parse_op(self, line): @@ -162,5 +167,5 @@ inpargs = self.parse_header_line(line[1:-1]) return base_indent, inpargs -def parse(descr, cpu=None, namespace={}): - return OpParser(descr, cpu, namespace).parse() +def parse(descr, cpu=None, namespace={}, type_system='lltype'): + return OpParser(descr, cpu, namespace, type_system).parse() Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_oparser.py Mon May 25 10:34:18 2009 @@ -22,7 +22,7 @@ def test_const_ptr_subops(): x = """ [p0] - guard_class(p0, ConstAddr(vtable)) + guard_class(p0, ConstClass(vtable)) fail() """ S = lltype.Struct('S') Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Mon May 25 10:34:18 2009 @@ -42,6 +42,7 @@ return True class LLtypeMixin(object): + type_system = 'lltype' node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable) @@ -72,6 +73,8 @@ namespace = locals() class OOtypeMixin(object): + type_system = 'ootype' + cpu = runner.OOtypeCPU(None) NODE = ootype.Instance('NODE', ootype.ROOT, {}) @@ -85,13 +88,32 @@ nodebox = BoxObj(ootype.cast_to_object(node)) nodedescr = cpu.fielddescrof(NODE, 'value') + TP = ootype.Array(ootype.Signed) + + XY = ootype.Instance('XY', ootype.ROOT, + {'inst_field': ootype.Signed, + 'inst_other_field': ootype.Signed, + 'inst_list': TP}, + _hints = {'virtualizable2': True, + 'virtuals': ('field','list')}) + + field_desc = cpu.fielddescrof(XY, 'inst_field') + array_descr = cpu.arraydescrof(TP) + list_desc = cpu.fielddescrof(XY, 'inst_list') + other_field_desc = cpu.fielddescrof(XY, 'inst_other_field') + vdesc = VirtualizableDesc(cpu, XY, XY) + namespace = locals() class BaseTestOptimize2(object): + def parse(self, s): + return parse(s, self.cpu, self.namespace, + type_system=self.type_system) + def optimize(self, lst, optimizations_enabled=[]): if not isinstance(lst, TreeLoop): - loop = parse(lst, self.cpu, self.namespace) + loop = self.parse(lst) else: loop = lst optimize_loop(None, [], loop, self.cpu, @@ -99,8 +121,7 @@ return loop.operations def assert_equal(self, optimized, expected): - equaloplists(optimized, - parse(expected, self.cpu, self.namespace).operations) + equaloplists(optimized, self.parse(expected).operations) def test_basic_constant_folding(self): pre_op = """ @@ -113,14 +134,14 @@ def test_remove_guard_class(self): pre_op = """ [p0] - guard_class(p0, ConstAddr(node_vtable)) + guard_class(p0, ConstClass(node_vtable)) fail() - guard_class(p0, ConstAddr(node_vtable)) + guard_class(p0, ConstClass(node_vtable)) fail() """ expected = """ [p0] - guard_class(p0, ConstAddr(node_vtable)) + guard_class(p0, ConstClass(node_vtable)) fail() """ self.assert_equal(self.optimize(pre_op, @@ -290,5 +311,11 @@ pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - def setup_class(cls): - py.test.skip("XXX Fix me") + + def skip(self): + py.test.skip('in-progress') + + test_basic_virtualizable = skip + test_virtualizable_setfield_rebuild_ops = skip + test_virtualized_list_on_virtualizable = skip + test_virtualized_list_on_virtualizable_2 = skip From antocuni at codespeak.net Mon May 25 10:44:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 25 May 2009 10:44:04 +0200 (CEST) Subject: [pypy-svn] r65406 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090525084404.3A34E169FCA@codespeak.net> Author: antocuni Date: Mon May 25 10:44:03 2009 New Revision: 65406 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: fix ootype virtualizable tests Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Mon May 25 10:44:03 2009 @@ -91,16 +91,16 @@ TP = ootype.Array(ootype.Signed) XY = ootype.Instance('XY', ootype.ROOT, - {'inst_field': ootype.Signed, - 'inst_other_field': ootype.Signed, - 'inst_list': TP}, + {'ofield': ootype.Signed, + 'oother_field': ootype.Signed, + 'olist': TP}, _hints = {'virtualizable2': True, 'virtuals': ('field','list')}) - field_desc = cpu.fielddescrof(XY, 'inst_field') + field_desc = cpu.fielddescrof(XY, 'ofield') array_descr = cpu.arraydescrof(TP) - list_desc = cpu.fielddescrof(XY, 'inst_list') - other_field_desc = cpu.fielddescrof(XY, 'inst_other_field') + list_desc = cpu.fielddescrof(XY, 'olist') + other_field_desc = cpu.fielddescrof(XY, 'oother_field') vdesc = VirtualizableDesc(cpu, XY, XY) namespace = locals() @@ -311,11 +311,4 @@ pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - - def skip(self): - py.test.skip('in-progress') - - test_basic_virtualizable = skip - test_virtualizable_setfield_rebuild_ops = skip - test_virtualized_list_on_virtualizable = skip - test_virtualized_list_on_virtualizable_2 = skip + pass From antocuni at codespeak.net Mon May 25 12:43:35 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 25 May 2009 12:43:35 +0200 (CEST) Subject: [pypy-svn] r65407 - in pypy/branch/pyjitpl5-experiments/pypy/jit: . metainterp Message-ID: <20090525104335.BE8FE169FCA@codespeak.net> Author: antocuni Date: Mon May 25 12:43:33 2009 New Revision: 65407 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/conftest.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py Log: add an option to show only the loops, ignoring the annotated/rtyped graphs Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/conftest.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/conftest.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/conftest.py Mon May 25 12:43:33 2009 @@ -9,5 +9,9 @@ group.addoption('--slow', action="store_true", default=False, dest="run_slow_tests", help="run all the compiled tests (instead of just a few)") + group.addoption('--viewloops', action="store_true", + default=False, dest="viewloops", + help="show only the compiled loops") + ConftestPlugin = JitTestPlugin Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py Mon May 25 12:43:33 2009 @@ -66,7 +66,7 @@ def show_loop(metainterp, loop=None, error=None): # debugging - if option.view: + if option.view or option.viewloops: if error: errmsg = error.__class__.__name__ if str(error): From antocuni at codespeak.net Mon May 25 14:09:46 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 25 May 2009 14:09:46 +0200 (CEST) Subject: [pypy-svn] r65408 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph Message-ID: <20090525120946.A537F169F68@codespeak.net> Author: antocuni Date: Mon May 25 14:09:44 2009 New Revision: 65408 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py Log: make reprs of oo descrs more readable Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py Mon May 25 14:09:44 2009 @@ -593,6 +593,9 @@ return boxresult(RESULT, res) self.callmeth = callmeth + def __repr__(self): + return '' % self.methname + class TypeDescr(OODescr): create = None @@ -633,6 +636,9 @@ self.getarraylength = getarraylength self.instanceof = instanceof + def __repr__(self): + return '' % self.TYPE._short_name() + class FieldDescr(OODescr): getfield = None @@ -662,6 +668,9 @@ return self.TYPE == other.TYPE and \ self.fieldname == other.fieldname + def __repr__(self): + return '' % self.fieldname + # ____________________________________________________________ From cfbolz at codespeak.net Mon May 25 14:25:21 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 May 2009 14:25:21 +0200 (CEST) Subject: [pypy-svn] r65409 - in pypy/branch/tagged-pointers-framework/pypy/rpython: lltypesystem memory/gc memory/test test Message-ID: <20090525122521.C506C169F41@codespeak.net> Author: cfbolz Date: Mon May 25 14:25:19 2009 New Revision: 65409 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py Log: - fix casting of opaque pointers to ints. Needed for correct GCREF handing - allowing casting of addresses of dead objects to int. Fixes some test_transformed_gc tests - proper id handling of tagged pointers in moving GCs Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py Mon May 25 14:25:19 2009 @@ -461,8 +461,10 @@ return lltype.nullptr(EXPECTED_TYPE.TO) def _cast_to_int(self): + # This is a bit annoying. We want this method to still work when the + # pointed-to object is dead if self: - return self.ptr._cast_to_int() + return self.ptr._cast_to_int(False) else: return 0 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py Mon May 25 14:25:19 2009 @@ -816,6 +816,7 @@ if not ptr: return nullptr(PTRTYPE.TO) return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj, + ORIGTYPE = CURTYPE, solid = ptr._solid) elif (isinstance(CURTYPE.TO, OpaqueType) and isinstance(PTRTYPE.TO, OpaqueType)): @@ -899,7 +900,7 @@ top_parent = parent return top_parent -def normalizeptr(p): +def normalizeptr(p, check=True): # If p is a pointer, returns the same pointer casted to the largest # containing structure (for the cast where p points to the header part). # Also un-hides pointers to opaque. Null pointers become None. @@ -907,12 +908,17 @@ T = typeOf(p) if not isinstance(T, Ptr): return p # primitive - if not p: + obj = p._getobj(check) + if not obj: return None # null pointer if type(p._obj0) is int: return p # a pointer obtained by cast_int_to_ptr - container = p._obj._normalizedcontainer() - if container is not p._obj: + container = obj._normalizedcontainer() + if type(container) is int: + # this must be an opaque ptr originating from an integer + assert isinstance(obj, _opaque) + return cast_int_to_ptr(obj.ORIGTYPE, container) + if container is not obj: p = _ptr(Ptr(typeOf(container)), container, p._solid) return p @@ -1171,13 +1177,15 @@ raise RuntimeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO)) return _ptr(PTRTYPE, struc, solid=self._solid) - def _cast_to_int(self): - if not self: + def _cast_to_int(self, check=True): + obj = self._getobj(check) + if not obj: return 0 # NULL pointer - obj = self._obj if isinstance(obj, int): return obj # special case for cast_int_to_ptr() results - obj = normalizeptr(self)._obj + obj = normalizeptr(self, check)._getobj(check) + if isinstance(obj, int): + return obj # special case for cast_int_to_ptr() results put into opaques result = intmask(obj._getid()) # assume that id() returns an addressish value which is # not zero and aligned to at least a multiple of 4 @@ -1718,6 +1726,9 @@ # if we are an opaque containing a normal Struct/GcStruct, # unwrap it if hasattr(self, 'container'): + # an integer, cast to a ptr, cast to an opaque + if type(self.container) is int: + return self.container return self.container._normalizedcontainer() else: return _parentable._normalizedcontainer(self) Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py Mon May 25 14:25:19 2009 @@ -243,6 +243,8 @@ GCBase.setup(self) self.objects_with_id = self.AddressDict() self.id_free_list = self.AddressStack() + # XXX XXX XXX think of something sane: + # how do we prevent clashing with tagged pointers? self.next_free_id = 1 def can_move(self, addr): @@ -252,6 +254,11 @@ # Default implementation for id(), assuming that "external" objects # never move. Overriden in the HybridGC. obj = llmemory.cast_ptr_to_adr(ptr) + + # is it a tagged pointer? + if not self.is_valid_gc_object(obj): + return llmemory.cast_adr_to_int(obj) // 2 + if self._is_external(obj): result = obj else: Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py Mon May 25 14:25:19 2009 @@ -553,6 +553,11 @@ def id(self, ptr): obj = llmemory.cast_ptr_to_adr(ptr) + + # is it a tagged pointer? + if not self.is_valid_gc_object(obj): + return llmemory.cast_adr_to_int(obj) + if self._is_external(obj): # a prebuilt or rawmalloced object if self.is_last_generation(obj): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py Mon May 25 14:25:19 2009 @@ -514,6 +514,35 @@ res = self.interpret(fn, [-1000]) assert res == -897 + def test_tagged_id(self): + from pypy.rlib.objectmodel import UnboxedValue, compute_unique_id + + class Unrelated(object): + pass + + u = Unrelated() + u.x = UnboxedObject(47) + def fn(n): + id_prebuilt1 = compute_unique_id(u.x) + if n > 0: + x = BoxedObject(n) + else: + x = UnboxedObject(n) + id_x1 = compute_unique_id(x) + rgc.collect() # check that a prebuilt tagged pointer doesn't explode + id_prebuilt2 = compute_unique_id(u.x) + id_x2 = compute_unique_id(x) + print u.x, id_prebuilt1, id_prebuilt2 + print x, id_x1, id_x2 + return ((id_x1 == id_x2) * 1 + + (id_prebuilt1 == id_prebuilt2) * 10 + + (id_x1 != id_prebuilt1) * 100) + res = self.interpret(fn, [1000]) + assert res == 111 + res = self.interpret(fn, [-1000]) + assert res == 111 + + from pypy.rlib.objectmodel import UnboxedValue class TaggedBase(object): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py Mon May 25 14:25:19 2009 @@ -525,7 +525,7 @@ res = fn([]) assert res == 'y' - def test_tagged(self): + def test_tagged_simple(self): class Unrelated(object): pass @@ -546,6 +546,27 @@ res = func([]) assert res == fn(1000) + fn(-1000) + def test_tagged_prebuilt(self): + + class F: + pass + + f = F() + f.l = [UnboxedObject(10)] + def fn(n): + if n > 0: + x = BoxedObject(n) + else: + x = UnboxedObject(n) + f.l.append(x) + rgc.collect() + return f.l[-1].meth(100) + def func(): + return fn(1000) ^ fn(-1000) + func = self.runner(func) + res = func([]) + assert res == fn(1000) ^ fn(-1000) + from pypy.rlib.objectmodel import UnboxedValue class TaggedBase(object): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py Mon May 25 14:25:19 2009 @@ -112,6 +112,20 @@ interpret(fn, [11521]) +def test_odd_ints_opaque(): + T = GcStruct('T') + Q = GcOpaqueType('Q') + PT = Ptr(T) + PQ = Ptr(Q) + def fn(n): + t = cast_int_to_ptr(PT, n) + assert typeOf(t) == PT + assert cast_ptr_to_int(t) == n + o = cast_opaque_ptr(PQ, t) + assert cast_ptr_to_int(o) == n + + fn(13) + interpret(fn, [11521]) def test_Ptr(): S = GcStruct('s') From cfbolz at codespeak.net Mon May 25 14:34:08 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 May 2009 14:34:08 +0200 (CEST) Subject: [pypy-svn] r65410 - pypy/branch/speedup-global2/pypy/doc/config Message-ID: <20090525123408.CC7B5169F77@codespeak.net> Author: cfbolz Date: Mon May 25 14:34:08 2009 New Revision: 65410 Added: pypy/branch/speedup-global2/pypy/doc/config/objspace.std.withcelldict.txt (contents, props changed) Log: add missing documentation Added: pypy/branch/speedup-global2/pypy/doc/config/objspace.std.withcelldict.txt ============================================================================== --- (empty file) +++ pypy/branch/speedup-global2/pypy/doc/config/objspace.std.withcelldict.txt Mon May 25 14:34:08 2009 @@ -0,0 +1,2 @@ +Enable cell-dicts. This makes global lookups nearly as fast as the lookup of a +local. From antocuni at codespeak.net Mon May 25 15:03:41 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 25 May 2009 15:03:41 +0200 (CEST) Subject: [pypy-svn] r65411 - pypy/branch/pyjitpl5-experiments/pypy/jit/tl Message-ID: <20090525130341.E7AA0169FD7@codespeak.net> Author: antocuni Date: Mon May 25 15:03:40 2009 New Revision: 65411 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/tlc.py Log: framestack was an artifact introduced in the oo-jit branch to avoid recursive calls. Remove it, as it's not needed anymore Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/tl/tlc.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/tl/tlc.py Mon May 25 15:03:40 2009 @@ -225,16 +225,11 @@ 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', 'framestack']) + reds = ['frame', '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)) @@ -246,13 +241,12 @@ def interp_eval(code, pc, args, pool): assert isinstance(pc, int) - framestack = Framestack() frame = Frame(args, pc) pc = frame.pc while pc < len(code): if jitted: - myjitdriver.jit_merge_point(frame=frame, framestack=framestack, + myjitdriver.jit_merge_point(frame=frame, code=code, pc=pc, pool=pool) opcode = ord(code[pc]) pc += 1 @@ -355,7 +349,6 @@ pc += 1 if jitted and old_pc > pc: myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, - framestack=framestack, pool=pool) elif opcode == BR_COND: @@ -365,7 +358,6 @@ pc += char2int(code[pc]) + 1 if jitted and old_pc > pc: myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, - framestack=framestack, pool=pool) else: pc += 1 @@ -377,31 +369,19 @@ pc += offset if jitted and old_pc > pc: 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 - frame.pc = pc - framestack.s.append(frame) - frame = Frame([zero], pc + offset) - pc = frame.pc - - elif opcode == RETURN: - if not framestack.s: - break - if stack: - res = stack.pop() - else: - res = None - frame = framestack.s.pop() - stack = frame.stack - pc = frame.pc + res = interp_eval(code, pc + offset, [zero], pool) if res: stack.append(res) + elif opcode == RETURN: + break + elif opcode == PUSHARG: stack.append(frame.args[0]) @@ -444,10 +424,9 @@ meth_args[num_args] = stack.pop() a = meth_args[0] meth_pc = a.send(name) - frame.pc = pc - framestack.s.append(frame) - frame = Frame(meth_args, meth_pc) - pc = meth_pc + res = interp_eval(code, meth_pc, meth_args, pool) + if res: + stack.append(res) elif opcode == PRINT: if not we_are_translated(): @@ -464,7 +443,10 @@ else: raise RuntimeError("unknown opcode: " + str(opcode)) - return frame.stack[-1] + if frame.stack: + return frame.stack[-1] + else: + return None return interp, interp_eval From cfbolz at codespeak.net Mon May 25 17:22:31 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 May 2009 17:22:31 +0200 (CEST) Subject: [pypy-svn] r65412 - in pypy/branch/tagged-pointers-framework/pypy: config rpython/lltypesystem rpython/lltypesystem/test rpython/memory/test Message-ID: <20090525152231.A2BCA169F14@codespeak.net> Author: cfbolz Date: Mon May 25 17:22:29 2009 New Revision: 65412 Modified: pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py pypy/branch/tagged-pointers-framework/pypy/config/translationoption.py pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rclass.py pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py Log: Add a translation config option to use pointer tagging. This should make it possible for e.g. the Smalltalk VM to make pointer tagging a translate.py (as it is not really natural there to have to different classes as in the Python interpreter). Modified: pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py Mon May 25 17:22:29 2009 @@ -186,7 +186,8 @@ BoolOption("withsmallint", "use tagged integers", default=False, - requires=[("objspace.std.withprebuiltint", False)]), + requires=[("objspace.std.withprebuiltint", False), + ("translation.taggedpointers", True)]), BoolOption("withprebuiltint", "prebuild commonly used int objects", default=False), Modified: pypy/branch/tagged-pointers-framework/pypy/config/translationoption.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/config/translationoption.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/config/translationoption.py Mon May 25 17:22:29 2009 @@ -162,6 +162,10 @@ IntOption("withsmallfuncsets", "Represent groups of less funtions than this as indices into an array", default=0), + BoolOption("taggedpointers", + "When true, enable the use of tagged pointers. " + "If false, use normal boxing", + default=False), # options for ootype OptionDescription("ootype", "Object Oriented Typesystem options", [ Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rclass.py Mon May 25 17:22:29 2009 @@ -619,17 +619,19 @@ Constant(False)).value virtualizable2 = classdef.classdesc.read_attribute('_virtualizable2_', Constant(False)).value + config = rtyper.annotator.translator.config + usetagging = len(unboxed) != 0 and config.translation.taggedpointers if virtualizable: - assert len(unboxed) == 0 + assert not usetagging assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rvirtualizable return rvirtualizable.VirtualizableInstanceRepr(rtyper, classdef) elif virtualizable2: - assert len(unboxed) == 0 + assert not usetagging assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rvirtualizable2 return rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) - elif len(unboxed) == 0: + elif not usetagging: return InstanceRepr(rtyper, classdef, gcflavor) else: # the UnboxedValue class and its parent classes need a Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py Mon May 25 17:22:29 2009 @@ -33,20 +33,20 @@ def test_instantiate(): def fn1(n): return C(n) - res = interpret(fn1, [42]) + res = interpret(fn1, [42], taggedpointers=True) value = lltype.cast_ptr_to_int(res) assert value == 42 * 2 + 1 # for now def test_attribute(): def fn1(n): return C(n).smallint - res = interpret(fn1, [42]) + res = interpret(fn1, [42], taggedpointers=True) assert res == 42 def test_getvalue(): def fn1(n): return C(n).getvalue() - res = interpret(fn1, [42]) + res = interpret(fn1, [42], taggedpointers=True) assert res == 42 def test_overflowerror(): @@ -65,11 +65,11 @@ else: return 'A', 0 - res = interpret(fn2, [-117]) + res = interpret(fn2, [-117], taggedpointers=True) assert res.item0 == 'C' assert res.item1 == -117 - res = interpret(fn2, [sys.maxint]) + res = interpret(fn2, [sys.maxint], taggedpointers=True) assert res.item0 == 'B' assert res.item1 == sys.maxint @@ -95,13 +95,13 @@ else: return 'A', 0 - res = interpret(fn, [12]) + res = interpret(fn, [12], taggedpointers=True) assert res.item0 == 'C' assert res.item1 == 12 - res = interpret(fn, [-1]) + res = interpret(fn, [-1], taggedpointers=True) assert res.item0 == 'C' assert res.item1 == 111 - res = interpret(fn, [0]) + res = interpret(fn, [0], taggedpointers=True) assert res.item0 == 'B' assert res.item1 == 939393 @@ -118,9 +118,9 @@ x = C(n) return g(x) - res = interpret(fn, [-1]) + res = interpret(fn, [-1], taggedpointers=True) assert res == sys.maxint - res = interpret(fn, [56]) + res = interpret(fn, [56], taggedpointers=True) assert res == 56 def test_type(): @@ -131,9 +131,9 @@ x = C(n) return type(x) is B, type(x) is C - res = interpret(fn, [-212]) + res = interpret(fn, [-212], taggedpointers=True) assert res.item0 and not res.item1 - res = interpret(fn, [9874]) + res = interpret(fn, [9874], taggedpointers=True) assert res.item1 and not res.item0 def test_str(): @@ -143,9 +143,9 @@ else: x = C(n) return str(x) - res = interpret(fn, [-832]) + res = interpret(fn, [-832], taggedpointers=True) assert ''.join(res.chars) == '' - res = interpret(fn, [1]) + res = interpret(fn, [1], taggedpointers=True) assert ''.join(res.chars).startswith('' - res = interpret(fn, [1]) + res = interpret(fn, [1], taggedpointers=True) assert ''.join(res.chars).startswith(' Author: cfbolz Date: Mon May 25 17:26:28 2009 New Revision: 65413 Modified: pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_boehm.py pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_newgc.py Log: Fix translating tagging tests to use the new option. Modified: pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_boehm.py Mon May 25 17:26:28 2009 @@ -24,7 +24,7 @@ self._cleanups.pop()() def getcompiled(self, func, argstypelist = [], - annotatorpolicy=None): + annotatorpolicy=None, **extraconfigopts): from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy @@ -32,6 +32,7 @@ if self.stacklessgc: config.translation.gcrootfinder = "stackless" config.translation.simplifying = True + config.set(**extraconfigopts) t = TranslationContext(config=config) self.t = t a = t.buildannotator(policy=annotatorpolicy) Modified: pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_newgc.py Mon May 25 17:26:28 2009 @@ -15,6 +15,7 @@ from pypy.rlib.rstring import StringBuilder, UnicodeBuilder from pypy import conftest from pypy.tool.udir import udir +from pypy.rlib import rgc def compile_func(fn, inputtypes, t=None, gcpolicy="ref"): from pypy.config.pypyoption import get_pypy_config @@ -584,7 +585,6 @@ def test_weakref(self): import weakref - from pypy.rlib import rgc class A: pass @@ -620,7 +620,6 @@ def test_prebuilt_weakref(self): import weakref - from pypy.rlib import rgc class A: pass a = A() @@ -844,7 +843,6 @@ from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint from pypy.rpython.lltypesystem import rffi, ll2ctypes - from pypy.rlib import rgc import gc slong = cast_type_to_ffitype(rffi.LONG) @@ -891,7 +889,6 @@ assert c_fn() == 1 def test_can_move(self): - from pypy.rlib import rgc class A: pass def fn(): @@ -904,7 +901,6 @@ TP = lltype.GcArray(lltype.Char) def func(): try: - from pypy.rlib import rgc a = rgc.malloc_nonmovable(TP, 3) rgc.collect() if a: @@ -920,7 +916,6 @@ def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr - from pypy.rlib import rgc def f(): ptr = rgc.resizable_buffer_of_shape(STR, 2) @@ -932,6 +927,45 @@ run = self.getcompiled(f) assert run() == True + def test_tagged(self): + class Unrelated(object): + pass + + u = Unrelated() + u.x = UnboxedObject(47) + def fn(n): + rgc.collect() # check that a prebuilt tagged pointer doesn't explode + if n > 0: + x = BoxedObject(n) + else: + x = UnboxedObject(n) + u.x = x # invoke write barrier + rgc.collect() + return x.meth(100) + def func(): + return fn(1000) + fn(-1000) + func = self.getcompiled(func, taggedpointers=True) + res = func() + assert res == fn(1000) + fn(-1000) + +from pypy.rlib.objectmodel import UnboxedValue + +class TaggedBase(object): + __slots__ = () + def meth(self, x): + raise NotImplementedError + +class BoxedObject(TaggedBase): + attrvalue = 66 + def __init__(self, normalint): + self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + +class UnboxedObject(TaggedBase, UnboxedValue): + __slots__ = 'smallint' + def meth(self, x): + return self.smallint + x + 3 class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTests): gcpolicy = "semispace" should_be_moving = True @@ -975,7 +1009,6 @@ def fn(): # the semispace size starts at 8MB for now, so setting a # smaller limit has no effect - from pypy.rlib import rgc rgc.set_max_heap_size(20000000) # almost 20 MB s1 = s2 = s3 = None try: From cfbolz at codespeak.net Mon May 25 17:39:36 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 May 2009 17:39:36 +0200 (CEST) Subject: [pypy-svn] r65414 - pypy/branch/tagged-pointers-framework/pypy/rlib Message-ID: <20090525153936.37004169F2E@codespeak.net> Author: cfbolz Date: Mon May 25 17:39:35 2009 New Revision: 65414 Modified: pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py Log: update comment Modified: pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py Mon May 25 17:39:35 2009 @@ -227,7 +227,8 @@ class UnboxedValue(object): """A mixin class to use for classes that have exactly one field which - is an integer. They are represented as a tagged pointer.""" + is an integer. They are represented as a tagged pointer, if the + translation.taggedpointers config option is used.""" _mixin_ = True def __new__(cls, value): From cfbolz at codespeak.net Mon May 25 17:44:47 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 May 2009 17:44:47 +0200 (CEST) Subject: [pypy-svn] r65415 - in pypy/branch/tagged-pointers-framework/pypy: rlib rpython/lltypesystem rpython/lltypesystem/test Message-ID: <20090525154447.180141684EF@codespeak.net> Author: cfbolz Date: Mon May 25 17:44:47 2009 New Revision: 65415 Modified: pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py Log: Rename the very generic method name "getvalue" to get_untagged_value. So far it's not really used much anyway, only in tests. Modified: pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py Mon May 25 17:44:47 2009 @@ -248,9 +248,9 @@ raise OverflowError("UnboxedValue: argument out of range") def __repr__(self): - return '' % (self.getvalue(),) + return '' % (self.get_untagged_value(),) - def getvalue(self): # helper, equivalent to reading the custom field + def get_untagged_value(self): # helper, equivalent to reading the custom field if isinstance(self.__class__.__slots__, str): return getattr(self, self.__class__.__slots__) else: Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py Mon May 25 17:44:47 2009 @@ -53,7 +53,7 @@ def convert_const_exact(self, value): self.setup() - number = value.getvalue() + number = value.get_untagged_value() return ll_int_to_unboxed(self.lowleveltype, number) def getvalue_from_unboxed(self, llops, vinst): Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py Mon May 25 17:44:47 2009 @@ -43,9 +43,9 @@ res = interpret(fn1, [42], taggedpointers=True) assert res == 42 -def test_getvalue(): +def test_get_untagged_value(): def fn1(n): - return C(n).getvalue() + return C(n).get_untagged_value() res = interpret(fn1, [42], taggedpointers=True) assert res == 42 From benjamin at codespeak.net Tue May 26 02:01:28 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Tue, 26 May 2009 02:01:28 +0200 (CEST) Subject: [pypy-svn] r65416 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526000128.256A8169E9F@codespeak.net> Author: benjamin Date: Tue May 26 02:01:26 2009 New Revision: 65416 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: change optimize methods to return True to remove the operation Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 02:01:26 2009 @@ -119,12 +119,12 @@ self.additional_setarrayitems = {} newoperations = [] for op in self.loop.operations: - newop = op + remove_op = False for opt in self.optimizations[op.opnum]: - newop = opt(op, self) - if newop is None: + remove_op = opt(op, self) + if remove_op: break - if newop is None: + if remove_op: continue if op.is_guard(): op = self.optimize_guard(op) @@ -161,9 +161,9 @@ def optimize_guard_class(op, spec): instnode = spec.getnode(op.args[0]) if instnode.cls is not None: - return None + return True instnode.cls = op.args[1] - return op + return False class SimpleVirtualizableOpt(object): @staticmethod @@ -171,61 +171,61 @@ instnode = spec.getnode(op.args[0]) instnode.virtualized = True instnode.vdesc = op.vdesc - return None + return True @staticmethod def optimize_getfield_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.virtualized: - return op + return False field = op.descr if field not in instnode.vdesc.virtuals: - return op + return False node = instnode.cleanfields.get(field, None) if node is not None: spec.nodes[op.result] = node - return None + return True node = spec.getnode(op.result) node.possibly_virtualized_list = True instnode.cleanfields[field] = node - return op + return False @staticmethod def optimize_setfield_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.virtualized: - return op + return False field = op.descr if field not in instnode.vdesc.virtuals: - return op + return False node = spec.getnode(op.args[1]) instnode.cleanfields[field] = node # we never set it here d = spec.additional_stores.setdefault(instnode, {}) d[field] = node - return None + return True @staticmethod def optimize_getarrayitem_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.possibly_virtualized_list: - return op + return False if not spec.getnode(op.args[1]).const: raise VirtualizedListAccessedWithVariableArg() field = spec.getnode(op.args[1]).source node = instnode.cleanfields.get(field, None) if node is not None: spec.nodes[op.result] = node - return None + return True node = spec.getnode(op.result) instnode.cleanfields[field] = node - return op + return False @staticmethod def optimize_setarrayitem_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.possibly_virtualized_list: - return op + return False argnode = spec.getnode(op.args[1]) if not argnode.const: raise VirtualizedListAccessedWithVariableArg() @@ -234,7 +234,7 @@ instnode.cleanfields[field] = fieldnode d = spec.additional_setarrayitems.setdefault(instnode, {}) d[field] = (fieldnode, op.descr) - return None + return True specializer = Specializer([SimpleVirtualizableOpt(), ConsecutiveGuardClassRemoval()]) From fijal at codespeak.net Tue May 26 04:13:59 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 04:13:59 +0200 (CEST) Subject: [pypy-svn] r65417 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090526021359.5CD9B169F10@codespeak.net> Author: fijal Date: Tue May 26 04:13:56 2009 New Revision: 65417 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a test and a fix that not all guards can be constant folded away only based on their args Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 04:13:56 2009 @@ -90,11 +90,12 @@ return newboxes def optimize_guard(self, op): - for arg in op.args: - if not self.getnode(arg).const: - break - else: - return None + if op.is_foldable_guard(): + for arg in op.args: + if not self.getnode(arg).const: + break + else: + return None assert len(op.suboperations) == 1 op_fail = op.suboperations[0] op_fail.args = self.new_arguments(op_fail) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/resoperation.py Tue May 26 04:13:56 2009 @@ -64,6 +64,9 @@ def is_guard(self): return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST + def is_foldable_guard(self): + return rop._GUARD_FOLDABLE_FIRST <= self.opnum <= rop._GUARD_FOLDABLE_LAST + def is_guard_exception(self): return (self.opnum == rop.GUARD_EXCEPTION or self.opnum == rop.GUARD_NO_EXCEPTION) @@ -98,10 +101,12 @@ _FINAL_LAST = 3 _GUARD_FIRST = 8 # ----- start of guard operations ----- + _GUARD_FOLDABLE_FIRST = 8 GUARD_TRUE = 8 GUARD_FALSE = 9 GUARD_VALUE = 10 GUARD_CLASS = 11 + _GUARD_FOLDABLE_LAST = 11 GUARD_NONVIRTUALIZED = 12 GUARD_NO_EXCEPTION = 13 GUARD_EXCEPTION = 14 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 26 04:13:56 2009 @@ -199,6 +199,14 @@ expected = "[]" self.assert_equal(self.optimize(pre_op, []), expected) + def test_don_t_fold_guard_no_exception(self): + pre_op = """ + [] + guard_no_exception() + fail() + """ + self.assert_equal(self.optimize(pre_op, []), pre_op) + def test_virtualized_list_on_virtualizable(self): pre_op = """ [p0] From fijal at codespeak.net Tue May 26 05:29:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 05:29:08 +0200 (CEST) Subject: [pypy-svn] r65418 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090526032908.D7DA3169F3A@codespeak.net> Author: fijal Date: Tue May 26 05:29:06 2009 New Revision: 65418 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a passing test Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 26 05:29:06 2009 @@ -245,8 +245,6 @@ fail() """ pre_op = parse(pre_op, self.cpu, self.namespace) - # cheat - pre_op.operations[-2].result.value = 1 expected = """ [p0, i0] p1 = getfield_gc(p0, descr=list_desc) @@ -259,6 +257,34 @@ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), expected) + def test_virtualized_list_on_virtualizable_3(self): + pre_op = """ + [p0, i0, i1] + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + p1 = getfield_gc(p0, descr=list_desc) + setarrayitem_gc(p1, 0, i0, descr=array_descr) + i2 = getarrayitem_gc(p1, 0) + setarrayitem_gc(p1, 0, i1, descr=array_descr) + i3 = getarrayitem_gc(p1, 0) + i4 = int_add(i2, i3) + i5 = int_is_true(i4) + guard_true(i5) + fail() + """ + pre_op = parse(pre_op, self.cpu, self.namespace) + expected = """ + [p0, i0, i1] + p1 = getfield_gc(p0, descr=list_desc) + i4 = int_add(i0, i1) + i5 = int_is_true(i4) + guard_true(i5) + setarrayitem_gc(p1, 0, i1, descr=array_descr) + fail() + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), + expected) + def test_remove_consecutive_guard_value_constfold(self): py.test.skip("not yet") n = BoxInt(0) From fijal at codespeak.net Tue May 26 05:37:32 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 05:37:32 +0200 (CEST) Subject: [pypy-svn] r65419 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526033732.011AB169F49@codespeak.net> Author: fijal Date: Tue May 26 05:37:32 2009 New Revision: 65419 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: Leave a comment what to do next Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 05:37:32 2009 @@ -2,7 +2,12 @@ """ Simplified optimize.py """ from pypy.jit.metainterp.resoperation import rop, ResOperation, opname -from pypy.jit.metainterp.history import Const, Box +from pypy.jit.metainterp.history import Const, Box, ConstInt + +# For anybody reading. +# Next step is to fix this so cleanfields and dicts on specializer +# (additional_*) would be r_dicts so they can consider +# two different constants as the same. class VirtualizedListAccessedWithVariableArg(Exception): pass @@ -110,7 +115,7 @@ for field, (fieldnode, descr) in d.iteritems(): box = fieldnode.source op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, - [node.source, field, box], None, descr)) + [node.source, field, box], None, descr)) op.suboperations.append(op_fail) op.args = self.new_arguments(op) return op From cfbolz at codespeak.net Tue May 26 15:10:35 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 May 2009 15:10:35 +0200 (CEST) Subject: [pypy-svn] r65420 - pypy/branch/tagged-pointers-framework/pypy/lang/prolog/interpreter Message-ID: <20090526131035.A81A9168569@codespeak.net> Author: cfbolz Date: Tue May 26 15:10:34 2009 New Revision: 65420 Modified: pypy/branch/tagged-pointers-framework/pypy/lang/prolog/interpreter/term.py Log: make it possible to use tagged pointers in the prolog implementation. Modified: pypy/branch/tagged-pointers-framework/pypy/lang/prolog/interpreter/term.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/lang/prolog/interpreter/term.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/lang/prolog/interpreter/term.py Tue May 26 15:10:34 2009 @@ -25,10 +25,6 @@ __slots__ = () _immutable_ = True - def __init__(self): - raise NotImplementedError("abstract base class") - return self - def getvalue(self, heap): return self @@ -269,12 +265,11 @@ error.throw_type_error("evaluable", self.get_prolog_signature()) -class Number(NonVar): +class Number(NonVar, UnboxedValue): TAG = tag() STANDARD_ORDER = 2 _immutable_ = True - def __init__(self, num): - self.num = num + __slots__ = ("num", ) @specialize.arg(3) def basic_unify(self, other, heap, occurs_check=False): From antocuni at codespeak.net Tue May 26 16:08:40 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 26 May 2009 16:08:40 +0200 (CEST) Subject: [pypy-svn] r65421 - pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template Message-ID: <20090526140840.4CD21169E19@codespeak.net> Author: antocuni Date: Tue May 26 16:08:37 2009 New Revision: 65421 Modified: pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/class_.py Log: skip this test, as it cannot really work after translation Modified: pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/class_.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/class_.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/oosupport/test_template/class_.py Tue May 26 16:08:37 2009 @@ -64,5 +64,8 @@ return a.x + b.x assert self.interpret(fn, [1, 2]) == 3 + def test_cast_object_mix_null(self): + py.test.skip('cannot return ootype.NULL from translated functions') + class BaseTestSpecialcase(BaseTestRspecialcase): pass From cfbolz at codespeak.net Tue May 26 17:40:47 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 May 2009 17:40:47 +0200 (CEST) Subject: [pypy-svn] r65422 - in pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem: . test Message-ID: <20090526154047.3C5BA169DFC@codespeak.net> Author: cfbolz Date: Tue May 26 17:40:45 2009 New Revision: 65422 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py Log: waaaaaa, how could this ever have worked? type(x) where x=None but x could also be a tagged pointer segfaulted so far. Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py Tue May 26 17:40:45 2009 @@ -1,7 +1,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython.rclass import getclassrepr, getinstancerepr, get_type_repr from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE +from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE, ll_inst_type from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute from pypy.rpython.lltypesystem.rclass import ll_issubclass_const from pypy.rpython.rmodel import TyperError, inputconst @@ -62,7 +62,7 @@ c_one = inputconst(lltype.Signed, 1) return llops.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed) - def gettype_from_unboxed(self, llops, vinst): + def gettype_from_unboxed(self, llops, vinst, can_be_none=False): unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) if self.is_parent: @@ -81,8 +81,12 @@ vinst = llops.genop('cast_pointer', [vinst], resulttype=self.common_repr()) if can_be_tagged: + # XXX do we care about optimizing the case where vinst cannot + # be None here? return llops.gendirectcall(ll_unboxed_getclass, vinst, cunboxedcls) + elif can_be_none: + return llops.gendirectcall(ll_inst_type, vinst) else: ctypeptr = inputconst(lltype.Void, 'typeptr') return llops.genop('getfield', [vinst, ctypeptr], @@ -100,7 +104,8 @@ def rtype_type(self, hop): [vinst] = hop.inputargs(self) - return self.gettype_from_unboxed(hop.llops, vinst) + return self.gettype_from_unboxed( + hop.llops, vinst, can_be_none=hop.args_s[0].can_be_none()) def rtype_setattr(self, hop): # only for UnboxedValue.__init__(), which is not actually called @@ -144,8 +149,10 @@ def ll_unboxed_getclass(instance, class_if_unboxed): if lltype.cast_ptr_to_int(instance) & 1: return class_if_unboxed - else: + elif instance: return instance.typeptr + else: + return lltype.nullptr(lltype.typeOf(instance).TO.typeptr.TO) def ll_unboxed_isinstance_const(obj, minid, maxid, answer_if_unboxed): if not obj: Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py Tue May 26 17:40:45 2009 @@ -136,6 +136,27 @@ res = interpret(fn, [9874], taggedpointers=True) assert res.item1 and not res.item0 +def test_type_of_None(): + # use extra function to prevent flow graph cleverness + def g(n): + if n < 0: + x = B(n) + elif n == 0: + x = None + else: + x = C(n) + return x + def fn(n): + x= g(n) + return type(x) is B, type(x) is C + + res = interpret(fn, [-212], taggedpointers=True) + assert res.item0 and not res.item1 + res = interpret(fn, [9874], taggedpointers=True) + assert res.item1 and not res.item0 + res = interpret(fn, [0], taggedpointers=True) + assert not res.item1 and not res.item0 + def test_str(): def fn(n): if n > 0: From fijal at codespeak.net Tue May 26 17:47:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 17:47:56 +0200 (CEST) Subject: [pypy-svn] r65423 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526154756.352BE169DFA@codespeak.net> Author: fijal Date: Tue May 26 17:47:55 2009 New Revision: 65423 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: Attempt to fix the issue with different constants with the same value. Store different dicts for arrays and structs Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 17:47:55 2009 @@ -20,7 +20,7 @@ self.const = const self.cls = None self.cleanfields = {} - self.dirtyfields = {} + self.arrayfields = {} self.virtualized = False self.possibly_virtualized_list = False @@ -115,7 +115,7 @@ for field, (fieldnode, descr) in d.iteritems(): box = fieldnode.source op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, - [node.source, field, box], None, descr)) + [node.source, ConstInt(field), box], None, descr)) op.suboperations.append(op_fail) op.args = self.new_arguments(op) return op @@ -218,13 +218,13 @@ return False if not spec.getnode(op.args[1]).const: raise VirtualizedListAccessedWithVariableArg() - field = spec.getnode(op.args[1]).source - node = instnode.cleanfields.get(field, None) + field = spec.getnode(op.args[1]).source.getint() + node = instnode.arrayfields.get(field, None) if node is not None: spec.nodes[op.result] = node return True node = spec.getnode(op.result) - instnode.cleanfields[field] = node + instnode.arrayfields[field] = node return False @staticmethod @@ -236,8 +236,8 @@ if not argnode.const: raise VirtualizedListAccessedWithVariableArg() fieldnode = spec.getnode(op.args[2]) - field = argnode.source - instnode.cleanfields[field] = fieldnode + field = argnode.source.getint() + instnode.arrayfields[field] = fieldnode d = spec.additional_setarrayitems.setdefault(instnode, {}) d[field] = (fieldnode, op.descr) return True From fijal at codespeak.net Tue May 26 18:52:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 18:52:21 +0200 (CEST) Subject: [pypy-svn] r65424 - pypy/branch/pyjitpl5-experiments/pypy/interpreter Message-ID: <20090526165221.69A3116857F@codespeak.net> Author: fijal Date: Tue May 26 18:52:20 2009 New Revision: 65424 Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py Log: promote valuestackdepth everywhere. if we don't we cannot perform optimizations Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py Tue May 26 18:52:20 2009 @@ -131,14 +131,14 @@ def pushvalue(self, w_object): depth = self.valuestackdepth self.valuestack_w[depth] = w_object - self.valuestackdepth = depth + 1 + self.valuestackdepth = hint(depth + 1, promote=True) def popvalue(self): depth = self.valuestackdepth - 1 assert depth >= 0, "pop from empty value stack" w_object = self.valuestack_w[depth] self.valuestack_w[depth] = None - self.valuestackdepth = depth + self.valuestackdepth = hint(depth, promote=True) return w_object def popstrdictvalues(self, n): @@ -188,7 +188,7 @@ if n < 0: break self.valuestack_w[finaldepth+n] = None - self.valuestackdepth = finaldepth + self.valuestackdepth = hint(finaldepth, promote=True) def pushrevvalues(self, n, values_w): # n should be len(values_w) while True: @@ -221,7 +221,7 @@ while depth >= finaldepth: self.valuestack_w[depth] = None depth -= 1 - self.valuestackdepth = finaldepth + self.valuestackdepth = hint(finaldepth, promote=True) def savevaluestack(self): return self.valuestack_w[:self.valuestackdepth] From antocuni at codespeak.net Tue May 26 20:06:46 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 26 May 2009 20:06:46 +0200 (CEST) Subject: [pypy-svn] r65425 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526180646.CE819169E19@codespeak.net> Author: antocuni Date: Tue May 26 20:06:38 2009 New Revision: 65425 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py Log: make a better repr for static methods Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py Tue May 26 20:06:38 2009 @@ -48,6 +48,8 @@ try: if box.value.obj._TYPE is ootype.String: return '(%r)' % box.value.obj._str + if isinstance(box.value.obj._TYPE, ootype.StaticMethod): + return '(%r)' % box.value.obj if isinstance(box.value.obj, ootype._view): return repr(box.value.obj._inst._TYPE) else: From antocuni at codespeak.net Tue May 26 20:07:06 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 26 May 2009 20:07:06 +0200 (CEST) Subject: [pypy-svn] r65426 - pypy/branch/pyjitpl5-experiments/pypy/jit/tl Message-ID: <20090526180706.B0CB0169E25@codespeak.net> Author: antocuni Date: Tue May 26 20:07:05 2009 New Revision: 65426 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_child.py Log: use optimize2 by default Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_child.py Tue May 26 20:07:05 2009 @@ -2,7 +2,8 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp import warmspot #from pypy.jit.metainterp.simple_optimize import Optimizer -from pypy.jit.metainterp import optimize as Optimizer +#from pypy.jit.metainterp import optimize as Optimizer +from pypy.jit.metainterp.optimize2 import Optimizer from pypy.module.pypyjit.policy import PyPyJitPolicy # Current output: http://paste.pocoo.org/show/106540/ From fijal at codespeak.net Tue May 26 20:16:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 20:16:20 +0200 (CEST) Subject: [pypy-svn] r65427 - pypy/branch/pyjitpl5-experiments/pypy/jit/tl Message-ID: <20090526181620.3862C169EC9@codespeak.net> Author: fijal Date: Tue May 26 20:16:17 2009 New Revision: 65427 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py Log: a currently exploding loop Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py Tue May 26 20:16:17 2009 @@ -13,10 +13,17 @@ i = i + step print i +def g(i): + for k in range(i, i +2): + pass + +def loop(): + for i in range(10000): + g(i) try: #do() - simple_loop() + loop() print "---ending 2---" except BaseException, e: print "---ending 0---" From fijal at codespeak.net Tue May 26 20:27:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 20:27:54 +0200 (CEST) Subject: [pypy-svn] r65428 - pypy/branch/pyjitpl5-experiments/pypy/jit/tl Message-ID: <20090526182754.6C257169E84@codespeak.net> Author: fijal Date: Tue May 26 20:27:52 2009 New Revision: 65428 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py Log: a test checkin Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py Tue May 26 20:27:52 2009 @@ -1,5 +1,6 @@ TESTNAME = 'test_builtin' + def do(): __import__('test.' + TESTNAME) print "---ending 1---" From fijal at codespeak.net Tue May 26 20:49:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 20:49:08 +0200 (CEST) Subject: [pypy-svn] r65429 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090526184908.90C89169E83@codespeak.net> Author: fijal Date: Tue May 26 20:49:08 2009 New Revision: 65429 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: put some extra guards on a rebuild path. backend will kill them away anyway and we can deduce what kind of operations those are. We have no way of passing this kind of information some other way so far Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 20:49:08 2009 @@ -22,7 +22,7 @@ self.cleanfields = {} self.arrayfields = {} self.virtualized = False - self.possibly_virtualized_list = False + self.vdesc = None def __repr__(self): flags = '' @@ -109,11 +109,19 @@ op.suboperations = [] for node, d in self.additional_stores.iteritems(): for field, fieldnode in d.iteritems(): + gop = ResOperation(rop.GUARD_NONVIRTUALIZED, + [node.source], None) + gop.vdesc = node.vdesc + op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETFIELD_GC, [node.source, fieldnode.source], None, field)) for node, d in self.additional_setarrayitems.iteritems(): for field, (fieldnode, descr) in d.iteritems(): box = fieldnode.source + gop = ResOperation(rop.GUARD_NONVIRTUALIZED, + [node.source], None) + gop.vdesc = node.vdesc + op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, [node.source, ConstInt(field), box], None, descr)) op.suboperations.append(op_fail) @@ -192,7 +200,7 @@ spec.nodes[op.result] = node return True node = spec.getnode(op.result) - node.possibly_virtualized_list = True + node.virtualized = True instnode.cleanfields[field] = node return False @@ -214,7 +222,7 @@ @staticmethod def optimize_getarrayitem_gc(op, spec): instnode = spec.getnode(op.args[0]) - if not instnode.possibly_virtualized_list: + if not instnode.virtualized: return False if not spec.getnode(op.args[1]).const: raise VirtualizedListAccessedWithVariableArg() @@ -230,7 +238,7 @@ @staticmethod def optimize_setarrayitem_gc(op, spec): instnode = spec.getnode(op.args[0]) - if not instnode.possibly_virtualized_list: + if not instnode.virtualized: return False argnode = spec.getnode(op.args[1]) if not argnode.const: Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 26 20:49:08 2009 @@ -184,6 +184,7 @@ i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=other_field_desc) guard_true(i2) + guard_nonvirtualized(p0) setfield_gc(p0, i2, descr=field_desc) fail() """ @@ -251,6 +252,7 @@ i2 = int_add(i0, i0) i3 = int_is_true(i2) guard_true(i3) + guard_nonvirtualized(p1) setarrayitem_gc(p1, 0, i0, descr=array_descr) fail() """ @@ -279,6 +281,7 @@ i4 = int_add(i0, i1) i5 = int_is_true(i4) guard_true(i5) + guard_nonvirtualized(p1) setarrayitem_gc(p1, 0, i1, descr=array_descr) fail() """ From fijal at codespeak.net Tue May 26 20:52:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 20:52:51 +0200 (CEST) Subject: [pypy-svn] r65430 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526185251.F1F04169EB8@codespeak.net> Author: fijal Date: Tue May 26 20:52:51 2009 New Revision: 65430 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: append a dummy suboperations to that GUARD Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 20:52:51 2009 @@ -112,6 +112,7 @@ gop = ResOperation(rop.GUARD_NONVIRTUALIZED, [node.source], None) gop.vdesc = node.vdesc + gop.suboperations = [ResOperation(rop.FAIL, [], None)] op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETFIELD_GC, [node.source, fieldnode.source], None, field)) @@ -120,6 +121,7 @@ box = fieldnode.source gop = ResOperation(rop.GUARD_NONVIRTUALIZED, [node.source], None) + gop.suboperations = [ResOperation(rop.FAIL, [], None)] gop.vdesc = node.vdesc op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, From antocuni at codespeak.net Tue May 26 21:04:22 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 26 May 2009 21:04:22 +0200 (CEST) Subject: [pypy-svn] r65431 - in pypy/branch/pyjitpl5-experiments/pypy: config jit/backend/cli jit/backend/cli/test jit/backend/test jit/metainterp/test rpython/ootypesystem translator/cli translator/cli/src translator/oosupport/test_template Message-ID: <20090526190422.951331684BF@codespeak.net> Author: antocuni Date: Tue May 26 21:04:20 2009 New Revision: 65431 Added: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_loop.py - copied unchanged from r65430, pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_loop.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_vlist.py - copied unchanged from r65430, pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_vlist.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_loop.py - copied unchanged from r65430, pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_loop.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py - copied unchanged from r65430, pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_virtualizable.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_vlist.py - copied unchanged from r65430, pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_zrpy_vlist.py Modified: pypy/branch/pyjitpl5-experiments/pypy/config/translationoption.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/methodfactory.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_basic.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_exception.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_send.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/support.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5-experiments/pypy/rpython/ootypesystem/rpbc.py pypy/branch/pyjitpl5-experiments/pypy/translator/cli/opcodes.py pypy/branch/pyjitpl5-experiments/pypy/translator/cli/src/pypylib.cs pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/test_template/class_.py Log: merge changes from pyjitpl5 to pyjitpl5-experiments svn merge svn+ssh://codespeak.net/svn/pypy/branch/pyjitpl5/pypy -r65302:HEAD ------------------------------------------------------------------------ r65304 | antocuni | 2009-05-19 10:31:13 +0200 (Tue, 19 May 2009) | 5 lines don't print stuff on stdout, as it breaks the minimal and cli backends (because the spawn an external process and read the result as printed on stdout) ------------------------------------------------------------------------ r65314 | antocuni | 2009-05-19 17:28:40 +0200 (Tue, 19 May 2009) | 7 lines implement bridges; so far the implementation is very simple, just a tailcall to the method containing the next loop; hopefully, the speed penalty associated to the tail call is not too heavy, because we don't expect bridges to be so frequent (thanks cfbolz for the idea). In the future, we might think of other techniques to avoid tail calls. ------------------------------------------------------------------------ r65331 | antocuni | 2009-05-20 16:21:28 +0200 (Wed, 20 May 2009) | 10 lines the code to implement bridges was broken, fix it: - don't put a 'ret' in emit_store_opargs, else the jump is never taken - put the array of failing ops on the cpu, not on the method, else the "failed_op" index stored in inputargs is meaningless - add a bunch of debugging stuff ------------------------------------------------------------------------ r65335 | antocuni | 2009-05-20 18:19:29 +0200 (Wed, 20 May 2009) | 3 lines update test status: two more tests pass, one fails only on mono but not on windows, another is not a translation test ------------------------------------------------------------------------ r65336 | antocuni | 2009-05-20 18:32:07 +0200 (Wed, 20 May 2009) | 3 lines good, all these tests pass now ------------------------------------------------------------------------ r65337 | antocuni | 2009-05-20 18:36:30 +0200 (Wed, 20 May 2009) | 4 lines more passing tests. test_int_lshift_ovf still fails because of a NotImplementedError (will investigate later) ------------------------------------------------------------------------ r65338 | antocuni | 2009-05-20 18:42:01 +0200 (Wed, 20 May 2009) | 2 lines implement set_overflow_error to make test_int_lshift_ovf passing ------------------------------------------------------------------------ r65339 | antocuni | 2009-05-20 18:51:57 +0200 (Wed, 20 May 2009) | 2 lines be explicit on which operation we don't expect in the cli backend. Only few "real" operations are left now ------------------------------------------------------------------------ r65341 | antocuni | 2009-05-21 10:06:38 +0200 (Thu, 21 May 2009) | 3 lines add new tests (to be run directly through Python for .NET); most of them pass, a bunch can be run only after translation, only one seems to be related to a real failure ------------------------------------------------------------------------ r65342 | antocuni | 2009-05-21 10:09:51 +0200 (Thu, 21 May 2009) | 2 lines I was wrong, this test also has no chances to pass without translation ------------------------------------------------------------------------ r65343 | antocuni | 2009-05-21 10:19:59 +0200 (Thu, 21 May 2009) | 2 lines more tests, most of them pass :-) ------------------------------------------------------------------------ r65344 | antocuni | 2009-05-21 11:46:23 +0200 (Thu, 21 May 2009) | 7 lines - add a new test to test_loop to test string operations - fix oosends to String and Unicode objects - test_loop_{string,unicode} pass ------------------------------------------------------------------------ r65345 | antocuni | 2009-05-21 12:39:34 +0200 (Thu, 21 May 2009) | 2 lines port more tests, implement do_oonewarray; test_simple_array passes ------------------------------------------------------------------------ r65346 | antocuni | 2009-05-21 13:55:06 +0200 (Thu, 21 May 2009) | 3 lines implement emit_op_new_arry, but comment it out as it cannot be tested without translation. ------------------------------------------------------------------------ r65347 | antocuni | 2009-05-21 14:05:47 +0200 (Thu, 21 May 2009) | 2 lines implement emit_op_new_arry to make almost all these tests passing ------------------------------------------------------------------------ r65348 | antocuni | 2009-05-21 14:12:41 +0200 (Thu, 21 May 2009) | 4 lines delay the call to get_concrete_calltable, so that the low level types of the methods arguments have been fully computed, much like r65288. test_ll_fixed_setitem_fast passes ------------------------------------------------------------------------ r65349 | antocuni | 2009-05-21 14:31:03 +0200 (Thu, 21 May 2009) | 2 lines port more tests, ignore 'promote_virtualizable' in the normal cli backend. ------------------------------------------------------------------------ r65350 | antocuni | 2009-05-21 14:50:55 +0200 (Thu, 21 May 2009) | 5 lines implement emit_op_instanceof, and all the remaining virtualizable tests pass. Moreover, add stubs for all the few still missing operations, so that we can kill the warning and put an assert instead ------------------------------------------------------------------------ r65351 | antocuni | 2009-05-21 21:51:06 +0200 (Thu, 21 May 2009) | 2 lines use "boehm" as a dummy value, else it conflicts with tl/pypyjit.py ------------------------------------------------------------------------ r65352 | antocuni | 2009-05-22 00:47:33 +0200 (Fri, 22 May 2009) | 3 lines implement sort_key() for all CLI descrs ------------------------------------------------------------------------ r65358 | antocuni | 2009-05-22 13:56:38 +0200 (Fri, 22 May 2009) | 2 lines these two tests pass also on ootype nowadays ------------------------------------------------------------------------ r65421 | antocuni | 2009-05-26 16:08:37 +0200 (Tue, 26 May 2009) | 2 lines skip this test, as it cannot really work after translation ------------------------------------------------------------------------ Modified: pypy/branch/pyjitpl5-experiments/pypy/config/translationoption.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/config/translationoption.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/config/translationoption.py Tue May 26 21:04:20 2009 @@ -30,7 +30,7 @@ ("translation.backendopt.heap2stack", False), ("translation.backendopt.clever_malloc_removal", False), ("translation.list_comprehension_operations", False), - ("translation.gc", "generation"), # it's not really used, but some jit code expects a value here + ("translation.gc", "boehm"), # it's not really used, but some jit code expects a value here ] }), ChoiceOption("backend", "Backend to use for code generation", Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py Tue May 26 21:04:20 2009 @@ -14,6 +14,7 @@ System = CLR.System OpCodes = System.Reflection.Emit.OpCodes LoopDelegate = CLR.pypy.runtime.LoopDelegate +DelegateHolder = CLR.pypy.runtime.DelegateHolder InputArgs = CLR.pypy.runtime.InputArgs cVoid = ootype.nullruntimeclass @@ -51,12 +52,40 @@ def store(self, meth): assert False, 'cannot store() to Constant' + def get_cliobj(self): + return dotnet.cast_to_native_object(self.getobj()) + class __extend__(ConstInt): __metaclass__ = extendabletype def load(self, meth): meth.il.Emit(OpCodes.Ldc_I4, self.value) + +class ConstFunction(Const): + + def __init__(self, name): + self.name = name + self.holder = DelegateHolder() + + def get_cliobj(self): + return dotnet.cliupcast(self.holder, System.Object) + + def load(self, meth): + holdertype = self.holder.GetType() + funcfield = holdertype.GetField('func') + Const.load(self, meth) + meth.il.Emit(OpCodes.Castclass, holdertype) + meth.il.Emit(OpCodes.Ldfld, funcfield) + meth.il.Emit(OpCodes.Castclass, dotnet.typeof(LoopDelegate)) + + def _getrepr_(self): + return '' % self.name + + def __hash__(self): + return hash(self.holder) + + class MethodArgument(AbstractValue): def __init__(self, index, cliType): self.index = index @@ -87,6 +116,7 @@ class Method(object): operations = [] # overwritten at the end of the module + tailcall = True debug = False def __init__(self, cpu, name, loop): @@ -94,7 +124,6 @@ self.name = name self.loop = loop self.boxes = {} # box --> local var - self.failing_ops = [] # index --> op self.branches = [] self.branchlabels = [] self.consts = {} # object --> index @@ -124,10 +153,12 @@ # initialize the array of genconsts consts = dotnet.new_array(System.Object, len(self.consts)) for av_const, i in self.consts.iteritems(): - consts[i] = dotnet.cast_to_native_object(av_const.getobj()) + #consts[i] = dotnet.cast_to_native_object(av_const.getobj()) + consts[i] = av_const.get_cliobj() # build the delegate func = self.meth_wrapper.create_delegate(delegatetype, consts) - self.func = dotnet.clidowncast(func, LoopDelegate) + func = dotnet.clidowncast(func, LoopDelegate) + self.loop._cli_funcbox.holder.SetFunc(func) def _get_meth_wrapper(self): restype = dotnet.class2type(cVoid) @@ -151,10 +182,10 @@ def get_index_for_failing_op(self, op): try: - return self.failing_ops.index(op) + return self.cpu.failing_ops.index(op) except ValueError: - self.failing_ops.append(op) - return len(self.failing_ops)-1 + self.cpu.failing_ops.append(op) + return len(self.cpu.failing_ops)-1 def get_index_for_constant(self, obj): try: @@ -199,6 +230,7 @@ self.il.Emit(OpCodes.Stelem, clitype) def emit_load_inputargs(self): + self.emit_debug("executing: " + self.name) i = 0 for box in self.loop.inputargs: self.load_inputarg(i, box.type, box.getCliType()) @@ -211,8 +243,7 @@ def emit_operations(self, operations): for op in operations: - if self.debug: - self.il.EmitWriteLine(op.repr()) + self.emit_debug(op.repr()) func = self.operations[op.opnum] assert func is not None func(self, op) @@ -246,6 +277,10 @@ def store_result(self, op): op.result.store(self) + def emit_debug(self, msg): + if self.debug: + self.il.EmitWriteLine(msg) + def emit_clear_exception(self): self.av_inputargs.load(self) self.il.Emit(OpCodes.Ldnull) @@ -282,12 +317,15 @@ self.il.Emit(OpCodes.Ldc_I4, index_op) field = dotnet.typeof(InputArgs).GetField('failed_op') self.il.Emit(OpCodes.Stfld, field) - # store the lates values + self.emit_store_opargs(op) + self.il.Emit(OpCodes.Ret) + + def emit_store_opargs(self, op): + # store the latest values i = 0 for box in op.args: self.store_inputarg(i, box.type, box.getCliType(), box) i+=1 - self.il.Emit(OpCodes.Ret) def emit_guard_bool(self, op, opcode): assert op.suboperations @@ -344,13 +382,24 @@ def emit_op_jump(self, op): target = op.jump_target - assert target is self.loop, 'TODO' assert len(op.args) == len(target.inputargs) - i = 0 - for i in range(len(op.args)): - op.args[i].load(self) - target.inputargs[i].store(self) - self.il.Emit(OpCodes.Br, self.il_loop_start) + if target is self.loop: + i = 0 + for i in range(len(op.args)): + op.args[i].load(self) + target.inputargs[i].store(self) + self.il.Emit(OpCodes.Br, self.il_loop_start) + else: + # it's a real bridge + self.emit_debug('jumping to ' + target.name) + self.emit_store_opargs(op) + target._cli_funcbox.load(self) + self.av_inputargs.load(self) + methinfo = dotnet.typeof(LoopDelegate).GetMethod('Invoke') + if self.tailcall: + self.il.Emit(OpCodes.Tailcall) + self.il.Emit(OpCodes.Callvirt, methinfo) + self.il.Emit(OpCodes.Ret) def emit_op_new_with_vtable(self, op): assert isinstance(op.args[0], ConstObj) # ignored, using the descr instead @@ -361,6 +410,19 @@ self.il.Emit(OpCodes.Newobj, ctor_info) self.store_result(op) + def emit_op_runtimenew(self, op): + raise NotImplementedError + + def emit_op_instanceof(self, op): + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + clitype = descr.get_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Isinst, clitype) + self.il.Emit(OpCodes.Ldnull) + self.il.Emit(OpCodes.Cgt_Un) + self.store_result(op) + def emit_op_ooidentityhash(self, op): raise NotImplementedError @@ -369,7 +431,8 @@ assert isinstance(descr, runner.StaticMethDescr) delegate_type = descr.get_delegate_clitype() meth_invoke = descr.get_meth_info() - self._emit_call(op, delegate_type, meth_invoke, descr.has_result) + self._emit_call(op, OpCodes.Callvirt, delegate_type, + meth_invoke, descr.has_result) def emit_op_call(self, op): emit_op = Method.emit_op_call_impl.im_func @@ -383,17 +446,18 @@ assert isinstance(descr, runner.MethDescr) clitype = descr.get_self_clitype() methinfo = descr.get_meth_info() - self._emit_call(op, clitype, methinfo, descr.has_result) + opcode = descr.get_call_opcode() + self._emit_call(op, opcode, clitype, methinfo, descr.has_result) emit_op_oosend_pure = emit_op_oosend - def _emit_call(self, op, clitype, methinfo, has_result): + def _emit_call(self, op, opcode, clitype, methinfo, has_result): av_sm, args_av = op.args[0], op.args[1:] av_sm.load(self) self.il.Emit(OpCodes.Castclass, clitype) for av_arg in args_av: av_arg.load(self) - self.il.Emit(OpCodes.Callvirt, methinfo) + self.il.Emit(opcode, methinfo) if has_result: self.store_result(op) @@ -451,25 +515,36 @@ self.il.Emit(OpCodes.Castclass, clitype) self.il.Emit(OpCodes.Ldlen) self.store_result(op) - - def not_implemented(self, op): + + def emit_op_new_array(self, op): + descr = op.descr + assert isinstance(descr, runner.TypeDescr) + item_clitype = descr.get_clitype() + op.args[0].load(self) + self.il.Emit(OpCodes.Newarr, item_clitype) + self.store_result(op) + + def emit_op_guard_nonvirtualized(self, op): + raise NotImplementedError + + def lltype_only(self, op): + print 'Operation %s is lltype specific, should not get here!' % op.getopname() raise NotImplementedError - emit_op_cast_int_to_ptr = not_implemented - emit_op_guard_nonvirtualized = not_implemented - emit_op_unicodelen = not_implemented - emit_op_setfield_raw = not_implemented - emit_op_cast_ptr_to_int = not_implemented - emit_op_newunicode = not_implemented - emit_op_new_array = not_implemented - emit_op_unicodegetitem = not_implemented - emit_op_strgetitem = not_implemented - emit_op_getfield_raw = not_implemented - emit_op_unicodesetitem = not_implemented - emit_op_getfield_raw_pure = not_implemented - emit_op_strlen = not_implemented - emit_op_newstr = not_implemented - emit_op_strsetitem = not_implemented + emit_op_new = lltype_only + emit_op_setfield_raw = lltype_only + emit_op_getfield_raw = lltype_only + emit_op_getfield_raw_pure = lltype_only + emit_op_strsetitem = lltype_only + emit_op_unicodesetitem = lltype_only + emit_op_cast_int_to_ptr = lltype_only + emit_op_cast_ptr_to_int = lltype_only + emit_op_newstr = lltype_only + emit_op_strlen = lltype_only + emit_op_strgetitem = lltype_only + emit_op_newunicode = lltype_only + emit_op_unicodelen = lltype_only + emit_op_unicodegetitem = lltype_only # -------------------------------------------------------------------- @@ -507,10 +582,7 @@ elif isinstance(instr, opcodes.PushArg): lines.append('self.push_arg(op, %d)' % instr.n) else: - if not isinstance(instr, str): - print 'WARNING: unknown instruction %s' % instr - return - + assert isinstance(instr, str), 'unknown instruction %s' % instr if instr.startswith('call '): signature = instr[len('call '):] renderCall(lines, signature) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/methodfactory.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/methodfactory.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/methodfactory.py Tue May 26 21:04:20 2009 @@ -71,7 +71,7 @@ def create_delegate(self, delegatetype, consts): t = self.typeBuilder.CreateType() methinfo = t.GetMethod("invoke") -## if self.name == 'generated_case_1': +## if self.name == 'Loop #0(r1)_2': ## assemblyData.auto_save_assembly.Save() return System.Delegate.CreateDelegate(delegatetype, consts, Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py Tue May 26 21:04:20 2009 @@ -1,6 +1,9 @@ +from pypy.tool.pairtype import extendabletype from pypy.rpython.ootypesystem import ootype +from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.history import AbstractDescr, AbstractMethDescr -from pypy.jit.metainterp.history import Box, BoxInt, BoxObj +from pypy.jit.metainterp.history import Box, BoxInt, BoxObj, ConstObj, Const +from pypy.jit.metainterp.history import TreeLoop from pypy.jit.metainterp import executor from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model @@ -10,7 +13,19 @@ from pypy.translator.cli.dotnet import CLR System = CLR.System +OpCodes = System.Reflection.Emit.OpCodes InputArgs = CLR.pypy.runtime.InputArgs +cpypyString = dotnet.classof(CLR.pypy.runtime.String) + +class __extend__(TreeLoop): + __metaclass__ = extendabletype + + _cli_funcbox = None + _cli_meth = None + _cli_count = 0 + + def _get_cli_name(self): + return '%s(r%d)' % (self.name, self._cli_count) class CliCPU(model.AbstractCPU): @@ -25,6 +40,7 @@ self.stats = stats self.translate_support_code = translate_support_code self.inputargs = None + self.failing_ops = [] # index --> op self.ll_ovf_exc = self._get_prebuilt_exc(OverflowError) self.ll_zero_exc = self._get_prebuilt_exc(ZeroDivisionError) @@ -48,6 +64,8 @@ @cached_method('_methcache') def methdescrof(self, SELFTYPE, methname): + if SELFTYPE in (ootype.String, ootype.Unicode): + return StringMethDescr(SELFTYPE, methname) return MethDescr(SELFTYPE, methname) @cached_method('_typecache') @@ -67,14 +85,19 @@ # ---------------------- def compile_operations(self, loop): - from pypy.jit.backend.cli.method import Method - meth = Method(self, loop.name, loop) - loop._cli_meth = meth + from pypy.jit.backend.cli.method import Method, ConstFunction + if loop._cli_funcbox is None: + loop._cli_funcbox = ConstFunction(loop.name) + else: + # discard previously compiled loop + loop._cli_funcbox.holder.SetFunc(None) + loop._cli_meth = Method(self, loop._get_cli_name(), loop) + loop._cli_count += 1 def execute_operations(self, loop): - meth = loop._cli_meth - meth.func(self.get_inputargs()) - return meth.failing_ops[self.inputargs.get_failed_op()] + func = loop._cli_funcbox.holder.GetFunc() + func(self.get_inputargs()) + return self.failing_ops[self.inputargs.get_failed_op()] def set_future_value_int(self, index, intvalue): self.get_inputargs().set_int(index, intvalue) @@ -110,10 +133,14 @@ self.get_inputargs().set_exc_value(None) def set_overflow_error(self): - raise NotImplementedError + exc_obj = ootype.cast_to_object(self.ll_ovf_exc) + exc_value = dotnet.cast_to_native_object(exc_obj) + self.get_inputargs().set_exc_value(exc_value) def set_zero_division_error(self): - raise NotImplementedError + exc_obj = ootype.cast_to_object(self.ll_zero_exc) + exc_value = dotnet.cast_to_native_object(exc_obj) + self.get_inputargs().set_exc_value(exc_value) # ---------------------- @@ -122,6 +149,11 @@ assert len(args) == 1 # but we don't need it, so ignore return typedescr.create() + def do_new_array(self, args, typedescr): + assert isinstance(typedescr, TypeDescr) + assert len(args) == 1 + return typedescr.create_array(args[0]) + def do_runtimenew(self, args, descr): classbox = args[0] classobj = ootype.cast_from_object(ootype.Class, classbox.getobj()) @@ -188,6 +220,16 @@ # ---------------------------------------------------------------------- key_manager = KeyManager() +class DescrWithKey(AbstractDescr): + key = -1 + + def __init__(self, key): + self.key = key_manager.getkey(key) + + def sort_key(self): + return self.key + + def get_class_for_type(T): if T is ootype.Void: return ootype.nullruntimeclass @@ -206,10 +248,10 @@ else: assert False - -class TypeDescr(AbstractDescr): +class TypeDescr(DescrWithKey): def __init__(self, TYPE): + DescrWithKey.__init__(self, TYPE) from pypy.jit.backend.llgraph.runner import boxresult from pypy.jit.metainterp.warmspot import unwrap ARRAY = ootype.Array(TYPE) @@ -245,25 +287,25 @@ self.getarraylength = getarraylength self.instanceof = instanceof self.ooclass = get_class_for_type(TYPE) - self.ooarrayclass = get_class_for_type(ARRAY) def get_clitype(self): return dotnet.class2type(self.ooclass) def get_array_clitype(self): - return dotnet.class2type(self.ooarrayclass) + return self.get_clitype().MakeArrayType() def get_constructor_info(self): clitype = self.get_clitype() return clitype.GetConstructor(dotnet.new_array(System.Type, 0)) -class StaticMethDescr(AbstractDescr): +class StaticMethDescr(DescrWithKey): callfunc = None funcclass = ootype.nullruntimeclass has_result = False def __init__(self, FUNC, ARGS, RESULT): + DescrWithKey.__init__(self, (FUNC, ARGS, RESULT)) from pypy.jit.backend.llgraph.runner import boxresult, make_getargs getargs = make_getargs(FUNC.ARGS) def callfunc(funcbox, argboxes): @@ -300,6 +342,7 @@ selfclass = ootype.nullruntimeclass methname = '' has_result = False + key = -1 def __init__(self, SELFTYPE, methname): from pypy.jit.backend.llgraph.runner import boxresult, make_getargs @@ -317,6 +360,10 @@ self.selfclass = ootype.runtimeClass(SELFTYPE) self.methname = methname self.has_result = (METH.RESULT != ootype.Void) + self.key = key_manager.getkey((SELFTYPE, methname)) + + def sort_key(self): + return self.key def get_self_clitype(self): return dotnet.class2type(self.selfclass) @@ -325,16 +372,29 @@ clitype = self.get_self_clitype() return clitype.GetMethod(self.methname+'') + def get_call_opcode(self): + return OpCodes.Callvirt -class FieldDescr(AbstractDescr): + +class StringMethDescr(MethDescr): + + def get_meth_info(self): + clitype = dotnet.class2type(cpypyString) + return clitype.GetMethod(self.methname+'') + + def get_call_opcode(self): + return OpCodes.Call + + +class FieldDescr(DescrWithKey): getfield = None setfield = None selfclass = ootype.nullruntimeclass fieldname = '' - key = -1 def __init__(self, TYPE, fieldname): + DescrWithKey.__init__(self, (TYPE, fieldname)) from pypy.jit.backend.llgraph.runner import boxresult from pypy.jit.metainterp.warmspot import unwrap _, T = TYPE._lookup_field(fieldname) @@ -353,9 +413,6 @@ self.fieldname = fieldname self.key = key_manager.getkey((TYPE, fieldname)) - def sort_key(self): - return self.key - def equals(self, other): assert isinstance(other, FieldDescr) return self.key == other.key Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py Tue May 26 21:04:20 2009 @@ -37,7 +37,4 @@ test_oostring_instance = skip test_long_long = skip test_free_object = skip - - test_stopatxpolicy = _skip - test_bridge_from_interpreter = _skip - test_bridge_from_interpreter_4 = _skip + test_stopatxpolicy = skip Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_basic.py Tue May 26 21:04:20 2009 @@ -16,17 +16,21 @@ # for the individual tests see # ====> ../../../metainterp/test/test_basic.py + def mono_bug(self): + py.test.skip('mono bug?') + def skip(self): py.test.skip('in-progress') - test_stopatxpolicy = skip + test_stopatxpolicy = mono_bug + test_print = skip test_bridge_from_interpreter = skip test_bridge_from_interpreter_2 = skip - test_bridge_from_interpreter_3 = skip - test_bridge_from_interpreter_4 = skip - test_bridge_leaving_interpreter_5 = skip test_free_object = skip + def test_bridge_from_interpreter_4(self): + pass # not a translation test + def test_we_are_jitted(self): py.test.skip("it seems to fail even with the x86 backend, didn't investigate the problem") Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_exception.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_exception.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_exception.py Tue May 26 21:04:20 2009 @@ -7,17 +7,5 @@ # for the individual tests see # ====> ../../../metainterp/test/test_exception.py - def skip_loop(self): - py.test.skip('jump across loops not implemented yet') - - def skip(self): - py.test.skip('in-progress') - - test_bridge_from_guard_exception = skip_loop - test_exception_four_cases = skip_loop - test_bridge_from_interpreter_exc = skip_loop - test_bridge_from_interpreter_exc_2 = skip_loop - test_int_lshift_ovf = skip_loop - - + pass Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_zrpy_send.py Tue May 26 21:04:20 2009 @@ -7,12 +7,6 @@ # for the individual tests see # ====> ../../../metainterp/test/test_send.py - def skip_loop(self): - py.test.skip('jump across loops not implemented yet') - - test_three_receivers = skip_loop - test_three_classes = skip_loop - test_recursive_call_to_portal_from_blackhole = skip_loop - test_indirect_call_unknown_object_1 = skip_loop - test_three_cases = skip_loop + def test_recursive_call_to_portal_from_blackhole(self): + py.test.skip('string return values are not supported') Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/support.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/support.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/support.py Tue May 26 21:04:20 2009 @@ -104,3 +104,9 @@ from pypy.translator.cli.test.runtest import compile_graph func = compile_graph(entry_point_graph, t, nowrap=True, standalone=True) return func(*args) + + def run_directly(self, fn, args): + from pypy.translator.cli.test.runtest import compile_function, get_annotation + ann = [get_annotation(x) for x in args] + clifunc = compile_function(fn, ann) + return clifunc(*args) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_loop.py Tue May 26 21:04:20 2009 @@ -16,6 +16,9 @@ CPUClass=self.CPUClass, type_system=self.type_system) + def run_directly(self, f, args): + return f(*args) + def test_simple_loop(self): myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) def f(x, y): @@ -348,7 +351,21 @@ x += unichr(n) n -= 1 return hash(x) - expected = f(100) + expected = self.run_directly(f, [100]) + res = self.meta_interp(f, [100]) + assert res == expected + + def test_loop_string(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'n']) + def f(n): + x = '' + while n > 13: + myjitdriver.can_enter_jit(n=n, x=x) + myjitdriver.jit_merge_point(n=n, x=x) + x += chr(n) + n -= 1 + return hash(x) + expected = self.run_directly(f, [100]) res = self.meta_interp(f, [100]) assert res == expected Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_tl.py Tue May 26 21:04:20 2009 @@ -95,8 +95,6 @@ def test_tl_base(self): res = self.meta_interp(self.main.im_func, [0, 6], listops=True) assert res == 5040 - if self.type_system == 'ootype': - py.test.skip('optimizing problem') self.check_loops({'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, 'guard_false':1, 'guard_value':1}) @@ -104,8 +102,6 @@ def test_tl_2(self): res = self.meta_interp(self.main.im_func, [1, 10], listops=True) assert res == self.main.im_func(1, 10) - if self.type_system == 'ootype': - py.test.skip('optimizing problem') self.check_loops({'int_sub':1, 'int_le':1, 'int_is_true':1, 'guard_false':1, 'jump':1, 'guard_value':1}) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py Tue May 26 21:04:20 2009 @@ -617,3 +617,11 @@ ImplicitVirtualizableTests, LLJitMixin): pass + + +class TestOptimize2(ImplicitVirtualizableTests, LLJitMixin): + + def meta_interp(self, *args, **kwds): + from pypy.jit.metainterp.optimize2 import Optimizer + kwds['optimizer'] = Optimizer + return LLJitMixin.meta_interp(self, *args, **kwds) Modified: pypy/branch/pyjitpl5-experiments/pypy/rpython/ootypesystem/rpbc.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/rpython/ootypesystem/rpbc.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/rpython/ootypesystem/rpbc.py Tue May 26 21:04:20 2009 @@ -116,10 +116,11 @@ class MethodsPBCRepr(AbstractMethodsPBCRepr): - def __init__(self, rtyper, s_pbc): - AbstractMethodsPBCRepr.__init__(self, rtyper, s_pbc) - sampledesc = s_pbc.descriptions.iterkeys().next() - self.concretetable, _ = get_concrete_calltable(rtyper, + concretetable = None # set by _setup_repr_final + + def _setup_repr_final(self): + sampledesc = self.s_pbc.descriptions.iterkeys().next() + self.concretetable, _ = get_concrete_calltable(self.rtyper, sampledesc.funcdesc.getcallfamily()) def rtype_simple_call(self, hop): Modified: pypy/branch/pyjitpl5-experiments/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/translator/cli/opcodes.py Tue May 26 21:04:20 2009 @@ -80,6 +80,7 @@ 'keepalive': Ignore, 'is_early_constant': [PushPrimitive(ootype.Bool, False)], 'jit_marker': Ignore, + 'promote_virtualizable': Ignore, } # __________ numeric operations __________ Modified: pypy/branch/pyjitpl5-experiments/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/pyjitpl5-experiments/pypy/translator/cli/src/pypylib.cs Tue May 26 21:04:20 2009 @@ -291,24 +291,25 @@ return default_blockid; } } + */ public class DelegateHolder { - public Delegate func; + public LoopDelegate func; // we need getter and setter because we can't directly access fields from RPython - public void SetFunc(Delegate func) + public void SetFunc(LoopDelegate func) { this.func = func; } - public Delegate GetFunc() + public LoopDelegate GetFunc() { return this.func; } } - */ + public class AutoSaveAssembly { Modified: pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/test_template/class_.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/test_template/class_.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/test_template/class_.py Tue May 26 21:04:20 2009 @@ -64,5 +64,8 @@ return a.x + b.x assert self.interpret(fn, [1, 2]) == 3 + def test_cast_object_mix_null(self): + py.test.skip('cannot return ootype.NULL from translated functions') + class BaseTestSpecialcase(BaseTestRspecialcase): pass From fijal at codespeak.net Tue May 26 21:10:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:10:06 +0200 (CEST) Subject: [pypy-svn] r65432 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090526191006.411FF1684BF@codespeak.net> Author: fijal Date: Tue May 26 21:10:04 2009 New Revision: 65432 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: make guard_nonvirtualizable yield a class. That's mostly to make llgraph backend a bit happier, I'm not too happy about it Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 21:10:04 2009 @@ -110,7 +110,7 @@ for node, d in self.additional_stores.iteritems(): for field, fieldnode in d.iteritems(): gop = ResOperation(rop.GUARD_NONVIRTUALIZED, - [node.source], None) + [node.source, node.cls], None) gop.vdesc = node.vdesc gop.suboperations = [ResOperation(rop.FAIL, [], None)] op.suboperations.append(gop) @@ -120,7 +120,7 @@ for field, (fieldnode, descr) in d.iteritems(): box = fieldnode.source gop = ResOperation(rop.GUARD_NONVIRTUALIZED, - [node.source], None) + [node.source, node.cls], None) gop.suboperations = [ResOperation(rop.FAIL, [], None)] gop.vdesc = node.vdesc op.suboperations.append(gop) @@ -186,6 +186,7 @@ def optimize_guard_nonvirtualized(op, spec): instnode = spec.getnode(op.args[0]) instnode.virtualized = True + instnode.cls = op.args[1] instnode.vdesc = op.vdesc return True Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Tue May 26 21:10:04 2009 @@ -4,7 +4,7 @@ """ from pypy.jit.metainterp.history import TreeLoop, BoxInt, BoxPtr, ConstInt,\ - ConstAddr, ConstObj + ConstAddr, ConstObj, ConstPtr from pypy.jit.metainterp.resoperation import rop, ResOperation from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype @@ -59,6 +59,8 @@ self.cpu) else: return ConstObj(ootype.cast_to_object(self.consts[name])) + elif arg == 'None': + return None return self.vars[arg] def parse_op(self, line): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 26 21:10:04 2009 @@ -59,7 +59,8 @@ TP = lltype.GcArray(lltype.Signed) - XY = lltype.GcStruct('XY', ('inst_field', lltype.Signed), + XY = lltype.GcStruct('XY', ('parent', OBJECT), + ('inst_field', lltype.Signed), ('inst_other_field', lltype.Signed), ('inst_list', lltype.Ptr(TP)), hints= {'virtualizable2': True, @@ -69,6 +70,7 @@ list_desc = cpu.fielddescrof(XY, 'inst_list') other_field_desc = cpu.fielddescrof(XY, 'inst_other_field') vdesc = VirtualizableDesc(cpu, XY, XY) + xy_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) namespace = locals() @@ -102,6 +104,7 @@ list_desc = cpu.fielddescrof(XY, 'olist') other_field_desc = cpu.fielddescrof(XY, 'oother_field') vdesc = VirtualizableDesc(cpu, XY, XY) + xy_vtable = ootype.runtimeClass(XY) namespace = locals() @@ -151,7 +154,7 @@ def test_basic_virtualizable(self): pre_op = """ [p0] - guard_nonvirtualized(p0, vdesc=vdesc) + guard_nonvirtualized(p0, ConstClass(xy_vtable), vdesc=vdesc) fail() i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=field_desc) @@ -168,7 +171,7 @@ def test_virtualizable_setfield_rebuild_ops(self): pre_op = """ [p0] - guard_nonvirtualized(p0, vdesc=vdesc) + guard_nonvirtualized(p0, ConstClass(xy_vtable), vdesc=vdesc) fail() i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=other_field_desc) @@ -184,7 +187,8 @@ i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=other_field_desc) guard_true(i2) - guard_nonvirtualized(p0) + guard_nonvirtualized(p0, ConstClass(xy_vtable)) + fail() setfield_gc(p0, i2, descr=field_desc) fail() """ @@ -211,7 +215,7 @@ def test_virtualized_list_on_virtualizable(self): pre_op = """ [p0] - guard_nonvirtualized(p0, vdesc=vdesc) + guard_nonvirtualized(p0, ConstClass(xy_vtable), vdesc=vdesc) fail() p1 = getfield_gc(p0, descr=list_desc) setarrayitem_gc(p1, 0, 1, descr=array_descr) @@ -235,7 +239,7 @@ def test_virtualized_list_on_virtualizable_2(self): pre_op = """ [p0, i0] - guard_nonvirtualized(p0, vdesc=vdesc) + guard_nonvirtualized(p0, ConstClass(xy_vtable), vdesc=vdesc) fail() p1 = getfield_gc(p0, descr=list_desc) setarrayitem_gc(p1, 0, i0, descr=array_descr) @@ -252,7 +256,8 @@ i2 = int_add(i0, i0) i3 = int_is_true(i2) guard_true(i3) - guard_nonvirtualized(p1) + guard_nonvirtualized(p1, None) + fail() setarrayitem_gc(p1, 0, i0, descr=array_descr) fail() """ @@ -262,7 +267,7 @@ def test_virtualized_list_on_virtualizable_3(self): pre_op = """ [p0, i0, i1] - guard_nonvirtualized(p0, vdesc=vdesc) + guard_nonvirtualized(p0, ConstClass(xy_vtable), vdesc=vdesc) fail() p1 = getfield_gc(p0, descr=list_desc) setarrayitem_gc(p1, 0, i0, descr=array_descr) @@ -281,7 +286,8 @@ i4 = int_add(i0, i1) i5 = int_is_true(i4) guard_true(i5) - guard_nonvirtualized(p1) + guard_nonvirtualized(p1, None) + fail() setarrayitem_gc(p1, 0, i1, descr=array_descr) fail() """ @@ -348,4 +354,5 @@ pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - pass + def setup_class(cls): + py.test.skip("XXX") From fijal at codespeak.net Tue May 26 21:10:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:10:56 +0200 (CEST) Subject: [pypy-svn] r65433 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph Message-ID: <20090526191056.705561684BF@codespeak.net> Author: fijal Date: Tue May 26 21:10:55 2009 New Revision: 65433 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Log: don't complain if class is None Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Tue May 26 21:10:55 2009 @@ -555,7 +555,8 @@ def op_guard_nonvirtualized(self, for_accessing_field, value, expected_class): - self.op_guard_class(-1, value, expected_class) + if expected_class is not None: + self.op_guard_class(-1, value, expected_class) if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control From fijal at codespeak.net Tue May 26 21:13:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:13:31 +0200 (CEST) Subject: [pypy-svn] r65434 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph Message-ID: <20090526191331.6B8C8169DB2@codespeak.net> Author: fijal Date: Tue May 26 21:13:30 2009 New Revision: 65434 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Log: seems this won't work Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Tue May 26 21:13:30 2009 @@ -555,8 +555,7 @@ def op_guard_nonvirtualized(self, for_accessing_field, value, expected_class): - if expected_class is not None: - self.op_guard_class(-1, value, expected_class) + self.op_guard_class(-1, value, expected_class) if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control From fijal at codespeak.net Tue May 26 21:16:14 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:16:14 +0200 (CEST) Subject: [pypy-svn] r65435 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090526191614.B352A168556@codespeak.net> Author: fijal Date: Tue May 26 21:16:14 2009 New Revision: 65435 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: remove the hack about guard_nonvirtualized Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 21:16:14 2009 @@ -94,6 +94,13 @@ newboxes.append(box) return newboxes + def _guard_for_node(self, node): + gop = ResOperation(rop.GUARD_NONVIRTUALIZED, + [node.source], None) + gop.vdesc = node.vdesc + gop.suboperations = [ResOperation(rop.FAIL, [], None)] + return gop + def optimize_guard(self, op): if op.is_foldable_guard(): for arg in op.args: @@ -109,20 +116,14 @@ op.suboperations = [] for node, d in self.additional_stores.iteritems(): for field, fieldnode in d.iteritems(): - gop = ResOperation(rop.GUARD_NONVIRTUALIZED, - [node.source, node.cls], None) - gop.vdesc = node.vdesc - gop.suboperations = [ResOperation(rop.FAIL, [], None)] + gop = self._guard_for_node(node) op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETFIELD_GC, [node.source, fieldnode.source], None, field)) for node, d in self.additional_setarrayitems.iteritems(): for field, (fieldnode, descr) in d.iteritems(): box = fieldnode.source - gop = ResOperation(rop.GUARD_NONVIRTUALIZED, - [node.source, node.cls], None) - gop.suboperations = [ResOperation(rop.FAIL, [], None)] - gop.vdesc = node.vdesc + gop = self._guard_for_node(node) op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, [node.source, ConstInt(field), box], None, descr)) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Tue May 26 21:16:14 2009 @@ -187,7 +187,7 @@ i1 = getfield_gc(p0, descr=field_desc) i2 = getfield_gc(p0, descr=other_field_desc) guard_true(i2) - guard_nonvirtualized(p0, ConstClass(xy_vtable)) + guard_nonvirtualized(p0) fail() setfield_gc(p0, i2, descr=field_desc) fail() @@ -256,7 +256,7 @@ i2 = int_add(i0, i0) i3 = int_is_true(i2) guard_true(i3) - guard_nonvirtualized(p1, None) + guard_nonvirtualized(p1) fail() setarrayitem_gc(p1, 0, i0, descr=array_descr) fail() @@ -286,7 +286,7 @@ i4 = int_add(i0, i1) i5 = int_is_true(i4) guard_true(i5) - guard_nonvirtualized(p1, None) + guard_nonvirtualized(p1) fail() setarrayitem_gc(p1, 0, i1, descr=array_descr) fail() From fijal at codespeak.net Tue May 26 21:17:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:17:03 +0200 (CEST) Subject: [pypy-svn] r65436 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph Message-ID: <20090526191703.BB545168548@codespeak.net> Author: fijal Date: Tue May 26 21:17:00 2009 New Revision: 65436 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Log: try yo make llgraph backend happy Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Tue May 26 21:17:00 2009 @@ -554,8 +554,9 @@ raise GuardFailed def op_guard_nonvirtualized(self, for_accessing_field, - value, expected_class): - self.op_guard_class(-1, value, expected_class) + value, expected_class=None): + if expected_class is None: + self.op_guard_class(-1, value, expected_class) if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control From fijal at codespeak.net Tue May 26 21:20:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:20:53 +0200 (CEST) Subject: [pypy-svn] r65437 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph Message-ID: <20090526192053.BE69D168556@codespeak.net> Author: fijal Date: Tue May 26 21:20:53 2009 New Revision: 65437 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Log: oops Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Tue May 26 21:20:53 2009 @@ -555,7 +555,7 @@ def op_guard_nonvirtualized(self, for_accessing_field, value, expected_class=None): - if expected_class is None: + if expected_class is not None: self.op_guard_class(-1, value, expected_class) if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control From fijal at codespeak.net Tue May 26 21:23:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:23:46 +0200 (CEST) Subject: [pypy-svn] r65438 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526192346.1936E1684BF@codespeak.net> Author: fijal Date: Tue May 26 21:23:45 2009 New Revision: 65438 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: remove this as it might not be there right now Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 21:23:45 2009 @@ -187,7 +187,6 @@ def optimize_guard_nonvirtualized(op, spec): instnode = spec.getnode(op.args[0]) instnode.virtualized = True - instnode.cls = op.args[1] instnode.vdesc = op.vdesc return True From fijal at codespeak.net Tue May 26 21:37:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:37:20 +0200 (CEST) Subject: [pypy-svn] r65439 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526193720.AE864168556@codespeak.net> Author: fijal Date: Tue May 26 21:37:19 2009 New Revision: 65439 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: add counting of operations Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Tue May 26 21:37:19 2009 @@ -135,7 +135,9 @@ self.additional_stores = {} self.additional_setarrayitems = {} newoperations = [] + opnum = 0 for op in self.loop.operations: + opnum += 1 remove_op = False for opt in self.optimizations[op.opnum]: remove_op = opt(op, self) From fijal at codespeak.net Tue May 26 21:44:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 21:44:48 +0200 (CEST) Subject: [pypy-svn] r65440 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090526194448.11F8B169E27@codespeak.net> Author: fijal Date: Tue May 26 21:44:47 2009 New Revision: 65440 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py Log: don't show suboperations for guard_nonvirtualized Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py Tue May 26 21:44:47 2009 @@ -2,7 +2,7 @@ from pypy.translator.tool.graphpage import GraphPage from pypy.translator.tool.make_dot import DotGen from pypy.jit.metainterp.history import Box - +from pypy.jit.metainterp.resoperation import rop class SubGraph: def __init__(self, suboperations): @@ -16,7 +16,7 @@ graphs = [(loop, loop in highlight_loops) for loop in loops] for graph, highlight in graphs: for op in graph.get_operations(): - if op.is_guard(): + if op.is_guard() and op.opnum != rop.GUARD_NONVIRTUALIZED: graphs.append((SubGraph(op.suboperations), highlight)) graphpage = ResOpGraphPage(graphs, errmsg) graphpage.display() From fijal at codespeak.net Tue May 26 23:51:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 26 May 2009 23:51:10 +0200 (CEST) Subject: [pypy-svn] r65441 - pypy/branch/pyjitpl5-experiments/pypy/interpreter Message-ID: <20090526215110.0DC88169EEB@codespeak.net> Author: fijal Date: Tue May 26 23:51:09 2009 New Revision: 65441 Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py Log: Move hints around. Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py Tue May 26 23:51:09 2009 @@ -181,6 +181,7 @@ return values_w def dropvalues(self, n): + n = hint(n, promote=True) finaldepth = self.valuestackdepth - n assert finaldepth >= 0, "stack underflow in dropvalues()" while True: @@ -188,7 +189,7 @@ if n < 0: break self.valuestack_w[finaldepth+n] = None - self.valuestackdepth = hint(finaldepth, promote=True) + self.valuestackdepth = finaldepth def pushrevvalues(self, n, values_w): # n should be len(values_w) while True: @@ -207,21 +208,24 @@ self.pushvalue(w_value) def peekvalue(self, index_from_top=0): + index_from_top = hint(index_from_top, promote=True) index = self.valuestackdepth + ~index_from_top assert index >= 0, "peek past the bottom of the stack" return self.valuestack_w[index] def settopvalue(self, w_object, index_from_top=0): + index_from_top = hint(index_from_top, promote=True) index = self.valuestackdepth + ~index_from_top assert index >= 0, "settop past the bottom of the stack" self.valuestack_w[index] = w_object def dropvaluesuntil(self, finaldepth): depth = self.valuestackdepth - 1 + finaldepth = hint(finaldepth, promote=True) while depth >= finaldepth: self.valuestack_w[depth] = None depth -= 1 - self.valuestackdepth = hint(finaldepth, promote=True) + self.valuestackdepth = finaldepth def savevaluestack(self): return self.valuestack_w[:self.valuestackdepth] From fijal at codespeak.net Wed May 27 00:14:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 00:14:49 +0200 (CEST) Subject: [pypy-svn] r65442 - pypy/trunk/dotviewer Message-ID: <20090526221449.5F9E6169EC8@codespeak.net> Author: fijal Date: Wed May 27 00:14:47 2009 New Revision: 65442 Modified: pypy/trunk/dotviewer/graphclient.py pypy/trunk/dotviewer/graphserver.py Log: De-arminize. s/connexion/connection/ Modified: pypy/trunk/dotviewer/graphclient.py ============================================================================== --- pypy/trunk/dotviewer/graphclient.py (original) +++ pypy/trunk/dotviewer/graphclient.py Wed May 27 00:14:47 2009 @@ -92,7 +92,7 @@ if msg[0] == msgstruct.MSG_OK: break except EOFError: - ioerror = ioerror or IOError("connexion unexpectedly closed " + ioerror = ioerror or IOError("connection unexpectedly closed " "(graphserver crash?)") if ioerror is not None: raise ioerror Modified: pypy/trunk/dotviewer/graphserver.py ============================================================================== --- pypy/trunk/dotviewer/graphserver.py (original) +++ pypy/trunk/dotviewer/graphserver.py Wed May 27 00:14:47 2009 @@ -126,7 +126,7 @@ print 'listening on %r...' % (s1.getsockname(),) while True: conn, addr = s1.accept() - print 'accepted connexion from %r' % (addr,) + print 'accepted connection from %r' % (addr,) sock_io = msgstruct.SocketIO(conn) handler_io = graphclient.spawn_local_handler() thread.start_new_thread(copy_all, (sock_io, handler_io)) From fijal at codespeak.net Wed May 27 02:41:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 02:41:09 +0200 (CEST) Subject: [pypy-svn] r65443 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090527004109.0280D169F1A@codespeak.net> Author: fijal Date: Wed May 27 02:41:07 2009 New Revision: 65443 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: cheat - don't virtualize virtualizables that are allocated in a loop. The reason behind it is that if it does so, it's going to be an argument of a portal call Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Wed May 27 02:41:07 2009 @@ -22,6 +22,7 @@ self.cleanfields = {} self.arrayfields = {} self.virtualized = False + self.allocated_in_loop = False self.vdesc = None def __repr__(self): @@ -83,7 +84,10 @@ self.getnode(box) box = op.result if box is not None: - self.nodes[box] = self.getnode(box) + node = self.getnode(box) + if op.opnum == rop.NEW or op.opnum == rop.NEW_WITH_VTABLE: + node.allocated_in_loop = True + self.nodes[box] = node def new_arguments(self, op): newboxes = [] @@ -188,8 +192,9 @@ @staticmethod def optimize_guard_nonvirtualized(op, spec): instnode = spec.getnode(op.args[0]) - instnode.virtualized = True - instnode.vdesc = op.vdesc + if not instnode.allocated_in_loop: + instnode.virtualized = True + instnode.vdesc = op.vdesc return True @staticmethod Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py Wed May 27 02:41:07 2009 @@ -667,7 +667,6 @@ res = self.meta_interp(f, [30]) assert res == 1 - class TestOOtype(BasicTests, OOJitMixin): def test_oohash(self): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Wed May 27 02:41:07 2009 @@ -279,7 +279,6 @@ guard_true(i5) fail() """ - pre_op = parse(pre_op, self.cpu, self.namespace) expected = """ [p0, i0, i1] p1 = getfield_gc(p0, descr=list_desc) @@ -294,6 +293,23 @@ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), expected) + def test_newly_allocated_virtualizable_is_not_virtualized(self): + pre_op = """ + [] + p0 = new_with_vtable(13, ConstClass(xy_vtable)) + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + setfield_gc(p0, 3, descr=field_desc) + """ + expected = """ + [] + p0 = new_with_vtable(13, ConstClass(xy_vtable)) + setfield_gc(p0, 3, descr=field_desc) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), + expected) + + def test_remove_consecutive_guard_value_constfold(self): py.test.skip("not yet") n = BoxInt(0) From cfbolz at codespeak.net Wed May 27 14:03:01 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 14:03:01 +0200 (CEST) Subject: [pypy-svn] r65444 - in pypy/trunk/pypy: config doc/config interpreter objspace objspace/fake objspace/std objspace/std/test translator/microbench Message-ID: <20090527120301.CE691169F82@codespeak.net> Author: cfbolz Date: Wed May 27 14:03:00 2009 New Revision: 65444 Added: pypy/trunk/pypy/doc/config/objspace.std.withcelldict.txt (contents, props changed) pypy/trunk/pypy/objspace/std/celldict.py (contents, props changed) pypy/trunk/pypy/objspace/std/test/test_celldict.py (contents, props changed) Modified: pypy/trunk/pypy/config/pypyoption.py pypy/trunk/pypy/interpreter/module.py pypy/trunk/pypy/interpreter/pycode.py pypy/trunk/pypy/objspace/fake/objspace.py pypy/trunk/pypy/objspace/reflective.py pypy/trunk/pypy/objspace/std/dictmultiobject.py pypy/trunk/pypy/objspace/std/objspace.py pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py pypy/trunk/pypy/objspace/std/test/test_dictobject.py pypy/trunk/pypy/translator/microbench/test_count1.py Log: merge speedup-global2 branch: ------------------------------------------------------------------------ r62765 | cfbolz | 2009-03-09 17:53:28 +0100 (Mon, 09 Mar 2009) | 3 lines Changed paths: A /pypy/branch/speedup-globals (from /pypy/trunk:62764) A branch to try Armin's and mine newest idea about how to speed up global lookups. ------------------------------------------------------------------------ r62773 | cfbolz | 2009-03-09 19:02:50 +0100 (Mon, 09 Mar 2009) | 5 lines Changed paths: M /pypy/branch/speedup-globals/pypy/config/pypyoption.py M /pypy/branch/speedup-globals/pypy/interpreter/module.py M /pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py M /pypy/branch/speedup-globals/pypy/objspace/reflective.py M /pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py M /pypy/branch/speedup-globals/pypy/objspace/std/objspace.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py First step to make global lookups faster: Introduce a special dict implementation for modules, where every value in the RPython-level dict is a cell that contains the real value. As long as the "valid" flag on such a cell is set, it is safe to store the cell somewhere else. ------------------------------------------------------------------------ r62811 | cfbolz | 2009-03-10 16:00:52 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: A /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py M /pypy/branch/speedup-globals/pypy/objspace/std/objspace.py A /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py Actually use the cell-dict stuff to cache global lookups in frames. ------------------------------------------------------------------------ r62816 | cfbolz | 2009-03-10 16:34:17 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py help flow space ------------------------------------------------------------------------ r62819 | cfbolz | 2009-03-10 17:54:44 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py fix typo ------------------------------------------------------------------------ r62823 | cfbolz | 2009-03-10 17:57:56 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py fix gadfly ------------------------------------------------------------------------ r62827 | cfbolz | 2009-03-10 19:07:12 +0100 (Tue, 10 Mar 2009) | 4 lines Changed paths: M /pypy/branch/speedup-globals/pypy/interpreter/pycode.py M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py It turns out that using one additional dict lookup per call negates many of the benefits of this optimization. Therefore, attach the cache to the code object directly. ------------------------------------------------------------------------ r62830 | cfbolz | 2009-03-10 20:38:30 +0100 (Tue, 10 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py two more microbenchmarks ------------------------------------------------------------------------ r62845 | cfbolz | 2009-03-11 11:54:45 +0100 (Wed, 11 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py get rid of invalid flag ------------------------------------------------------------------------ r62856 | cfbolz | 2009-03-11 13:16:33 +0100 (Wed, 11 Mar 2009) | 2 lines Changed paths: M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py fix a corner-case ------------------------------------------------------------------------ r65410 | cfbolz | 2009-05-25 14:34:08 +0200 (Mon, 25 May 2009) | 2 lines Changed paths: A /pypy/branch/speedup-global2/pypy/doc/config/objspace.std.withcelldict.txt add missing documentation Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Wed May 27 14:03:00 2009 @@ -228,6 +228,13 @@ "use dictionaries optimized for flexibility", default=False), + BoolOption("withcelldict", + "use dictionaries that are opimized for being used as module dicts", + default=False, + requires=[("objspace.std.withmultidict", True), + ("objspace.opcodes.CALL_LIKELY_BUILTIN", False), + ("objspace.honor__builtins__", False)]), + BoolOption("withsharingdict", "use dictionaries that share the keys part", default=False, Added: pypy/trunk/pypy/doc/config/objspace.std.withcelldict.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/config/objspace.std.withcelldict.txt Wed May 27 14:03:00 2009 @@ -0,0 +1,2 @@ +Enable cell-dicts. This makes global lookups nearly as fast as the lookup of a +local. Modified: pypy/trunk/pypy/interpreter/module.py ============================================================================== --- pypy/trunk/pypy/interpreter/module.py (original) +++ pypy/trunk/pypy/interpreter/module.py Wed May 27 14:03:00 2009 @@ -11,7 +11,7 @@ def __init__(self, space, w_name, w_dict=None): self.space = space if w_dict is None: - w_dict = space.newdict(track_builtin_shadowing=True) + w_dict = space.newdict(module=True) self.w_dict = w_dict self.w_name = w_name if w_name is not None: Modified: pypy/trunk/pypy/interpreter/pycode.py ============================================================================== --- pypy/trunk/pypy/interpreter/pycode.py (original) +++ pypy/trunk/pypy/interpreter/pycode.py Wed May 27 14:03:00 2009 @@ -111,6 +111,10 @@ self._compute_flatcall() + if space.config.objspace.std.withcelldict: + from pypy.objspace.std.celldict import init_code + init_code(self) + co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): Modified: pypy/trunk/pypy/objspace/fake/objspace.py ============================================================================== --- pypy/trunk/pypy/objspace/fake/objspace.py (original) +++ pypy/trunk/pypy/objspace/fake/objspace.py Wed May 27 14:03:00 2009 @@ -93,7 +93,7 @@ newint = make_dummy() newlong = make_dummy() newfloat = make_dummy() - def newdict(self, track_builtin_shadowing=False): + def newdict(self, module=False): return self.newfloat() newlist = make_dummy() emptylist = make_dummy() Modified: pypy/trunk/pypy/objspace/reflective.py ============================================================================== --- pypy/trunk/pypy/objspace/reflective.py (original) +++ pypy/trunk/pypy/objspace/reflective.py Wed May 27 14:03:00 2009 @@ -137,8 +137,8 @@ return None if opname == "newdict": # grr grr kwargs - def fn(track_builtin_shadowing=False): - w_obj = parentfn(track_builtin_shadowing) + def fn(module=False): + w_obj = parentfn(module) w_newobj = user_hook(w_obj) if w_newobj is not None: return w_newobj Added: pypy/trunk/pypy/objspace/std/celldict.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/objspace/std/celldict.py Wed May 27 14:03:00 2009 @@ -0,0 +1,248 @@ +from pypy.objspace.std.dictmultiobject import DictImplementation +from pypy.objspace.std.dictmultiobject import IteratorImplementation +from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash + +class ModuleCell(object): + def __init__(self, w_value=None): + self.w_value = w_value + + def invalidate(self): + w_value = self.w_value + self.w_value = None + return w_value + + def __repr__(self): + return "" % (self.w_value, ) + +class ModuleDictImplementation(DictImplementation): + def __init__(self, space): + self.space = space + self.content = {} + self.unshadowed_builtins = {} + + def getcell(self, key, make_new=True): + try: + return self.content[key] + except KeyError: + if not make_new: + raise + result = self.content[key] = ModuleCell() + return result + + def add_unshadowed_builtin(self, name, builtin_impl): + assert isinstance(builtin_impl, ModuleDictImplementation) + self.unshadowed_builtins[name] = builtin_impl + + def invalidate_unshadowed_builtin(self, name): + impl = self.unshadowed_builtins[name] + try: + cell = impl.content[name] + except KeyError: + pass + else: + w_value = cell.invalidate() + cell = impl.content[name] = ModuleCell(w_value) + + def setitem(self, w_key, w_value): + space = self.space + if space.is_w(space.type(w_key), space.w_str): + return self.setitem_str(w_key, w_value) + else: + return self._as_rdict().setitem(w_key, w_value) + + def setitem_str(self, w_key, w_value, shadows_type=True): + name = self.space.str_w(w_key) + self.getcell(name).w_value = w_value + + if name in self.unshadowed_builtins: + self.invalidate_unshadowed_builtin(name) + del self.unshadowed_builtins[name] + + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + cell = self.getcell(key, False) + cell.invalidate() + del self.content[key] + return self + elif _is_sane_hash(space, w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def length(self): + return len(self.content) + + def get(self, w_lookup): + space = self.space + w_lookup_type = space.type(w_lookup) + if space.is_w(w_lookup_type, space.w_str): + try: + return self.getcell(space.str_w(w_lookup), False).w_value + except KeyError: + return None + elif _is_sane_hash(space, w_lookup_type): + return None + else: + return self._as_rdict().get(w_lookup) + + def iteritems(self): + return ModuleDictItemIteratorImplementation(self.space, self) + + def iterkeys(self): + return ModuleDictKeyIteratorImplementation(self.space, self) + + def itervalues(self): + return ModuleDictValueIteratorImplementation(self.space, self) + + def keys(self): + space = self.space + return [space.wrap(key) for key in self.content.iterkeys()] + + def values(self): + return [cell.w_value for cell in self.content.itervalues()] + + def items(self): + space = self.space + return [space.newtuple([space.wrap(key), cell.w_value]) + for (key, cell) in self.content.iteritems()] + + def _as_rdict(self): + newimpl = self.space.DefaultDictImpl(self.space) + for k, cell in self.content.iteritems(): + newimpl.setitem(self.space.wrap(k), cell.w_value) + cell.invalidate() + for k in self.unshadowed_builtins: + self.invalidate_unshadowed_builtin(k) + return newimpl + +# grrrrr. just a copy-paste from StrKeyIteratorImplementation in dictmultiobject +class ModuleDictKeyIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iterkeys() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key in self.iterator: + return self.space.wrap(key) + else: + return None + +class ModuleDictValueIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.itervalues() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for cell in self.iterator: + return cell.w_value + else: + return None + +class ModuleDictItemIteratorImplementation(IteratorImplementation): + def __init__(self, space, dictimplementation): + IteratorImplementation.__init__(self, space, dictimplementation) + self.iterator = dictimplementation.content.iteritems() + + def next_entry(self): + # note that this 'for' loop only runs once, at most + for key, cell in self.iterator: + return self.space.newtuple([self.space.wrap(key), cell.w_value]) + else: + return None + + + + + + + +class State(object): + def __init__(self, space): + self.space = space + self.invalidcell = ModuleCell() + self.always_invalid_cache = [] + self.neverused_dictimpl = ModuleDictImplementation(space) + +class GlobalCacheHolder(object): + def __init__(self, space): + self.cache = None + state = space.fromcache(State) + self.dictimpl = state.neverused_dictimpl + + def getcache(self, space, code, w_globals): + implementation = getimplementation(w_globals) + if self.dictimpl is implementation: + return self.cache + return self.getcache_slow(space, code, w_globals, implementation) + getcache._always_inline_ = True + + def getcache_slow(self, space, code, w_globals, implementation): + state = space.fromcache(State) + if not isinstance(implementation, ModuleDictImplementation): + missing_length = max(len(code.co_names_w) - len(state.always_invalid_cache), 0) + state.always_invalid_cache.extend([state.invalidcell] * missing_length) + cache = state.always_invalid_cache + else: + cache = [state.invalidcell] * len(code.co_names_w) + self.cache = cache + self.dictimpl = implementation + return cache + getcache_slow._dont_inline_ = True + +def init_code(code): + code.globalcacheholder = GlobalCacheHolder(code.space) + + +def get_global_cache(space, code, w_globals): + from pypy.interpreter.pycode import PyCode + if not isinstance(code, PyCode): + return [] + holder = code.globalcacheholder + return holder.getcache(space, code, w_globals) + +def getimplementation(w_dict): + if type(w_dict) is W_DictMultiObject: + return w_dict.implementation + else: + return None + +def LOAD_GLOBAL(f, nameindex, *ignored): + cell = f.cache_for_globals[nameindex] + w_value = cell.w_value + if w_value is None: + # slow path + w_value = load_global_fill_cache(f, nameindex) + f.pushvalue(w_value) +LOAD_GLOBAL._always_inline_ = True + +def find_cell_from_dict(implementation, name): + if isinstance(implementation, ModuleDictImplementation): + try: + return implementation.getcell(name, False) + except KeyError: + return None + return None + +def load_global_fill_cache(f, nameindex): + name = f.space.str_w(f.getname_w(nameindex)) + implementation = getimplementation(f.w_globals) + if isinstance(implementation, ModuleDictImplementation): + cell = find_cell_from_dict(implementation, name) + if cell is None: + builtin_impl = getimplementation(f.get_builtin().getdict()) + cell = find_cell_from_dict(builtin_impl, name) + if cell is not None: + implementation.add_unshadowed_builtin(name, builtin_impl) + + if cell is not None: + f.cache_for_globals[nameindex] = cell + return cell.w_value + return f._load_global(f.getname_w(nameindex)) +load_global_fill_cache._dont_inline_ = True Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/trunk/pypy/objspace/std/dictmultiobject.py Wed May 27 14:03:00 2009 @@ -865,7 +865,6 @@ else: return None - import time, py class DictInfo(object): @@ -1038,8 +1037,11 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space, wary=False, sharing=False): - if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: + def __init__(w_self, space, wary=False, sharing=False, module=False): + if space.config.objspace.std.withcelldict and wary: + from pypy.objspace.std.celldict import ModuleDictImplementation + w_self.implementation = ModuleDictImplementation(space) + elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: w_self.implementation = WaryDictImplementation(space) elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) Modified: pypy/trunk/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/pypy/objspace/std/objspace.py Wed May 27 14:03:00 2009 @@ -72,7 +72,16 @@ # Import all the object types and implementations self.model = StdTypeModel(self.config) + from pypy.objspace.std.celldict import get_global_cache + class StdObjSpaceFrame(pyframe.PyFrame): + if self.config.objspace.std.withcelldict: + def __init__(self, space, code, w_globals, closure): + pyframe.PyFrame.__init__(self, space, code, w_globals, closure) + self.cache_for_globals = get_global_cache(space, code, w_globals) + + from pypy.objspace.std.celldict import LOAD_GLOBAL + if self.config.objspace.std.optimized_int_add: if self.config.objspace.std.withsmallint: def BINARY_ADD(f, oparg, *ignored): @@ -580,8 +589,8 @@ from pypy.objspace.std.listobject import W_ListObject return W_ListObject(list_w) - def newdict(self, track_builtin_shadowing=False): - if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing: + def newdict(self, module=False): + if self.config.objspace.std.withmultidict and module: from pypy.objspace.std.dictmultiobject import W_DictMultiObject return W_DictMultiObject(self, wary=True) return self.DictObjectCls(self) Added: pypy/trunk/pypy/objspace/std/test/test_celldict.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/objspace/std/test/test_celldict.py Wed May 27 14:03:00 2009 @@ -0,0 +1,259 @@ +from pypy.conftest import gettestobjspace +from pypy.objspace.std.celldict import get_global_cache, ModuleCell, ModuleDictImplementation +from pypy.interpreter import gateway + +# this file tests mostly the effects of caching global lookup. The dict +# implementation itself is tested in test_dictmultiobject.py + + +class AppTestCellDict(object): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withcelldict": True}) + cls.w_impl_used = cls.space.appexec([], """(): + import __pypy__ + def impl_used(obj): + assert "ModuleDictImplementation" in __pypy__.internal_repr(obj) + return impl_used + """) + def is_in_cache(space, w_code, w_globals, w_name): + name = space.str_w(w_name) + cache = get_global_cache(space, w_code, w_globals) + index = [space.str_w(w_n) for w_n in w_code.co_names_w].index(name) + return space.wrap(cache[index].w_value is not None) + is_in_cache = gateway.interp2app(is_in_cache) + cls.w_is_in_cache = cls.space.wrap(is_in_cache) + stored_builtins = [] + def rescue_builtins(space): + w_dict = space.builtin.getdict() + content = {} + for key, cell in w_dict.implementation.content.iteritems(): + newcell = ModuleCell() + newcell.w_value = cell.w_value + content[key] = newcell + stored_builtins.append(content) + rescue_builtins = gateway.interp2app(rescue_builtins) + cls.w_rescue_builtins = cls.space.wrap(rescue_builtins) + def restore_builtins(space): + w_dict = space.builtin.getdict() + if not isinstance(w_dict.implementation, ModuleDictImplementation): + w_dict.implementation = ModuleDictImplementation(space) + w_dict.implementation.content = stored_builtins.pop() + restore_builtins = gateway.interp2app(restore_builtins) + cls.w_restore_builtins = cls.space.wrap(restore_builtins) + + def test_same_code_in_different_modules(self): + import sys + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + mod2 = type(sys)("abc") + self.impl_used(mod2.__dict__) + glob2 = mod2.__dict__ + def f(): + return x + 1 + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = 1 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + mod1.x = 2 + assert f1() == 3 + assert self.is_in_cache(code, glob1, "x") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "x") + f2 = type(f)(code, glob2) + mod2.x = 5 + assert not self.is_in_cache(code, glob2, "x") + assert f2() == 6 + assert self.is_in_cache(code, glob2, "x") + assert f2() == 6 + assert self.is_in_cache(code, glob2, "x") + mod2.x = 7 + assert f2() == 8 + assert self.is_in_cache(code, glob2, "x") + assert f2() == 8 + assert self.is_in_cache(code, glob2, "x") + + def test_override_builtins(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + return len(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 0 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + assert f1() == 0 + mod1.x.append(1) + assert f1() == 1 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + mod1.len = lambda x: 15 + assert not self.is_in_cache(code, glob1, "len") + mod1.x.append(1) + assert f1() == 15 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 15 + assert self.is_in_cache(code, glob1, "len") + del mod1.len + mod1.x.append(1) + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 3 + assert self.is_in_cache(code, glob1, "len") + orig_len = __builtins__.len + try: + __builtins__.len = lambda x: 12 + mod1.x.append(1) + assert self.is_in_cache(code, glob1, "len") + assert f1() == 12 + assert self.is_in_cache(code, glob1, "len") + assert f1() == 12 + assert self.is_in_cache(code, glob1, "len") + finally: + __builtins__.len = orig_len + + def test_override_builtins2(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + return l(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + __builtin__.l = len + try: + assert not self.is_in_cache(code, glob1, "l") + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 0 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + assert f1() == 0 + mod1.x.append(1) + assert f1() == 1 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + del __builtin__.l + mod1.l = len + mod1.x.append(1) + assert not self.is_in_cache(code, glob1, "l") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "l") + assert self.is_in_cache(code, glob1, "x") + finally: + if hasattr(__builtins__, "l"): + del __builtins__.l + + def test_generator(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + glob1 = mod1.__dict__ + self.impl_used(mod1.__dict__) + def f(): + yield 1 + yield x + yield len(x) + code = f.func_code + f1 = type(f)(f.func_code, glob1) + mod1.x = [] + gen = f1() + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v == 1 + assert not self.is_in_cache(code, glob1, "len") + assert not self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v is mod1.x + assert not self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + v = gen.next() + assert v == 0 + assert self.is_in_cache(code, glob1, "len") + assert self.is_in_cache(code, glob1, "x") + + def test_degenerate_to_rdict(self): + import sys + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + def f(): + return x + 1 + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = 1 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + glob1[1] = 2 + assert not self.is_in_cache(code, glob1, "x") + assert f1() == 2 + assert not self.is_in_cache(code, glob1, "x") + + def test_degenerate_builtin_to_rdict(self): + import sys, __builtin__ + mod1 = type(sys)("abc") + self.impl_used(mod1.__dict__) + glob1 = mod1.__dict__ + def f(): + return len(x) + code = f.func_code + f1 = type(f)(code, glob1) + mod1.x = [1, 2] + assert not self.is_in_cache(code, glob1, "x") + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 2 + assert self.is_in_cache(code, glob1, "x") + assert self.is_in_cache(code, glob1, "len") + self.rescue_builtins() + try: + __builtin__.__dict__[1] = 2 + assert not self.is_in_cache(code, glob1, "len") + assert f1() == 2 + assert not self.is_in_cache(code, glob1, "len") + finally: + self.restore_builtins() + + def test_mapping_as_locals(self): + import sys + if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'): + skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements") + class M(object): + def __getitem__(self, key): + return key + def __setitem__(self, key, value): + self.result[key] = value + m = M() + m.result = {} + exec "x=m" in {}, m + assert m.result == {'x': 'm'} + exec "y=n" in m # NOTE: this doesn't work in CPython 2.4 + assert m.result == {'x': 'm', 'y': 'n'} + + def test_subclass_of_dict_as_locals(self): + import sys + if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'): + skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements") + class M(dict): + def __getitem__(self, key): + return key + def __setitem__(self, key, value): + dict.__setitem__(self, key, value) + m = M() + exec "x=m" in {}, m + assert m == {'x': 'm'} + exec "y=n" in m # NOTE: this doesn't work in CPython 2.4 + assert m == {'x': 'm', 'y': 'n'} + Modified: pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py Wed May 27 14:03:00 2009 @@ -3,6 +3,8 @@ W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \ EmptyDictImplementation, RDictImplementation, StrDictImplementation, \ SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation + +from pypy.objspace.std.celldict import ModuleDictImplementation from pypy.conftest import gettestobjspace from pypy.objspace.std.test import test_dictobject @@ -58,6 +60,26 @@ a.__dict__.items() == [("abc", 12)] +class AppTestModuleDict(object): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withcelldict": True}) + cls.w_impl_used = cls.space.appexec([], """(): + import __pypy__ + def impl_used(obj): + assert "ModuleDictImplementation" in __pypy__.internal_repr(obj) + return impl_used + """) + + + def test_check_module_uses_module_dict(self): + m = type(__builtins__)("abc") + self.impl_used(m.__dict__) + + def test_key_not_there(self): + d = type(__builtins__)("abc").__dict__ + raises(KeyError, "d['def']") + + class TestW_DictSmall(test_dictobject.TestW_DictObject): def setup_class(cls): @@ -233,3 +255,15 @@ def get_impl(self): return self.ImplementionClass(self.space, self.string, self.string2) + +class TestModuleDictImplementation(TestRDictImplementation): + ImplementionClass = ModuleDictImplementation + EmptyClass = ModuleDictImplementation + +class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation): + ImplementionClass = ModuleDictImplementation + EmptyClass = ModuleDictImplementation + + string = "int" + string2 = "isinstance" + Modified: pypy/trunk/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_dictobject.py Wed May 27 14:03:00 2009 @@ -489,6 +489,7 @@ FakeSpace.config.objspace.std.withdictmeasurement = False FakeSpace.config.objspace.std.withsharingdict = False FakeSpace.config.objspace.std.withsmalldicts = False +FakeSpace.config.objspace.std.withcelldict = False FakeSpace.config.objspace.opcodes = Config() FakeSpace.config.objspace.opcodes.CALL_LIKELY_BUILTIN = False Modified: pypy/trunk/pypy/translator/microbench/test_count1.py ============================================================================== --- pypy/trunk/pypy/translator/microbench/test_count1.py (original) +++ pypy/trunk/pypy/translator/microbench/test_count1.py Wed May 27 14:03:00 2009 @@ -201,3 +201,15 @@ y = y + 1 c += 1 +def test_count_with_True(): + x = 0 + n = N + while x < n: + x = x + True + +increment = 1 +def test_count_with_global_increment(): + x = 0 + n = N + while x < n: + x = x + increment From cfbolz at codespeak.net Wed May 27 14:03:21 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 14:03:21 +0200 (CEST) Subject: [pypy-svn] r65445 - pypy/branch/speedup-global2 Message-ID: <20090527120321.6C3FB169F85@codespeak.net> Author: cfbolz Date: Wed May 27 14:03:21 2009 New Revision: 65445 Removed: pypy/branch/speedup-global2/ Log: kill merged branch From cfbolz at codespeak.net Wed May 27 14:03:36 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 14:03:36 +0200 (CEST) Subject: [pypy-svn] r65446 - pypy/branch/speedup-globals Message-ID: <20090527120336.764A1169F8A@codespeak.net> Author: cfbolz Date: Wed May 27 14:03:35 2009 New Revision: 65446 Removed: pypy/branch/speedup-globals/ Log: kill precursor of merged branch From cfbolz at codespeak.net Wed May 27 14:16:23 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 14:16:23 +0200 (CEST) Subject: [pypy-svn] r65447 - pypy/branch/tagged-pointers-framework/pypy/rlib/test Message-ID: <20090527121623.622DC169EEF@codespeak.net> Author: cfbolz Date: Wed May 27 14:16:22 2009 New Revision: 65447 Modified: pypy/branch/tagged-pointers-framework/pypy/rlib/test/test_objectmodel.py Log: forgot to fix a test Modified: pypy/branch/tagged-pointers-framework/pypy/rlib/test/test_objectmodel.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rlib/test/test_objectmodel.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rlib/test/test_objectmodel.py Wed May 27 14:16:22 2009 @@ -124,13 +124,13 @@ __slots__ = 'smallint' assert C(17).smallint == 17 - assert C(17).getvalue() == 17 + assert C(17).get_untagged_value() == 17 class A(UnboxedValue): __slots__ = ['value'] assert A(12098).value == 12098 - assert A(12098).getvalue() == 12098 + assert A(12098).get_untagged_value() == 12098 def test_symbolic(): py.test.skip("xxx no test here") From cfbolz at codespeak.net Wed May 27 14:18:40 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 14:18:40 +0200 (CEST) Subject: [pypy-svn] r65448 - pypy/branch/tagged-pointers-framework/pypy/translator/c/test Message-ID: <20090527121840.824DB169F6B@codespeak.net> Author: cfbolz Date: Wed May 27 14:18:39 2009 New Revision: 65448 Modified: pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_rtagged.py Log: fix another test Modified: pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_rtagged.py Wed May 27 14:18:39 2009 @@ -38,7 +38,7 @@ def entry_point(argv): n = 100 + len(argv) - assert C(n).getvalue() == n + assert C(n).get_untagged_value() == n x = makeint(42) assert isinstance(x, C) @@ -67,7 +67,7 @@ from pypy import conftest def test_tagged_boehm(): - t = Translation(entry_point, standalone=True, gc='boehm') + t = Translation(entry_point, standalone=True, gc='boehm', taggedpointers=True) try: exename = str(t.compile_c()) finally: From cfbolz at codespeak.net Wed May 27 14:41:48 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 14:41:48 +0200 (CEST) Subject: [pypy-svn] r65449 - pypy/trunk/pypy/objspace/std Message-ID: <20090527124148.D7092169F80@codespeak.net> Author: cfbolz Date: Wed May 27 14:41:46 2009 New Revision: 65449 Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py pypy/trunk/pypy/objspace/std/objspace.py Log: Get rid of a superfluous argument to __init__. Thanks Amaury for being wary. Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/trunk/pypy/objspace/std/dictmultiobject.py Wed May 27 14:41:46 2009 @@ -1037,11 +1037,11 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space, wary=False, sharing=False, module=False): - if space.config.objspace.std.withcelldict and wary: + def __init__(w_self, space, module=False, sharing=False): + if space.config.objspace.std.withcelldict and module: from pypy.objspace.std.celldict import ModuleDictImplementation w_self.implementation = ModuleDictImplementation(space) - elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: + elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and module: w_self.implementation = WaryDictImplementation(space) elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) Modified: pypy/trunk/pypy/objspace/std/objspace.py ============================================================================== --- pypy/trunk/pypy/objspace/std/objspace.py (original) +++ pypy/trunk/pypy/objspace/std/objspace.py Wed May 27 14:41:46 2009 @@ -592,7 +592,7 @@ def newdict(self, module=False): if self.config.objspace.std.withmultidict and module: from pypy.objspace.std.dictmultiobject import W_DictMultiObject - return W_DictMultiObject(self, wary=True) + return W_DictMultiObject(self, module=True) return self.DictObjectCls(self) def newslice(self, w_start, w_end, w_step): From afa at codespeak.net Wed May 27 14:49:31 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 27 May 2009 14:49:31 +0200 (CEST) Subject: [pypy-svn] r65450 - pypy/trunk/pypy/config Message-ID: <20090527124931.96331169F94@codespeak.net> Author: afa Date: Wed May 27 14:49:31 2009 New Revision: 65450 Modified: pypy/trunk/pypy/config/pypyoption.py Log: Typo in option description Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Wed May 27 14:49:31 2009 @@ -229,7 +229,7 @@ default=False), BoolOption("withcelldict", - "use dictionaries that are opimized for being used as module dicts", + "use dictionaries that are optimized for being used as module dicts", default=False, requires=[("objspace.std.withmultidict", True), ("objspace.opcodes.CALL_LIKELY_BUILTIN", False), From antocuni at codespeak.net Wed May 27 14:51:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 27 May 2009 14:51:04 +0200 (CEST) Subject: [pypy-svn] r65451 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090527125104.ACF85169F99@codespeak.net> Author: antocuni Date: Wed May 27 14:51:04 2009 New Revision: 65451 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: fix ootype tests Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Wed May 27 14:51:04 2009 @@ -225,7 +225,7 @@ guard_true(i3) fail() """ - pre_op = parse(pre_op, self.cpu, self.namespace) + pre_op = self.parse(pre_op) # cheat pre_op.operations[-2].result.value = 1 expected = """ @@ -249,7 +249,7 @@ guard_true(i3) fail() """ - pre_op = parse(pre_op, self.cpu, self.namespace) + pre_op = self.parse(pre_op) expected = """ [p0, i0] p1 = getfield_gc(p0, descr=list_desc) @@ -370,5 +370,4 @@ pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - def setup_class(cls): - py.test.skip("XXX") + pass From cfbolz at codespeak.net Wed May 27 15:02:22 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 15:02:22 +0200 (CEST) Subject: [pypy-svn] r65452 - pypy/branch/tagged-pointers-framework/pypy/doc/config Message-ID: <20090527130222.45A3C169EBC@codespeak.net> Author: cfbolz Date: Wed May 27 15:02:21 2009 New Revision: 65452 Added: pypy/branch/tagged-pointers-framework/pypy/doc/config/translation.taggedpointers.txt (contents, props changed) Log: add documentation Added: pypy/branch/tagged-pointers-framework/pypy/doc/config/translation.taggedpointers.txt ============================================================================== --- (empty file) +++ pypy/branch/tagged-pointers-framework/pypy/doc/config/translation.taggedpointers.txt Wed May 27 15:02:21 2009 @@ -0,0 +1,3 @@ +Enable tagged pointers. This option is mostly useful for the Smalltalk and +Prolog interpreters. For the Python interpreter the option +:config:`objspace.std.withsmallint` should be used. From cfbolz at codespeak.net Wed May 27 15:03:15 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 15:03:15 +0200 (CEST) Subject: [pypy-svn] r65453 - pypy/branch/tagged-pointers-framework/pypy/lang/smalltalk Message-ID: <20090527130315.37F95169EBC@codespeak.net> Author: cfbolz Date: Wed May 27 15:03:14 2009 New Revision: 65453 Modified: pypy/branch/tagged-pointers-framework/pypy/lang/smalltalk/model.py Log: Adapt smalltalk vm to make the translation.taggedpointers option do something. Modified: pypy/branch/tagged-pointers-framework/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/lang/smalltalk/model.py Wed May 27 15:03:14 2009 @@ -19,7 +19,7 @@ from pypy.rlib.rarithmetic import intmask from pypy.lang.smalltalk import constants, error from pypy.tool.pairtype import extendabletype -from pypy.rlib.objectmodel import instantiate +from pypy.rlib.objectmodel import instantiate, UnboxedValue from pypy.lang.smalltalk.tool.bitmanipulation import splitter class W_Object(object): @@ -96,14 +96,15 @@ False means swapping failed""" return False -class W_SmallInteger(W_Object): + +# the UnboxedValue mixin means the object can potentially be stored in unboxed +# form + +class W_SmallInteger(W_Object, UnboxedValue): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? __slots__ = ('value',) # the only allowed slot here - def __init__(self, value): - self.value = value - def getclass(self, space): """Return SmallInteger from special objects array.""" return space.w_SmallInteger From cfbolz at codespeak.net Wed May 27 15:04:33 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 15:04:33 +0200 (CEST) Subject: [pypy-svn] r65454 - in pypy/branch/tagged-pointers-framework/pypy: rpython/memory/gctransform translator/c/gcc/test Message-ID: <20090527130433.A348A169E9A@codespeak.net> Author: cfbolz Date: Wed May 27 15:04:33 2009 New Revision: 65454 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py Log: Fix asmgcroot stack walker in conjunction with tagged pointers. Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py Wed May 27 15:04:33 2009 @@ -154,7 +154,7 @@ if location == 0: break addr = self.getlocation(callee, location) - if addr.address[0] != llmemory.NULL: + if gc.points_to_valid_gc_object(addr): collect_stack_root(gc, addr) # # track where the caller_frame saved the registers from its own Modified: pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py Wed May 27 15:04:33 2009 @@ -14,7 +14,7 @@ # instructions: should_be_moving = False - def getcompiled(self, func): + def getcompiled(self, func, **extraargs): def main(argv): try: res = func() @@ -30,6 +30,7 @@ config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy config.translation.gcrootfinder = "asmgcc" + config.set(**extraargs) t = TranslationContext(config=config) self.t = t a = t.buildannotator() From antocuni at codespeak.net Wed May 27 15:52:38 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 27 May 2009 15:52:38 +0200 (CEST) Subject: [pypy-svn] r65455 - in pypy/branch/pyjitpl5-experiments/pypy: jit/backend jit/backend/cli jit/metainterp jit/tl translator translator/oosupport Message-ID: <20090527135238.12C5C169F52@codespeak.net> Author: antocuni Date: Wed May 27 15:52:37 2009 New Revision: 65455 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/detect_cpu.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/warmspot.py pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py pypy/branch/pyjitpl5-experiments/pypy/jit/tl/targetpypyjit.py pypy/branch/pyjitpl5-experiments/pypy/translator/driver.py pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/constant.py Log: make it possible to translate targetpypyjit with the cli backend Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py Wed May 27 15:52:37 2009 @@ -241,7 +241,7 @@ return dotnet.classof(System.Double) ## elif T is ootype.String: ## return dotnet.classof(System.String) - elif T is ootype.Char: + elif T in (ootype.Char, ootype.UniChar): return dotnet.classof(System.Char) elif isinstance(T, ootype.OOType): return ootype.runtimeClass(T) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/detect_cpu.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/detect_cpu.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/detect_cpu.py Wed May 27 15:52:37 2009 @@ -47,6 +47,8 @@ from pypy.jit.backend.x86.runner import CPU elif backend_name == 'minimal': from pypy.jit.backend.minimal.runner import LLtypeCPU as CPU + elif backend_name == 'cli': + from pypy.jit.backend.cli.runner import CliCPU as CPU else: raise ProcessorAutodetectError, "unsupported cpu '%s'" % backend_name return CPU Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/warmspot.py Wed May 27 15:52:37 2009 @@ -30,6 +30,7 @@ def apply_jit(translator, backend_name="auto", **kwds): from pypy.jit.metainterp.simple_optimize import Optimizer + #from pypy.jit.metainterp.optimize2 import Optimizer if 'CPUClass' not in kwds: from pypy.jit.backend.detect_cpu import getcpuclass kwds['CPUClass'] = getcpuclass(backend_name) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/tl/pypyjit_demo.py Wed May 27 15:52:37 2009 @@ -7,12 +7,17 @@ def simple_loop(): print "simple loop" + import time i = 0 N = 100 + #N = 10000000 step = 3 + start = time.clock() while i < N: i = i + step + end = time.clock() print i + print end-start, 'seconds' def g(i): for k in range(i, i +2): @@ -24,7 +29,8 @@ try: #do() - loop() + #loop() + simple_loop() print "---ending 2---" except BaseException, e: print "---ending 0---" Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/tl/targetpypyjit.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/tl/targetpypyjit.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/tl/targetpypyjit.py Wed May 27 15:52:37 2009 @@ -65,8 +65,15 @@ config.objspace.usemodules.pypyjit = True config.objspace.usemodules._weakref = False config.objspace.usemodules._sre = False - config.objspace.std.multimethods = 'mrd' - multimethod.Installer = multimethod.InstallerVersion2 + if config.translation.type_system == 'lltype': + config.objspace.std.multimethods = 'mrd' + multimethod.Installer = multimethod.InstallerVersion2 + else: + from pypy.rlib import jit + jit.PARAMETERS['hash_bits'] = 6 # XXX: this is a hack, should be fixed at some point + config.objspace.std.multimethods = 'doubledispatch' + multimethod.Installer = multimethod.InstallerVersion1 + config.objspace.std.builtinshortcut = True config.objspace.opcodes.CALL_LIKELY_BUILTIN = True config.objspace.std.withrangelist = True @@ -76,6 +83,7 @@ w_dict = space.newdict() return entry_point, None, PyPyAnnotatorPolicy(single_space = space) + def jitpolicy(driver): """Returns the JIT policy to use when translating.""" from pypy.module.pypyjit.policy import PyPyJitPolicy Modified: pypy/branch/pyjitpl5-experiments/pypy/translator/driver.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/translator/driver.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/translator/driver.py Wed May 27 15:52:37 2009 @@ -369,6 +369,20 @@ [RTYPE], "Backendopt before jitting") + def task_prejitbackendopt_ootype(self): + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(self.translator, + inline_threshold=0, + merge_if_blocks=True, + constfold=False, # XXX? + raisingop2direct_call=False, + remove_asserts=False) + # + task_prejitbackendopt_ootype = taskdef( + task_prejitbackendopt_ootype, + [OOTYPE], + "Backendopt before jitting") + def task_pyjitpl_lltype(self): get_policy = self.extra['jitpolicy'] self.jitpolicy = get_policy(self) @@ -383,6 +397,20 @@ [RTYPE, '?prejitbackendopt_lltype'], "JIT compiler generation") + def task_pyjitpl_ootype(self): + get_policy = self.extra['jitpolicy'] + self.jitpolicy = get_policy(self) + # + from pypy.jit.metainterp.warmspot import apply_jit + apply_jit(self.translator, policy=self.jitpolicy, + backend_name='cli') #XXX + # + self.log.info("the JIT compiler was generated") + # + task_pyjitpl_ootype = taskdef(task_pyjitpl_ootype, + [OOTYPE, '?prejitbackendopt_ootype'], + "JIT compiler generation") + def task_backendopt_lltype(self): from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(self.translator) Modified: pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/translator/oosupport/constant.py Wed May 27 15:52:37 2009 @@ -28,7 +28,7 @@ from pypy.rpython.ootypesystem import ootype import operator -MAX_CONST_PER_STEP = 100 +MAX_CONST_PER_STEP = 50 PRIMITIVE_TYPES = set([ootype.Void, ootype.Bool, ootype.Char, ootype.UniChar, ootype.Float, ootype.Signed, ootype.Unsigned, From cfbolz at codespeak.net Wed May 27 15:59:42 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 27 May 2009 15:59:42 +0200 (CEST) Subject: [pypy-svn] r65456 - pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem Message-ID: <20090527135942.ECBE5169F90@codespeak.net> Author: cfbolz Date: Wed May 27 15:59:42 2009 New Revision: 65456 Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py Log: Be more precise about getting the type of tagged-or-normal-or-None. Gets rid of a lot of warnings when translating. Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py Wed May 27 15:59:42 2009 @@ -81,9 +81,11 @@ vinst = llops.genop('cast_pointer', [vinst], resulttype=self.common_repr()) if can_be_tagged: - # XXX do we care about optimizing the case where vinst cannot - # be None here? - return llops.gendirectcall(ll_unboxed_getclass, vinst, + if can_be_none: + func = ll_unboxed_getclass_canbenone + else: + func = ll_unboxed_getclass + return llops.gendirectcall(func, vinst, cunboxedcls) elif can_be_none: return llops.gendirectcall(ll_inst_type, vinst) @@ -146,13 +148,15 @@ def ll_unboxed_to_int(p): return lltype.cast_ptr_to_int(p) >> 1 +def ll_unboxed_getclass_canbenone(instance, class_if_unboxed): + if instance: + return ll_unboxed_getclass(instance, class_if_unboxed) + return lltype.nullptr(lltype.typeOf(instance).TO.typeptr.TO) + def ll_unboxed_getclass(instance, class_if_unboxed): if lltype.cast_ptr_to_int(instance) & 1: return class_if_unboxed - elif instance: - return instance.typeptr - else: - return lltype.nullptr(lltype.typeOf(instance).TO.typeptr.TO) + return instance.typeptr def ll_unboxed_isinstance_const(obj, minid, maxid, answer_if_unboxed): if not obj: From david at codespeak.net Wed May 27 17:16:34 2009 From: david at codespeak.net (david at codespeak.net) Date: Wed, 27 May 2009 17:16:34 +0200 (CEST) Subject: [pypy-svn] r65457 - pypy/branch/io-lang/pypy/lang/io Message-ID: <20090527151634.7D90C169F6B@codespeak.net> Author: david Date: Wed May 27 17:16:32 2009 New Revision: 65457 Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.py Log: Removed debug print Modified: pypy/branch/io-lang/pypy/lang/io/parserhack.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/parserhack.py (original) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.py Wed May 27 17:16:32 2009 @@ -10,7 +10,7 @@ child_in.write(input) child_in.close() s = child_out_err.read().strip() - print s + # print s return eval(s) def interpret(code): From david at codespeak.net Wed May 27 17:18:09 2009 From: david at codespeak.net (david at codespeak.net) Date: Wed, 27 May 2009 17:18:09 +0200 (CEST) Subject: [pypy-svn] r65458 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090527151809.EF862169F82@codespeak.net> Author: david Date: Wed May 27 17:18:09 2009 New Revision: 65458 Modified: pypy/branch/io-lang/pypy/lang/io/list.py pypy/branch/io-lang/pypy/lang/io/test/test_list.py Log: (cfbolz, david) List foreach implementation Modified: pypy/branch/io-lang/pypy/lang/io/list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/list.py Wed May 27 17:18:09 2009 @@ -9,4 +9,31 @@ @register_method('List', 'at', unwrap_spec=[object, int]) def list_at(space, target, argument): - return target[argument] \ No newline at end of file + return target[argument] + + at register_method('List', 'foreach') +def list_foreach(space, w_target, w_message, w_context): + argcount = len(w_message.arguments) + assert argcount > 0 + + body = w_message.arguments[-1] + if argcount == 3: + key = w_message.arguments[0].name + value = w_message.arguments[1].name + + for i in range(len(w_target.items)): + w_context.slots[key] = W_Number(space, i) + w_context.slots[value] = w_target.items[i] + t = body.eval(space, w_context, w_context) + elif argcount == 2: + value = w_message.arguments[0].name + + for i in range(len(w_target.items)): + w_context.slots[value] = w_target.items[i] + t = body.eval(space, w_context, w_context) + + elif argcount == 1: + for i in range(len(w_target.items)): + t = body.eval(space, w_context, w_context) + + return t \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_list.py Wed May 27 17:18:09 2009 @@ -46,4 +46,29 @@ inp = 'a := list(1,2,3); a at("2")' # Unspecified exception until error handling are introduced assert py.test.raises(Exception, 'interpret(inp)') - \ No newline at end of file + +def test_list_foreach_key_value_returns_last(): + inp = 'a := list(1, 2, 3); a foreach(key, value, key+value)' + res,space = interpret(inp) + assert res.value == 5 + +def test_list_foreach_value_returns_last(): + inp = 'c := 99; a := list(1, 2, 3); a foreach(value, c)' + res,space = interpret(inp) + assert res.value == 99 + +def test_list_foreach_wo_args_returns_last(): + inp = 'c := 99; a := list(1, 2, 3); a foreach(c)' + res,space = interpret(inp) + assert res.value == 99 + +def test_list_key_value(): + inp = 'b := list(); a := list(99, 34); a foreach(key, value, b append(list(key, value))); b' + res,space = interpret(inp) + value = [(x.items[0].value, x.items[1].value) for x in res.items] + assert value == [(0, 99), (1, 34)] + +def test_list_foreach_leaks_variables(): + inp = 'b := list(); a := list(99, 34); a foreach(key, value, b append(list(key, value))); key+value' + res,space = interpret(inp) + assert res.value == 35 \ No newline at end of file From david at codespeak.net Wed May 27 17:32:15 2009 From: david at codespeak.net (david at codespeak.net) Date: Wed, 27 May 2009 17:32:15 +0200 (CEST) Subject: [pypy-svn] r65459 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090527153215.8C4C4169EDF@codespeak.net> Author: david Date: Wed May 27 17:32:13 2009 New Revision: 65459 Modified: pypy/branch/io-lang/pypy/lang/io/list.py pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/test/test_list.py Log: (cfbolz, david) fixed list append operation Modified: pypy/branch/io-lang/pypy/lang/io/list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/list.py Wed May 27 17:32:13 2009 @@ -3,8 +3,8 @@ @register_method('List', 'append') def list_append(space, w_target, w_message, w_context): assert w_message.arguments, 'requires at least one argument' - w_items = [x.eval(space, w_target, w_context) for x in w_message.arguments] - w_target.append(w_items) + items_w = [x.eval(space, w_target, w_context) for x in w_message.arguments] + w_target.extend(items_w) return w_target @register_method('List', 'at', unwrap_spec=[object, int]) Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Wed May 27 17:32:13 2009 @@ -55,8 +55,8 @@ W_Object.__init__(self, space, protos) self.items = items - def append(self, w_items): - self.items += w_items + def extend(self, items_w): + self.items.extend(items_w) def __getitem__(self, index): try: Modified: pypy/branch/io-lang/pypy/lang/io/test/test_list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_list.py Wed May 27 17:32:13 2009 @@ -26,6 +26,15 @@ inp = "a := list(); a append(1)" res,space = interpret(inp) assert res.items == [W_Number(space, 1)] + +def test_list_append_multiple(): + inp = "a := list(1,2); a append(3,4,5)" + res,space = interpret(inp) + assert res.items == [W_Number(space, 1), + W_Number(space, 2), + W_Number(space, 3), + W_Number(space, 4), + W_Number(space, 5)] def test_list_at(): inp = "a := list(1,2,3); a at(2)" From fijal at codespeak.net Wed May 27 18:22:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 18:22:56 +0200 (CEST) Subject: [pypy-svn] r65460 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph Message-ID: <20090527162256.2E964169F92@codespeak.net> Author: fijal Date: Wed May 27 18:22:55 2009 New Revision: 65460 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Log: ignore guard_nonvirtualized, with explanation Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/llimpl.py Wed May 27 18:22:55 2009 @@ -555,6 +555,11 @@ def op_guard_nonvirtualized(self, for_accessing_field, value, expected_class=None): + # XXX + # We completely ignore guard_nonvirtualized + # right now, nobody can devirtualize a virtualizable anyway + # and we abuse guard_nonvirtualized for propagating properties + return if expected_class is not None: self.op_guard_class(-1, value, expected_class) if heaptracker.cast_vable(value).vable_rti: From fijal at codespeak.net Wed May 27 18:25:50 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 18:25:50 +0200 (CEST) Subject: [pypy-svn] r65461 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090527162550.AD680169F98@codespeak.net> Author: fijal Date: Wed May 27 18:25:50 2009 New Revision: 65461 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py Log: Fix graphpage Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py Wed May 27 18:25:50 2009 @@ -138,7 +138,7 @@ while True: op = operations[opindex] lines.append(repr(op)) - if op.is_guard(): + if op.is_guard() and op.opnum != rop.GUARD_NONVIRTUALIZED: tgt = op.suboperations[0] tgt_g, tgt_i = self.all_operations[tgt] self.genedge((graphindex, opstartindex), From fijal at codespeak.net Wed May 27 21:47:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 21:47:46 +0200 (CEST) Subject: [pypy-svn] r65462 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090527194746.21EC6169F94@codespeak.net> Author: fijal Date: Wed May 27 21:47:39 2009 New Revision: 65462 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: kill old tests Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Wed May 27 21:47:39 2009 @@ -308,62 +308,6 @@ """ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), expected) - - - def test_remove_consecutive_guard_value_constfold(self): - py.test.skip("not yet") - n = BoxInt(0) - n1 = BoxInt(1) - n2 = BoxInt(3) - ops = [ - ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), - ResOperation(rop.INT_ADD, [n, ConstInt(1)], n1), - ResOperation(rop.GUARD_VALUE, [n1, ConstInt(1)], None), - ResOperation(rop.INT_ADD, [n1, ConstInt(2)], n2), - ] - ops[0].suboperations = [ResOperation(rop.FAIL, [], None)] - ops[2].suboperations = [ResOperation(rop.FAIL, [], None)] - loop = self.newloop([n], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GUARD_VALUE, [n, ConstInt(0)], None), - ]) - - def test_remove_consecutive_getfields(self): - py.test.skip("not yet") - n1 = BoxInt() - n2 = BoxInt() - n3 = BoxInt() - ops = [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.GETFIELD_GC, [self.nodebox], n2, self.nodedescr), - ResOperation(rop.INT_ADD, [n1, n2], n3), - ] - loop = self.newloop([self.nodebox], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.INT_ADD, [n1, n1], n3), - ]) - - def test_setfield_getfield_clean_cache(self): - py.test.skip("not yet") - n1 = BoxInt() - n2 = BoxInt() - n3 = BoxInt() - ops = [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.SETFIELD_GC, [self.nodebox, ConstInt(3)], None, self.nodedescr), - ResOperation(rop.GETFIELD_GC, [self.nodebox], n2, self.nodedescr), - ResOperation(rop.CALL, [n2], None), - ] - loop = self.newloop([self.nodebox], ops) - optimize_loop(None, [], loop) - equaloplists(loop.operations, [ - ResOperation(rop.GETFIELD_GC, [self.nodebox], n1, self.nodedescr), - ResOperation(rop.SETFIELD_GC, [self.nodebox, ConstInt(3)], None, self.nodedescr), - ResOperation(rop.CALL, [ConstInt(3)], None), - ]) class TestLLtype(LLtypeMixin, BaseTestOptimize2): From fijal at codespeak.net Wed May 27 22:02:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 22:02:00 +0200 (CEST) Subject: [pypy-svn] r65463 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090527200200.01F51169FB7@codespeak.net> Author: fijal Date: Wed May 27 22:02:00 2009 New Revision: 65463 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py Log: try to not create a new block for guard_nonvirtualized Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/graphpage.py Wed May 27 22:02:00 2009 @@ -64,7 +64,7 @@ self.block_starters[graphindex] = {0: True} for graphindex, graph in enumerate(self.graphs): for i, op in enumerate(graph.get_operations()): - if op.is_guard(): + if op.is_guard() and op.opnum != rop.GUARD_NONVIRTUALIZED: self.mark_starter(graphindex, i+1) def set_errmsg(self, errmsg): From fijal at codespeak.net Wed May 27 23:27:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 23:27:06 +0200 (CEST) Subject: [pypy-svn] r65464 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090527212706.6275F169FAD@codespeak.net> Author: fijal Date: Wed May 27 23:27:02 2009 New Revision: 65464 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: implement escape analysis (all startboxes do escape as of now) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Wed May 27 23:27:02 2009 @@ -13,7 +13,7 @@ pass class InstanceNode(object): - def __init__(self, source, const=False): + def __init__(self, source, const=False, escaped=False): self.source = source if const: assert isinstance(source, Const) @@ -24,10 +24,11 @@ self.virtualized = False self.allocated_in_loop = False self.vdesc = None + self.escaped = escaped def __repr__(self): flags = '' - #if self.escaped: flags += 'e' + if self.escaped: flags += 'e' #if self.startbox: flags += 's' if self.const: flags += 'c' #if self.virtual: flags += 'v' @@ -41,11 +42,17 @@ def __init__(self, opts): # NOT_RPYTHON self.optimizations = [[] for i in range(rop._LAST)] + self.find_nodes_funcs = [[] for i in range(rop._LAST)] for opt in opts: for opnum, name in opname.iteritems(): meth = getattr(opt, 'optimize_' + name.lower(), None) if meth is not None: self.optimizations[opnum].append(meth) + for opt in opts: + for opnum, name in opname.iteritems(): + meth = getattr(opt, 'find_nodes_' + name.lower(), None) + if meth is not None: + self.find_nodes_funcs[opnum].append(meth) def getnode(self, box): try: @@ -54,7 +61,7 @@ if isinstance(box, Const): node = InstanceNode(box, const=True) else: - node = InstanceNode(box) + node = InstanceNode(box, escaped=True) self.nodes[box] = node return node @@ -65,6 +72,13 @@ def find_nodes(self): for op in self.loop.operations: + res = False + for f in self.find_nodes_funcs[op.opnum]: + res = f(op, self) + if res: + break + if res: + continue if op.is_always_pure(): is_pure = True for arg in op.args: @@ -81,10 +95,13 @@ self.getnode(arg) # default case for box in op.args: - self.getnode(box) + node = self.getnode(box) + if not op.has_no_side_effect() and not op.is_guard(): + node.escaped = True box = op.result if box is not None: node = self.getnode(box) + node.escaped = False if op.opnum == rop.NEW or op.opnum == rop.NEW_WITH_VTABLE: node.allocated_in_loop = True self.nodes[box] = node @@ -190,11 +207,40 @@ class SimpleVirtualizableOpt(object): @staticmethod - def optimize_guard_nonvirtualized(op, spec): + def find_nodes_setfield_gc(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtualized: + return False + field = op.descr + if field not in instnode.vdesc.virtuals: + return False + return True + + @staticmethod + def find_nodes_getfield_gc(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtualized: + return False + field = op.descr + if field not in instnode.vdesc.virtuals: + return False + spec.getnode(op.result).virtualized = True + return False + + @staticmethod + def find_nodes_setarrayitem_gc(op, spec): + return False + + @staticmethod + def find_nodes_guard_nonvirtualized(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.allocated_in_loop: instnode.virtualized = True instnode.vdesc = op.vdesc + return False + + @staticmethod + def optimize_guard_nonvirtualized(op, spec): return True @staticmethod @@ -210,7 +256,6 @@ spec.nodes[op.result] = node return True node = spec.getnode(op.result) - node.virtualized = True instnode.cleanfields[field] = node return False @@ -260,6 +305,12 @@ d[field] = (fieldnode, op.descr) return True +class SimpleVirtualOpt(object): + def optimize_new_with_vtable(op, spec): + xxx + node = spec.getnode(op.result) + node.escaped = False + specializer = Specializer([SimpleVirtualizableOpt(), ConsecutiveGuardClassRemoval()]) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Wed May 27 23:27:02 2009 @@ -9,7 +9,8 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.optimize2 import (optimize_loop, - ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt) + ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt, + SimpleVirtualOpt) from pypy.jit.metainterp.test.test_optimize import ANY from pypy.jit.metainterp.test.oparser import parse @@ -309,6 +310,72 @@ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), expected) + def test_escape_analysis(self): + ops = """ + [i0] + i1 = int_add(i0, i0) + """ + spec = Specializer([]) + loop = self.parse(ops) + optimize_loop(None, [], loop, self.cpu, spec=spec) + assert spec.nodes[loop.operations[0].args[0]].escaped + ops = """ + [p0] + i1 = getfield_gc(p0, descr=field_desc) + i2 = int_add(i1, i1) + """ + spec = Specializer([]) + loop = self.parse(ops) + optimize_loop(None, [], loop, self.cpu, spec=spec) + assert not spec.nodes[loop.operations[0].result].escaped + ops = """ + [p0] + i1 = getfield_gc(p0, descr=field_desc) + fail(i1) + """ + spec = Specializer([]) + loop = self.parse(ops) + optimize_loop(None, [], loop, self.cpu, spec=spec) + assert spec.nodes[loop.operations[0].result].escaped + ops = """ + [p0] + i1 = getfield_gc(p0, descr=field_desc) + guard_true(i1) + fail() + """ + spec = Specializer([]) + loop = self.parse(ops) + optimize_loop(None, [], loop, self.cpu, spec=spec) + assert not spec.nodes[loop.operations[0].result].escaped + + def test_escape_analysis_on_virtualizable(self): + ops = """ + [p0] + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + i1 = getfield_gc(p0, descr=field_desc) + setfield_gc(p0, i1, descr=field_desc) + i2 = int_add(i1, i1) + """ + spec = Specializer([SimpleVirtualizableOpt()]) + loop = self.parse(ops) + optimize_loop(None, [], loop, self.cpu, spec=spec) + assert not spec.nodes[loop.operations[0].result].escaped + +# def test_simple_virtual(self): +# pre_op = """ +# [] +# p0 = new_with_vtable(13, ConstClass(node_vtable)) +# setfield_gc(p0, 1, descr=field_desc) +# i2 = getfield_gc(p0, descr=field_desc) +# fail(i2) +# """ +# expected = """ +# [] +# fail(1) +# """ +# self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), +# expected) class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass From fijal at codespeak.net Wed May 27 23:53:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 27 May 2009 23:53:51 +0200 (CEST) Subject: [pypy-svn] r65465 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090527215351.8A87B169FC1@codespeak.net> Author: fijal Date: Wed May 27 23:53:49 2009 New Revision: 65465 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a super-basic virtual Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Wed May 27 23:53:49 2009 @@ -25,13 +25,14 @@ self.allocated_in_loop = False self.vdesc = None self.escaped = escaped + self.virtual = False 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.virtual: flags += 'v' if self.virtualized: flags += 'V' return "" % (self.source, flags) @@ -94,9 +95,17 @@ for arg in op.suboperations[0].args: self.getnode(arg) # default case + nodes = [] for box in op.args: - node = self.getnode(box) - if not op.has_no_side_effect() and not op.is_guard(): + nodes.append(self.getnode(box)) + if op.has_no_side_effect() or op.is_guard(): + pass + elif (op.opnum in [rop.SETFIELD_GC, rop.SETFIELD_RAW, + rop.SETARRAYITEM_GC]): + for i in range(1, len(nodes)): + nodes[i].escaped = True + else: + for node in nodes: node.escaped = True box = op.result if box is not None: @@ -306,10 +315,32 @@ return True class SimpleVirtualOpt(object): + @staticmethod def optimize_new_with_vtable(op, spec): - xxx node = spec.getnode(op.result) - node.escaped = False + if node.escaped: + return False + node.virtual = True + return True + + @staticmethod + def optimize_setfield_gc(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtual: + return False + field = op.descr + node = spec.getnode(op.args[1]) + instnode.cleanfields[field] = node + return True + + @staticmethod + def optimize_getfield_gc(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtual: + return False + field = op.descr + spec.nodes[op.result] = instnode.cleanfields[field] + return True specializer = Specializer([SimpleVirtualizableOpt(), ConsecutiveGuardClassRemoval()]) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Wed May 27 23:53:49 2009 @@ -362,20 +362,20 @@ optimize_loop(None, [], loop, self.cpu, spec=spec) assert not spec.nodes[loop.operations[0].result].escaped -# def test_simple_virtual(self): -# pre_op = """ -# [] -# p0 = new_with_vtable(13, ConstClass(node_vtable)) -# setfield_gc(p0, 1, descr=field_desc) -# i2 = getfield_gc(p0, descr=field_desc) -# fail(i2) -# """ -# expected = """ -# [] -# fail(1) -# """ -# self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), -# expected) + def test_simple_virtual(self): + pre_op = """ + [] + p0 = new_with_vtable(13, ConstClass(node_vtable)) + setfield_gc(p0, 1, descr=field_desc) + i2 = getfield_gc(p0, descr=field_desc) + fail(i2) + """ + expected = """ + [] + fail(1) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), + expected) class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass From antocuni at codespeak.net Thu May 28 00:09:53 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 00:09:53 +0200 (CEST) Subject: [pypy-svn] r65466 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090527220953.9445C169FB1@codespeak.net> Author: antocuni Date: Thu May 28 00:09:53 2009 New Revision: 65466 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py Log: ops, TestOptimize2 was not meant to be checked in. Anyway, some tests pass, skip the other that are failing Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py Thu May 28 00:09:53 2009 @@ -625,3 +625,12 @@ from pypy.jit.metainterp.optimize2 import Optimizer kwds['optimizer'] = Optimizer return LLJitMixin.meta_interp(self, *args, **kwds) + + def skip(self): + py.test.skip('in-progress') + + test_simple_implicit = skip + test_virtual_on_virtualizable = skip + test_no_virtual_on_virtualizable = skip + test_virtualizable_hierarchy = skip + test_non_virtual_on_always_virtual = skip From antocuni at codespeak.net Thu May 28 00:12:07 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 00:12:07 +0200 (CEST) Subject: [pypy-svn] r65467 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090527221207.6E974169E6C@codespeak.net> Author: antocuni Date: Thu May 28 00:12:06 2009 New Revision: 65467 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py Log: test ootype too Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_virtualizable.py Thu May 28 00:12:06 2009 @@ -619,7 +619,7 @@ pass -class TestOptimize2(ImplicitVirtualizableTests, LLJitMixin): +class TestOptimize2LLtype(ImplicitVirtualizableTests, LLJitMixin): def meta_interp(self, *args, **kwds): from pypy.jit.metainterp.optimize2 import Optimizer @@ -634,3 +634,20 @@ test_no_virtual_on_virtualizable = skip test_virtualizable_hierarchy = skip test_non_virtual_on_always_virtual = skip + + +class TestOptimize2OOtype(ImplicitVirtualizableTests, OOJitMixin): + + def meta_interp(self, *args, **kwds): + from pypy.jit.metainterp.optimize2 import Optimizer + kwds['optimizer'] = Optimizer + return OOJitMixin.meta_interp(self, *args, **kwds) + + def skip(self): + py.test.skip('in-progress') + + test_simple_implicit = skip + test_virtual_on_virtualizable = skip + test_no_virtual_on_virtualizable = skip + test_virtualizable_hierarchy = skip + test_non_virtual_on_always_virtual = skip From fijal at codespeak.net Thu May 28 00:20:59 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 28 May 2009 00:20:59 +0200 (CEST) Subject: [pypy-svn] r65468 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090527222059.3927E169FB1@codespeak.net> Author: fijal Date: Thu May 28 00:20:58 2009 New Revision: 65468 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a test and a fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Thu May 28 00:20:58 2009 @@ -238,7 +238,10 @@ @staticmethod def find_nodes_setarrayitem_gc(op, spec): - return False + instnode = spec.getnode(op.args[0]) + if not instnode.virtualized: + return False + return True @staticmethod def find_nodes_guard_nonvirtualized(op, spec): @@ -343,6 +346,7 @@ return True specializer = Specializer([SimpleVirtualizableOpt(), + SimpleVirtualOpt(), ConsecutiveGuardClassRemoval()]) def optimize_loop(options, old_loops, loop, cpu=None, spec=specializer): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Thu May 28 00:20:58 2009 @@ -59,16 +59,19 @@ nodedescr = cpu.fielddescrof(NODE, 'value') TP = lltype.GcArray(lltype.Signed) + NODE_ARRAY = lltype.GcArray(lltype.Ptr(NODE)) XY = lltype.GcStruct('XY', ('parent', OBJECT), ('inst_field', lltype.Signed), ('inst_other_field', lltype.Signed), ('inst_list', lltype.Ptr(TP)), + ('inst_item_list', lltype.Ptr(NODE_ARRAY)), hints= {'virtualizable2': True, - 'virtuals': ('field','list')}) + 'virtuals': ('field','list', 'item_list')}) field_desc = cpu.fielddescrof(XY, 'inst_field') array_descr = cpu.arraydescrof(TP) list_desc = cpu.fielddescrof(XY, 'inst_list') + list_node_desc = cpu.fielddescrof(XY, 'inst_item_list') other_field_desc = cpu.fielddescrof(XY, 'inst_other_field') vdesc = VirtualizableDesc(cpu, XY, XY) xy_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True) @@ -377,8 +380,31 @@ self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), expected) + def test_virtual_with_virtualizable(self): + pre_op = """ + [p0] + p1 = new_with_vtable(13, ConstClass(node_vtable)) + setfield_gc(p1, 1, descr=nodedescr) + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + p2 = getfield_gc(p0, descr=list_node_desc) + setarrayitem_gc(p2, 0, p1) + p3 = getarrayitem_gc(p2, 0) + i3 = getfield_gc(p3, descr=nodedescr) + fail(i3) + """ + expected = """ + [p0] + p2 = getfield_gc(p0, descr=list_node_desc) + fail(1) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt(), + SimpleVirtualOpt()]), + expected) + class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - pass + def test_virtual_with_virtualizable(self): + py.test.skip("XXX") From benjamin at codespeak.net Thu May 28 00:34:14 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 28 May 2009 00:34:14 +0200 (CEST) Subject: [pypy-svn] r65469 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090527223414.83CC5169FB7@codespeak.net> Author: benjamin Date: Thu May 28 00:34:10 2009 New Revision: 65469 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Log: when somebody tries to use this on Windows, they'll thank me Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/oparser.py Thu May 28 00:34:10 2009 @@ -124,7 +124,7 @@ return self.parse_op_no_result(line) def parse(self): - lines = self.descr.split("\n") + lines = self.descr.splitlines() ops = [] newlines = [] for line in lines: From fijal at codespeak.net Thu May 28 00:36:40 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 28 May 2009 00:36:40 +0200 (CEST) Subject: [pypy-svn] r65470 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090527223640.7B64E169FC0@codespeak.net> Author: fijal Date: Thu May 28 00:36:39 2009 New Revision: 65470 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: rebuild ops. Needs more tests Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Thu May 28 00:36:39 2009 @@ -26,6 +26,7 @@ self.vdesc = None self.escaped = escaped self.virtual = False + self.size = 0 def __repr__(self): flags = '' @@ -131,6 +132,16 @@ gop.suboperations = [ResOperation(rop.FAIL, [], None)] return gop + def rebuild_virtual(self, ops, node): + assert node.virtual + ops.append(ResOperation(rop.NEW_WITH_VTABLE, [node.size, node.cls], + node.source)) + for field, valuenode in node.cleanfields.iteritems(): + if valuenode.virtual: + self.rebuild_virtual(ops, valuenode) + ops.append(ResOperation(rop.SETFIELD_GC, + [node.source, valuenode.source], None, field)) + def optimize_guard(self, op): if op.is_foldable_guard(): for arg in op.args: @@ -140,12 +151,19 @@ return None assert len(op.suboperations) == 1 op_fail = op.suboperations[0] + op.suboperations = [] + self.already_build_nodes = {} + for arg in op_fail.args: + node = self.getnode(arg) + if node.virtual: + self.rebuild_virtual(op.suboperations, node) op_fail.args = self.new_arguments(op_fail) # modification in place. Reason for this is explained in mirror # in optimize.py - op.suboperations = [] for node, d in self.additional_stores.iteritems(): for field, fieldnode in d.iteritems(): + if fieldnode.virtual: + self.rebuild_virtual(op.suboperations, fieldnode) gop = self._guard_for_node(node) op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETFIELD_GC, @@ -153,6 +171,8 @@ for node, d in self.additional_setarrayitems.iteritems(): for field, (fieldnode, descr) in d.iteritems(): box = fieldnode.source + if fieldnode.virtual: + self.rebuild_virtual(op.suboperations, fieldnode) gop = self._guard_for_node(node) op.suboperations.append(gop) op.suboperations.append(ResOperation(rop.SETARRAYITEM_GC, @@ -324,6 +344,8 @@ if node.escaped: return False node.virtual = True + node.cls = op.args[1] + node.size = op.args[0] return True @staticmethod Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Thu May 28 00:36:39 2009 @@ -402,6 +402,24 @@ SimpleVirtualOpt()]), expected) + def test_rebuild_ops(self): + pre_op = """ + [i1] + p1 = new_with_vtable(13, ConstClass(node_vtable)) + setfield_gc(p1, 1, descr=field_desc) + guard_true(i1) + fail(p1) + """ + expected = """ + [i1] + guard_true(i1) + p1 = new_with_vtable(13, ConstClass(node_vtable)) + setfield_gc(p1, 1, descr=field_desc) + fail(p1) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), + expected) + class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass From benjamin at codespeak.net Thu May 28 00:50:33 2009 From: benjamin at codespeak.net (benjamin at codespeak.net) Date: Thu, 28 May 2009 00:50:33 +0200 (CEST) Subject: [pypy-svn] r65471 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090527225033.9ED72169F91@codespeak.net> Author: benjamin Date: Thu May 28 00:50:32 2009 New Revision: 65471 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: drill more int operations for constant folding Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Thu May 28 00:50:32 2009 @@ -3,7 +3,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE -from pypy.jit.metainterp.resoperation import rop, ResOperation +from pypy.jit.metainterp.resoperation import rop, ResOperation, opname from pypy.jit.metainterp.history import ConstAddr, BoxPtr, TreeLoop,\ ConstInt, BoxInt, BoxObj, ConstObj from pypy.jit.backend.llgraph import runner @@ -131,13 +131,18 @@ equaloplists(optimized, self.parse(expected).operations) def test_basic_constant_folding(self): - pre_op = """ - [] - i1 = int_add(3, 2) - """ - expected = "[]" - self.assert_equal(self.optimize(pre_op), expected) - + for op in range(rop.INT_ADD, rop._COMPARISON_FIRST): + try: + op = opname[op] + except KeyError: + continue + pre_op = """ + [] + i1 = %s(3, 2) + """ % op.lower() + expected = "[]" + self.assert_equal(self.optimize(pre_op), expected) + def test_remove_guard_class(self): pre_op = """ [p0] From fijal at codespeak.net Thu May 28 00:53:44 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 28 May 2009 00:53:44 +0200 (CEST) Subject: [pypy-svn] r65472 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090527225344.1A3A8169F91@codespeak.net> Author: fijal Date: Thu May 28 00:53:43 2009 New Revision: 65472 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: oops, make this more real world Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Thu May 28 00:53:43 2009 @@ -134,8 +134,8 @@ def rebuild_virtual(self, ops, node): assert node.virtual - ops.append(ResOperation(rop.NEW_WITH_VTABLE, [node.size, node.cls], - node.source)) + ops.append(ResOperation(rop.NEW_WITH_VTABLE, [node.cls], + node.source, node.size)) for field, valuenode in node.cleanfields.iteritems(): if valuenode.virtual: self.rebuild_virtual(ops, valuenode) @@ -344,8 +344,8 @@ if node.escaped: return False node.virtual = True - node.cls = op.args[1] - node.size = op.args[0] + node.cls = op.args[0] + node.size = op.descr return True @staticmethod Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Thu May 28 00:53:43 2009 @@ -57,6 +57,7 @@ node = lltype.malloc(NODE) nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node)) nodedescr = cpu.fielddescrof(NODE, 'value') + nodesize = cpu.sizeof(NODE) TP = lltype.GcArray(lltype.Signed) NODE_ARRAY = lltype.GcArray(lltype.Ptr(NODE)) @@ -93,6 +94,7 @@ node = ootype.new(NODE) nodebox = BoxObj(ootype.cast_to_object(node)) nodedescr = cpu.fielddescrof(NODE, 'value') + nodesize = cpu.sizeof(node) TP = ootype.Array(ootype.Signed) @@ -305,14 +307,14 @@ def test_newly_allocated_virtualizable_is_not_virtualized(self): pre_op = """ [] - p0 = new_with_vtable(13, ConstClass(xy_vtable)) + p0 = new_with_vtable(ConstClass(xy_vtable)) guard_nonvirtualized(p0, vdesc=vdesc) fail() setfield_gc(p0, 3, descr=field_desc) """ expected = """ [] - p0 = new_with_vtable(13, ConstClass(xy_vtable)) + p0 = new_with_vtable(ConstClass(xy_vtable)) setfield_gc(p0, 3, descr=field_desc) """ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]), @@ -373,7 +375,7 @@ def test_simple_virtual(self): pre_op = """ [] - p0 = new_with_vtable(13, ConstClass(node_vtable)) + p0 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p0, 1, descr=field_desc) i2 = getfield_gc(p0, descr=field_desc) fail(i2) @@ -388,7 +390,7 @@ def test_virtual_with_virtualizable(self): pre_op = """ [p0] - p1 = new_with_vtable(13, ConstClass(node_vtable)) + p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p1, 1, descr=nodedescr) guard_nonvirtualized(p0, vdesc=vdesc) fail() @@ -410,7 +412,7 @@ def test_rebuild_ops(self): pre_op = """ [i1] - p1 = new_with_vtable(13, ConstClass(node_vtable)) + p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize) setfield_gc(p1, 1, descr=field_desc) guard_true(i1) fail(p1) @@ -418,7 +420,7 @@ expected = """ [i1] guard_true(i1) - p1 = new_with_vtable(13, ConstClass(node_vtable)) + p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize) setfield_gc(p1, 1, descr=field_desc) fail(p1) """ From fijal at codespeak.net Thu May 28 02:04:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 28 May 2009 02:04:17 +0200 (CEST) Subject: [pypy-svn] r65473 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090528000417.D3325169FC5@codespeak.net> Author: fijal Date: Thu May 28 02:04:15 2009 New Revision: 65473 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a next test to fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Thu May 28 02:04:15 2009 @@ -20,6 +20,7 @@ self.const = const self.cls = None self.cleanfields = {} + self.origfields = {} self.arrayfields = {} self.virtualized = False self.allocated_in_loop = False @@ -253,7 +254,8 @@ field = op.descr if field not in instnode.vdesc.virtuals: return False - spec.getnode(op.result).virtualized = True + node = spec.getnode(op.result) + node.virtualized = True return False @staticmethod @@ -270,7 +272,7 @@ instnode.virtualized = True instnode.vdesc = op.vdesc return False - + @staticmethod def optimize_guard_nonvirtualized(op, spec): return True Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Thu May 28 02:04:15 2009 @@ -427,9 +427,36 @@ self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), expected) + + def test_virtual_with_virtualizable_escapes(self): + py.test.skip("FIXME") + pre_op = """ + [p0] + p1 = new_with_vtable(ConstClass(node_vtable)) + setfield_gc(p1, 1, descr=nodedescr) + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + p2 = getfield_gc(p0, descr=list_node_desc) + setarrayitem_gc(p2, 0, p1) + p3 = getarrayitem_gc(p2, 0) + fail(p3) + """ + expected = """ + [p0] + p1 = new_with_vtable(ConstClass(node_vtable)) + setfield_gc(p1, 1, descr=nodedescr) + p2 = getfield_gc(p0, descr=list_node_desc) + fail(p1) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt(), + SimpleVirtualOpt()]), + expected) + class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): def test_virtual_with_virtualizable(self): py.test.skip("XXX") + + test_virtual_with_virtualizable_escapes = test_virtual_with_virtualizable From antocuni at codespeak.net Thu May 28 11:12:43 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 11:12:43 +0200 (CEST) Subject: [pypy-svn] r65474 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090528091243.10A57169FEA@codespeak.net> Author: antocuni Date: Thu May 28 11:12:43 2009 New Revision: 65474 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py Log: enhance the repr of ootype.Class objects Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/history.py Thu May 28 11:12:43 2009 @@ -46,14 +46,15 @@ def repr_object(box): try: - if box.value.obj._TYPE is ootype.String: + TYPE = box.value.obj._TYPE + if TYPE is ootype.String: return '(%r)' % box.value.obj._str - if isinstance(box.value.obj._TYPE, ootype.StaticMethod): + if TYPE is ootype.Class or isinstance(TYPE, ootype.StaticMethod): return '(%r)' % box.value.obj if isinstance(box.value.obj, ootype._view): return repr(box.value.obj._inst._TYPE) else: - return repr(box.value.obj._TYPE) + return repr(TYPE) except AttributeError: return box.value From antocuni at codespeak.net Thu May 28 11:54:11 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 11:54:11 +0200 (CEST) Subject: [pypy-svn] r65475 - in pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph: . test Message-ID: <20090528095411.68457169FE1@codespeak.net> Author: antocuni Date: Thu May 28 11:54:10 2009 New Revision: 65475 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/test/test_llgraph.py Log: make sure that you return the always same descr for fields defined in the superclasses Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/runner.py Thu May 28 11:54:10 2009 @@ -402,7 +402,9 @@ @staticmethod def fielddescrof(T, fieldname): - return FieldDescr.new(T, fieldname) + # use class where the field is really defined as a key + T1, _ = T._lookup_field(fieldname) + return FieldDescr.new(T1, fieldname) @staticmethod def calldescrof(FUNC, ARGS, RESULT): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llgraph/test/test_llgraph.py Thu May 28 11:54:10 2009 @@ -224,3 +224,13 @@ ## these tests never worked ## class TestOOTypeLLGraph(LLGraphTest): ## from pypy.jit.backend.llgraph.runner import OOtypeCPU as cpu_type + +def test_fielddescr_ootype(): + from pypy.rpython.ootypesystem import ootype + from pypy.jit.backend.llgraph.runner import OOtypeCPU + A = ootype.Instance("A", ootype.ROOT, {"foo": ootype.Signed}) + B = ootype.Instance("B", A) + cpu = OOtypeCPU(None) + descr1 = cpu.fielddescrof(A, "foo") + descr2 = cpu.fielddescrof(B, "foo") + assert descr1 is descr2 From david at codespeak.net Thu May 28 13:41:00 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 28 May 2009 13:41:00 +0200 (CEST) Subject: [pypy-svn] r65476 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090528114100.2C1EF169FE1@codespeak.net> Author: david Date: Thu May 28 13:40:58 2009 New Revision: 65476 Modified: pypy/branch/io-lang/pypy/lang/io/object.py pypy/branch/io-lang/pypy/lang/io/test/test_object.py Log: Added Object substract which returns negative version of a given number Modified: pypy/branch/io-lang/pypy/lang/io/object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/object.py Thu May 28 13:40:58 2009 @@ -1,5 +1,5 @@ from pypy.lang.io.register import register_method -from pypy.lang.io.model import W_ImmutableSequence, W_Block +from pypy.lang.io.model import W_ImmutableSequence, W_Block, W_Number @register_method('Object', 'setSlot', unwrap_spec=[object, str, object]) def w_object_set_slot(space, w_target, name, w_value): @@ -61,4 +61,8 @@ @register_method('Object', 'message') def object_message(space, w_target, w_message, w_context): - return w_message.arguments[0] \ No newline at end of file + return w_message.arguments[0] + + at register_method('Object', '-', unwrap_spec=[object, float]) +def object_minus(space, w_target, argument): + return W_Number(space, -argument) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_object.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_object.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_object.py Thu May 28 13:40:58 2009 @@ -43,4 +43,12 @@ inp = 'message(foo)' res, space = interpret(inp) assert isinstance(res, W_Message) - assert res.name == 'foo' \ No newline at end of file + assert res.name == 'foo' + +def test_object_substract(): + inp = '-1' + res, space = interpret(inp) + assert res.value == -1 + + inp = '-"a"' + py.test.raises(Exception, "interpret(inp)") \ No newline at end of file From david at codespeak.net Thu May 28 13:59:06 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 28 May 2009 13:59:06 +0200 (CEST) Subject: [pypy-svn] r65477 - pypy/branch/io-lang/pypy/lang/io Message-ID: <20090528115906.6B8C1169FE0@codespeak.net> Author: david Date: Thu May 28 13:59:05 2009 New Revision: 65477 Modified: pypy/branch/io-lang/pypy/lang/io/register.py Log: add option to pass a list of aliases for a method name Modified: pypy/branch/io-lang/pypy/lang/io/register.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/register.py (original) +++ pypy/branch/io-lang/pypy/lang/io/register.py Thu May 28 13:59:05 2009 @@ -1,7 +1,13 @@ from pypy.lang.io import model cfunction_definitions = {} -def register_method(type_name, slot_name, unwrap_spec=None): +def register_method(type_name, slot_name, unwrap_spec=None, alias=None): + if alias is None: + alias = [slot_name] + else: + alias.append(slot_name) + def register(function): + if unwrap_spec is None: wrapper = function else: @@ -34,7 +40,10 @@ raise ValueError, 'Unknown unwrap spec' return function(space, *args) subdict = cfunction_definitions.setdefault(type_name, {}) - subdict[slot_name] = wrapper + + + for slotn in alias: + subdict[slotn] = wrapper return function From david at codespeak.net Thu May 28 14:20:39 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 28 May 2009 14:20:39 +0200 (CEST) Subject: [pypy-svn] r65478 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090528122039.928C3169FF9@codespeak.net> Author: david Date: Thu May 28 14:20:38 2009 New Revision: 65478 Modified: pypy/branch/io-lang/pypy/lang/io/number.py pypy/branch/io-lang/pypy/lang/io/test/test_number.py Log: Some Number built-method (mod, ceil, floor, round, pow) Modified: pypy/branch/io-lang/pypy/lang/io/number.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/number.py (original) +++ pypy/branch/io-lang/pypy/lang/io/number.py Thu May 28 14:20:38 2009 @@ -1,3 +1,4 @@ +from math import ceil, floor from pypy.lang.io.register import register_method from pypy.lang.io.model import W_Number @@ -7,4 +8,32 @@ @register_method("Number", '-', unwrap_spec=[float, float]) def w_number_minus(space, target, argument): - return W_Number(space, target - argument) \ No newline at end of file + return W_Number(space, target - argument) + + at register_method('Number', '%', unwrap_spec=[float, float], alias=['mod']) +def w_number_modulo(space, target, argument): + argument = abs(argument) + return W_Number(space, target % argument) + + at register_method('Number', '**', unwrap_spec=[float, float], alias=['pow']) +def w_number_modulo(space, target, argument): + return W_Number(space, target ** argument) + + at register_method('Number', 'ceil', unwrap_spec=[float]) +def w_number_modulo(space, target): + return W_Number(space, ceil(target)) + + at register_method('Number', 'floor', unwrap_spec=[float]) +def w_number_modulo(space, target): + return W_Number(space, floor(target)) + + at register_method('Number', 'round', unwrap_spec=[float]) +def w_number_modulo(space, target): + if target < 0: + n = ceil(target - 0.5) + else: + n = floor(target + 0.5) + + return W_Number(space, n) + + Modified: pypy/branch/io-lang/pypy/lang/io/test/test_number.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_number.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_number.py Thu May 28 14:20:38 2009 @@ -29,3 +29,93 @@ res, space = interpret(inp) assert res.value == 8 +def test_modulo_int_int(): + inp = '5 % 3' + res, space = interpret(inp) + assert res.value == 2 + +def test_modulo_int_float(): + inp = '5 % 3.2' + res, space = interpret(inp) + assert res.value == 1.7999999999999998 + +def test_module_float_float(): + inp = '5.3 % 3.2' + res, space = interpret(inp) + assert res.value == 2.0999999999999996 + +def test_modulo_neg_int_int(): + inp = '-8 % 3' + res, space = interpret(inp) + assert res.value == -2 + +def test_modulo_int_neg_int(): + inp = '8 % -3' + res, space = interpret(inp) + assert res.value == 2 + +def test_modulo_int_neg_int_neg(): + inp = '-8 % -3' + res, space = interpret(inp) + assert res.value == -2 + +def test_modulo_float_float(): + inp = '8.3 % 3.2' + res, space = interpret(inp) + assert res.value == 1.9000000000000004 + +def test_modulo_neg_float_float(): + inp = '-8.3 % 3.2' + res, space = interpret(inp) + assert res.value == -1.9000000000000004 + +def test_modulo_float_neg_float(): + inp = '8.3 % -3.2' + res, space = interpret(inp) + assert res.value == 1.9000000000000004 + +def test_modulo_neg_float_neg_float(): + inp = '-8.3 % -3.2' + res, space = interpret(inp) + assert res.value == -1.9000000000000004 + +def test_alias_modulo(): + inp = '-8.3 mod(-3.2)' + res, space = interpret(inp) + assert res.value == -1.9000000000000004 + +def test_pow(): + inp1 = '5 ** -2.2' + inp2 = '5 pow(-2.2)' + res1, space = interpret(inp1) + res2, space = interpret(inp2) + assert res1.value >= 0.0289911865471078 \ + and res1.value <= 0.0289911865471079 \ + and res2.value == res1.value + +def test_ceil(): + inp = '3.3 ceil' + res, space = interpret(inp) + assert res.value == 4 + +def test_floor(): + inp = '3.9 floor' + res, space = interpret(inp) + assert res.value == 3 + +def test_round(): + inp = '3.3 round' + res, space = interpret(inp) + assert res.value == 3 + + inp = '3.7 round' + res, space = interpret(inp) + assert res.value == 4 + + inp = '3.5 round' + res, space = interpret(inp) + assert res.value == 4 + + inp = '-3.4 round' + res, space = interpret(inp) + assert res.value == -3 \ No newline at end of file From david at codespeak.net Thu May 28 15:00:22 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 28 May 2009 15:00:22 +0200 (CEST) Subject: [pypy-svn] r65479 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090528130022.B7741169F8A@codespeak.net> Author: david Date: Thu May 28 15:00:20 2009 New Revision: 65479 Modified: pypy/branch/io-lang/pypy/lang/io/list.py pypy/branch/io-lang/pypy/lang/io/test/test_list.py Log: Implemented some built-in operations on lists (with, indexOf, contains, size, first) Modified: pypy/branch/io-lang/pypy/lang/io/list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/list.py Thu May 28 15:00:20 2009 @@ -36,4 +36,49 @@ for i in range(len(w_target.items)): t = body.eval(space, w_context, w_context) - return t \ No newline at end of file + return t + + at register_method('List', 'with') +def list_with(space, w_target, w_message, w_context): + new_w_list = w_target.clone() + items_w = [x.eval(space, w_target, w_context) for x in w_message.arguments] + new_w_list.extend(items_w) + return new_w_list + +# TODO: Not sure if this is rpython + at register_method('List', 'indexOf', unwrap_spec=[object, object]) +def list_index_of(space, w_target, item): + try: + return W_Number(space, w_target.items.index(item)) + except ValueError, e: + return space.w_nil + +# TODO: Not sure if this is rpython + at register_method('List', 'contains', unwrap_spec=[object, object]) +def list_contains(space, w_target, item): + if item in w_target.items: + return space.w_true + return space.w_false + + at register_method('List', 'size') +def list_size(space, w_target, w_message, w_context): + return W_Number(space, len(w_target.items)) + + at register_method('List', 'first') +def list_size(space, w_target, w_message, w_context): + if len(w_message.arguments) != 0: + t = w_message.arguments[0].eval(space, w_target, w_context) + assert isinstance(t, W_Number) + nfirst = t.value + else: + nfirst = 1 + + if len(w_target.items) == 0 and nfirst == 1: + return space.w_nil + + flist_w = w_target.clone() + if nfirst < 1: + flist_w.items = [] + else: + flist_w.items = flist_w.items[0:nfirst] + return flist_w \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_list.py Thu May 28 15:00:20 2009 @@ -80,4 +80,63 @@ def test_list_foreach_leaks_variables(): inp = 'b := list(); a := list(99, 34); a foreach(key, value, b append(list(key, value))); key+value' res,space = interpret(inp) - assert res.value == 35 \ No newline at end of file + assert res.value == 35 + +def test_list_with(): + inp = 'a := list(1,2,3); b := a with(99, 34); list(a,b)' + res, space = interpret(inp) + a, b = res.items + # a is proto of b + assert b.protos == [a] + + # b has 1,2,3,99,34 as element + assert [x.value for x in b.items] == [1, 2, 3, 99, 34] + +def test_list_index_of(): + inp = 'list(9,8,7,7) indexOf(7)' + res, _ = interpret(inp) + assert res.value == 2 + + inp = 'list(9,8,7,7) indexOf(42)' + res, space = interpret(inp) + assert res == space.w_nil + +def test_list_contains(): + inp = 'list(9,8,7,7) contains(7)' + res, space = interpret(inp) + assert res == space.w_true + + inp = 'list(9,8,7,7) contains(42)' + res, space = interpret(inp) + assert res == space.w_false + +def test_list_size(): + inp = 'list(9,8,7,7) size' + res, _ = interpret(inp) + assert res.value == 4 + + inp = 'list() size' + res, _ = interpret(inp) + assert res.value == 0 + +def test_list_first_empty(): + inp = 'list() first' + res, space = interpret(inp) + assert res == space.w_nil + + inp = 'list() first(3)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert len(res.items) == 0 + +def test_list_first(): + inp = 'list(9,8,7,6,5,4,3,2,1,1) first' + res, _ = interpret(inp) + assert isinstance(res, W_List) + assert res.items[0].value == 9 + +def test_list_first_n(): + inp = 'list(9,8,7,6,5,4,3,2,1,1) first(3)' + res, _ = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [9,8,7] \ No newline at end of file From david at codespeak.net Thu May 28 15:06:08 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 28 May 2009 15:06:08 +0200 (CEST) Subject: [pypy-svn] r65480 - pypy/branch/io-lang/pypy/lang/io/test Message-ID: <20090528130608.29434169F8A@codespeak.net> Author: david Date: Thu May 28 15:06:07 2009 New Revision: 65480 Modified: pypy/branch/io-lang/pypy/lang/io/test/test_list.py Log: Ensure list receiving the call of "first" is proto of resulting list Modified: pypy/branch/io-lang/pypy/lang/io/test/test_list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_list.py Thu May 28 15:06:07 2009 @@ -124,19 +124,22 @@ res, space = interpret(inp) assert res == space.w_nil - inp = 'list() first(3)' + inp = 'a := list(); a first(3)' res, space = interpret(inp) assert isinstance(res, W_List) assert len(res.items) == 0 + assert res.protos == [space.w_lobby.slots['a']] def test_list_first(): - inp = 'list(9,8,7,6,5,4,3,2,1,1) first' - res, _ = interpret(inp) + inp = 'a := list(9,8,7,6,5,4,3,2,1,1); a first' + res, space = interpret(inp) assert isinstance(res, W_List) assert res.items[0].value == 9 + assert res.protos == [space.w_lobby.slots['a']] def test_list_first_n(): - inp = 'list(9,8,7,6,5,4,3,2,1,1) first(3)' - res, _ = interpret(inp) + inp = 'a := list(9,8,7,6,5,4,3,2,1,1); a first(3)' + res, space = interpret(inp) assert isinstance(res, W_List) - assert [x.value for x in res.items] == [9,8,7] \ No newline at end of file + assert [x.value for x in res.items] == [9,8,7] + assert res.protos == [space.w_lobby.slots['a']] \ No newline at end of file From antocuni at codespeak.net Thu May 28 22:27:27 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 22:27:27 +0200 (CEST) Subject: [pypy-svn] r65481 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli Message-ID: <20090528202727.5126E169F71@codespeak.net> Author: antocuni Date: Thu May 28 22:27:24 2009 New Revision: 65481 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py Log: make sure to return the same FieldDescr for all subclasses Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py Thu May 28 22:27:24 2009 @@ -80,7 +80,8 @@ @cached_method('_fieldcache') def fielddescrof(self, T, fieldname): - return FieldDescr(T, fieldname) + T1, _ = T._lookup_field(fieldname) + return FieldDescr(T1, fieldname) # ---------------------- From antocuni at codespeak.net Thu May 28 22:28:27 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 22:28:27 +0200 (CEST) Subject: [pypy-svn] r65482 - in pypy/branch/pyjitpl5-experiments/pypy/jit/backend: . x86 Message-ID: <20090528202827.9A40C169F78@codespeak.net> Author: antocuni Date: Thu May 28 22:28:22 2009 New Revision: 65482 Added: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/loopparser.py - copied unchanged from r65473, pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/loopparser.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py (contents, props changed) Removed: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/loopparser.py Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py Log: factor the loop logger out of the x86 backend and put it in support.py, so that it can be used by other backends as well Added: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py Thu May 28 22:28:22 2009 @@ -0,0 +1,107 @@ +import os +from pypy.rlib.objectmodel import compute_unique_id +from pypy.jit.metainterp.resoperation import rop +from pypy.jit.metainterp.history import Const, ConstInt, Box, ConstPtr, BoxPtr,\ + BoxInt, ConstAddr + +def repr_of_arg(memo, arg): + try: + mv = memo[arg] + except KeyError: + mv = len(memo) + memo[arg] = mv + if isinstance(arg, ConstInt): + return "ci(%d,%d)" % (mv, arg.value) + elif isinstance(arg, ConstPtr): + return "cp(%d,%d)" % (mv, arg.get_()) + elif isinstance(arg, BoxInt): + return "bi(%d,%d)" % (mv, arg.value) + elif isinstance(arg, BoxPtr): + return "bp(%d,%d)" % (mv, arg.get_()) + elif isinstance(arg, ConstAddr): + return "ca(%d,%d)" % (mv, arg.get_()) + else: + #raise NotImplementedError + return "?%r" % (arg,) + +class Logger(object): + + def __init__(self): + self._log_fd = -1 + + def create_log(self): + s = os.environ.get('PYPYJITLOG') + if not s: + return -1 + s += '.ops' + 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") + return -1 + return self._log_fd + + def repr_for_descr(self, descr): + return '' + + def eventually_log_operations(self, inputargs, operations, memo=None, + myid=0): + if self._log_fd == -1: + return + if memo is None: + memo = {} + if inputargs is None: + os.write(self._log_fd, "BEGIN(%s)\n" % myid) + else: + args = ",".join([repr_of_arg(memo, arg) for arg in inputargs]) + os.write(self._log_fd, "LOOP %s\n" % args) + for i in range(len(operations)): + op = operations[i] + args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) + if op.descr is not None: + descr = self.repr_for_descr(op.descr) + os.write(self._log_fd, "%d:%s %s[%s]\n" % (i, op.getopname(), + args, descr)) + else: + os.write(self._log_fd, "%d:%s %s\n" % (i, op.getopname(), args)) + if op.result is not None: + os.write(self._log_fd, " => %s\n" % repr_of_arg(memo, + op.result)) + if op.is_guard(): + self.eventually_log_operations(None, op.suboperations, memo) + if operations[-1].opnum == rop.JUMP: + if operations[-1].jump_target is not None: + jump_target = compute_unique_id(operations[-1].jump_target) + else: + # XXX hack for the annotator + jump_target = 13 + os.write(self._log_fd, 'JUMPTO:%s\n' % jump_target) + if inputargs is None: + os.write(self._log_fd, "END\n") + else: + os.write(self._log_fd, "LOOP END\n") + + def log_failure_recovery(self, gf, guard_index): + if self._log_fd == -1: + return + return # XXX + os.write(self._log_fd, 'xxxxxxxxxx\n') + memo = {} + reprs = [] + for j in range(len(gf.guard_op.liveboxes)): + valuebox = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j) + reprs.append(repr_of_arg(memo, valuebox)) + jmp = gf.guard_op._jmp_from + os.write(self._log_fd, "%d %d %s\n" % (guard_index, jmp, + ",".join(reprs))) + os.write(self._log_fd, 'xxxxxxxxxx\n') + + def log_call(self, valueboxes): + if self._log_fd == -1: + return + return # XXX + memo = {} + args_s = ','.join([repr_of_arg(memo, box) for box in valueboxes]) + os.write(self._log_fd, "CALL\n") + os.write(self._log_fd, "%s %s\n" % (name, args_s)) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py Thu May 28 22:28:22 2009 @@ -1,8 +1,7 @@ import sys, os import ctypes from pypy.jit.backend.x86 import symbolic -from pypy.jit.metainterp.history import Const, ConstInt, Box, ConstPtr, BoxPtr,\ - BoxInt, ConstAddr +from pypy.jit.metainterp.history import Const, Box, BoxPtr from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory from pypy.rpython.lltypesystem.rclass import OBJECT from pypy.rpython.lltypesystem.lloperation import llop @@ -14,31 +13,22 @@ from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.ri386 import * from pypy.jit.metainterp.resoperation import rop +from pypy.jit.backend.support import Logger # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on the stack MAX_FAIL_BOXES = 1000 -def repr_of_arg(memo, arg): - try: - mv = memo[arg] - except KeyError: - mv = len(memo) - memo[arg] = mv - if isinstance(arg, ConstInt): - return "ci(%d,%d)" % (mv, arg.value) - elif isinstance(arg, ConstPtr): - return "cp(%d,%d)" % (mv, arg.get_()) - elif isinstance(arg, BoxInt): - return "bi(%d,%d)" % (mv, arg.value) - elif isinstance(arg, BoxPtr): - return "bp(%d,%d)" % (mv, arg.get_()) - elif isinstance(arg, ConstAddr): - return "ca(%d,%d)" % (mv, arg.get_()) - else: - #raise NotImplementedError - return "?%r" % (arg,) +class x86Logger(Logger): + + def repr_for_descr(self, descr): + from pypy.jit.backend.x86.runner import ConstDescr3 + if isinstance(descr, ConstDescr3): + return (str(op.descr.v0) + "," + str(op.descr.v1) + + "," + str(op.descr.flag2)) + return Logger.repr_for_descr(descr) + class MachineCodeBlockWrapper(object): MC_SIZE = 1024*1024 @@ -91,7 +81,6 @@ self.counter -= 1 class Assembler386(object): - log_fd = -1 mc = None mc2 = None debug_markers = True @@ -104,19 +93,7 @@ self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) self._exception_addr = 0 self.mcstack = MachineCodeStack() - - def _get_log(self): - s = os.environ.get('PYPYJITLOG') - if not s: - return -1 - s += '.ops' - try: - flags = os.O_WRONLY|os.O_CREAT|os.O_TRUNC - log_fd = os.open(s, flags, 0666) - except OSError: - os.write(2, "could not create log file\n") - return -1 - return log_fd + self.logger = Logger() def make_sure_mc_exists(self): if self.mc is None: @@ -126,7 +103,7 @@ MAX_FAIL_BOXES, flavor='raw') self.fail_box_addr = self.cpu.cast_ptr_to_int(self.fail_boxes) - self._log_fd = self._get_log() + self.logger.create_log() # we generate the loop body in 'mc' # 'mc2' is for guard recovery code if we_are_translated(): @@ -159,69 +136,6 @@ if self.gcrootmap: self.gcrootmap.initialize() - def eventually_log_operations(self, inputargs, operations, memo=None, - myid=0): - from pypy.jit.backend.x86.runner import ConstDescr3 - - if self._log_fd == -1: - return - if memo is None: - memo = {} - if inputargs is None: - os.write(self._log_fd, "BEGIN(%s)\n" % myid) - else: - args = ",".join([repr_of_arg(memo, arg) for arg in inputargs]) - os.write(self._log_fd, "LOOP %s\n" % args) - for i in range(len(operations)): - op = operations[i] - args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) - if op.descr is not None and isinstance(op.descr, ConstDescr3): - descr = (str(op.descr.v0) + "," + str(op.descr.v1) + - "," + str(op.descr.flag2)) - os.write(self._log_fd, "%d:%s %s[%s]\n" % (i, op.getopname(), - args, descr)) - else: - os.write(self._log_fd, "%d:%s %s\n" % (i, op.getopname(), args)) - if op.result is not None: - os.write(self._log_fd, " => %s\n" % repr_of_arg(memo, - op.result)) - if op.is_guard(): - self.eventually_log_operations(None, op.suboperations, memo) - if operations[-1].opnum == rop.JUMP: - if operations[-1].jump_target is not None: - jump_target = compute_unique_id(operations[-1].jump_target) - else: - # XXX hack for the annotator - jump_target = 13 - os.write(self._log_fd, 'JUMPTO:%s\n' % jump_target) - if inputargs is None: - os.write(self._log_fd, "END\n") - else: - os.write(self._log_fd, "LOOP END\n") - - def log_failure_recovery(self, gf, guard_index): - if self._log_fd == -1: - return - return # XXX - os.write(self._log_fd, 'xxxxxxxxxx\n') - memo = {} - reprs = [] - for j in range(len(gf.guard_op.liveboxes)): - valuebox = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j) - reprs.append(repr_of_arg(memo, valuebox)) - jmp = gf.guard_op._jmp_from - os.write(self._log_fd, "%d %d %s\n" % (guard_index, jmp, - ",".join(reprs))) - os.write(self._log_fd, 'xxxxxxxxxx\n') - - def log_call(self, valueboxes): - if self._log_fd == -1: - return - return # XXX - memo = {} - args_s = ','.join([repr_of_arg(memo, box) for box in valueboxes]) - os.write(self._log_fd, "CALL\n") - os.write(self._log_fd, "%s %s\n" % (name, args_s)) def _compute_longest_fail_op(self, ops): max_so_far = 0 @@ -244,8 +158,8 @@ self.tree = tree self.make_sure_mc_exists() inputargs = tree.inputargs - self.eventually_log_operations(tree.inputargs, tree.operations, None, - compute_unique_id(tree)) + self.logger.eventually_log_operations(tree.inputargs, tree.operations, None, + compute_unique_id(tree)) regalloc = RegAlloc(self, tree, self.cpu.translate_support_code) self._regalloc = regalloc regalloc.walk_operations(tree) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py Thu May 28 22:28:22 2009 @@ -168,7 +168,7 @@ # # llop.debug_print(lltype.Void, '.. calling back from', # # guard_op, 'to the jit') # gf = GuardFailed(self, frame_addr, guard_op) -# self.assembler.log_failure_recovery(gf, guard_index) +# self.assembler.logger.log_failure_recovery(gf, guard_index) # self.metainterp.handle_guard_failure(gf) # self.return_value_type = gf.return_value_type # #if self.debug: @@ -279,7 +279,7 @@ # values_repr = ", ".join([str(values_as_int[i]) for i in # range(len(valueboxes))]) # llop.debug_print(lltype.Void, 'exec:', name, values_repr) - #self.assembler.log_call(valueboxes) --- XXX + #self.assembler.logger.log_call(valueboxes) --- XXX guard_index = self.execute_call(loop, func, verbose) self._guard_index = guard_index # for tests op = self._guard_list[guard_index] From antocuni at codespeak.net Thu May 28 22:31:15 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 22:31:15 +0200 (CEST) Subject: [pypy-svn] r65483 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86 Message-ID: <20090528203115.37149169F72@codespeak.net> Author: antocuni Date: Thu May 28 22:31:14 2009 New Revision: 65483 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py Log: typo Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py Thu May 28 22:31:14 2009 @@ -93,7 +93,7 @@ self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed)) self._exception_addr = 0 self.mcstack = MachineCodeStack() - self.logger = Logger() + self.logger = x86Logger() def make_sure_mc_exists(self): if self.mc is None: From antocuni at codespeak.net Thu May 28 23:15:13 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 May 2009 23:15:13 +0200 (CEST) Subject: [pypy-svn] r65484 - in pypy/branch/pyjitpl5-experiments/pypy/jit: backend backend/cli backend/x86 metainterp Message-ID: <20090528211513.9BFB9169F8A@codespeak.net> Author: antocuni Date: Thu May 28 23:15:13 2009 New Revision: 65484 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py Log: add support for loop logging to the cli backend Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/method.py Thu May 28 23:15:13 2009 @@ -1,5 +1,6 @@ import py from pypy.tool.pairtype import extendabletype +from pypy.rlib.objectmodel import compute_unique_id from pypy.rpython.ootypesystem import ootype from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -8,6 +9,7 @@ from pypy.jit.metainterp.history import (AbstractValue, Const, ConstInt, ConstObj) from pypy.jit.metainterp.resoperation import rop, opname +from pypy.jit.backend.support import AbstractLogger from pypy.jit.backend.cli import runner from pypy.jit.backend.cli.methodfactory import get_method_wrapper @@ -19,6 +21,16 @@ cVoid = ootype.nullruntimeclass +class CliLogger(AbstractLogger): + is_oo = True + + def repr_of_descr(self, descr): + from pypy.jit.backend.cli.runner import DescrWithKey + if isinstance(descr, DescrWithKey): + return descr.short_repr() + return AbstractLogger.repr_of_descr(self, descr) + +logger = CliLogger() class __extend__(AbstractValue): __metaclass__ = extendabletype @@ -139,6 +151,11 @@ else: self.av_OverflowError = None self.av_ZeroDivisionError = None + + # ---- + logger.create_log() + logger.eventually_log_operations(loop.inputargs, loop.operations, None, + compute_unique_id(loop)) # ---- self.emit_load_inputargs() self.emit_preamble() Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py Thu May 28 23:15:13 2009 @@ -230,6 +230,9 @@ def sort_key(self): return self.key + def short_repr(self): + return '' + def get_class_for_type(T): if T is ootype.Void: @@ -288,6 +291,7 @@ self.getarraylength = getarraylength self.instanceof = instanceof self.ooclass = get_class_for_type(TYPE) + self.typename = TYPE._short_name() def get_clitype(self): return dotnet.class2type(self.ooclass) @@ -299,6 +303,9 @@ clitype = self.get_clitype() return clitype.GetConstructor(dotnet.new_array(System.Type, 0)) + def short_repr(self): + return self.typename + class StaticMethDescr(DescrWithKey): callfunc = None @@ -425,6 +432,8 @@ clitype = self.get_self_clitype() return clitype.GetField(self.fieldname+'') + def short_repr(self): + return "'%s'" % self.fieldname CPU = CliCPU Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/support.py Thu May 28 23:15:13 2009 @@ -2,34 +2,18 @@ from pypy.rlib.objectmodel import compute_unique_id from pypy.jit.metainterp.resoperation import rop from pypy.jit.metainterp.history import Const, ConstInt, Box, ConstPtr, BoxPtr,\ - BoxInt, ConstAddr + BoxInt, ConstAddr, BoxObj, ConstObj -def repr_of_arg(memo, arg): - try: - mv = memo[arg] - except KeyError: - mv = len(memo) - memo[arg] = mv - if isinstance(arg, ConstInt): - return "ci(%d,%d)" % (mv, arg.value) - elif isinstance(arg, ConstPtr): - return "cp(%d,%d)" % (mv, arg.get_()) - elif isinstance(arg, BoxInt): - return "bi(%d,%d)" % (mv, arg.value) - elif isinstance(arg, BoxPtr): - return "bp(%d,%d)" % (mv, arg.get_()) - elif isinstance(arg, ConstAddr): - return "ca(%d,%d)" % (mv, arg.get_()) - else: - #raise NotImplementedError - return "?%r" % (arg,) - -class Logger(object): +class AbstractLogger(object): + # is_oo = ... ## need to be set by concrete classes + def __init__(self): self._log_fd = -1 def create_log(self): + if self._log_fd != -1: + return self._log_fd s = os.environ.get('PYPYJITLOG') if not s: return -1 @@ -42,9 +26,33 @@ return -1 return self._log_fd - def repr_for_descr(self, descr): + def repr_of_descr(self, descr): return '' + def repr_of_arg(self, memo, arg): + try: + mv = memo[arg] + except KeyError: + mv = len(memo) + memo[arg] = mv + if isinstance(arg, ConstInt): + return "ci(%d,%d)" % (mv, arg.value) + elif isinstance(arg, BoxInt): + return "bi(%d,%d)" % (mv, arg.value) + elif not self.is_oo and isinstance(arg, ConstPtr): + return "cp(%d,%d)" % (mv, arg.get_()) + elif not self.is_oo and isinstance(arg, BoxPtr): + return "bp(%d,%d)" % (mv, arg.get_()) + elif not self.is_oo and isinstance(arg, ConstAddr): + return "ca(%d,%d)" % (mv, arg.get_()) + elif self.is_oo and isinstance(arg, ConstObj): + return "co(%d,%d)" % (mv, arg.get_()) + elif self.is_oo and isinstance(arg, BoxObj): + return "bo(%d,%d)" % (mv, arg.get_()) + else: + #raise NotImplementedError + return "?%r" % (arg,) + def eventually_log_operations(self, inputargs, operations, memo=None, myid=0): if self._log_fd == -1: @@ -54,20 +62,20 @@ if inputargs is None: os.write(self._log_fd, "BEGIN(%s)\n" % myid) else: - args = ",".join([repr_of_arg(memo, arg) for arg in inputargs]) + args = ",".join([self.repr_of_arg(memo, arg) for arg in inputargs]) os.write(self._log_fd, "LOOP %s\n" % args) for i in range(len(operations)): op = operations[i] - args = ",".join([repr_of_arg(memo, arg) for arg in op.args]) + args = ",".join([self.repr_of_arg(memo, arg) for arg in op.args]) if op.descr is not None: - descr = self.repr_for_descr(op.descr) + descr = self.repr_of_descr(op.descr) os.write(self._log_fd, "%d:%s %s[%s]\n" % (i, op.getopname(), args, descr)) else: os.write(self._log_fd, "%d:%s %s\n" % (i, op.getopname(), args)) if op.result is not None: - os.write(self._log_fd, " => %s\n" % repr_of_arg(memo, - op.result)) + os.write(self._log_fd, " => %s\n" % self.repr_of_arg(memo, + op.result)) if op.is_guard(): self.eventually_log_operations(None, op.suboperations, memo) if operations[-1].opnum == rop.JUMP: @@ -91,7 +99,7 @@ reprs = [] for j in range(len(gf.guard_op.liveboxes)): valuebox = gf.cpu.getvaluebox(gf.frame, gf.guard_op, j) - reprs.append(repr_of_arg(memo, valuebox)) + reprs.append(self.repr_of_arg(memo, valuebox)) jmp = gf.guard_op._jmp_from os.write(self._log_fd, "%d %d %s\n" % (guard_index, jmp, ",".join(reprs))) @@ -102,6 +110,6 @@ return return # XXX memo = {} - args_s = ','.join([repr_of_arg(memo, box) for box in valueboxes]) + args_s = ','.join([self.repr_of_arg(memo, box) for box in valueboxes]) os.write(self._log_fd, "CALL\n") os.write(self._log_fd, "%s %s\n" % (name, args_s)) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py Thu May 28 23:15:13 2009 @@ -13,21 +13,23 @@ from pypy.jit.backend.x86 import codebuf from pypy.jit.backend.x86.ri386 import * from pypy.jit.metainterp.resoperation import rop -from pypy.jit.backend.support import Logger +from pypy.jit.backend.support import AbstractLogger # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on the stack MAX_FAIL_BOXES = 1000 -class x86Logger(Logger): +class x86Logger(AbstractLogger): - def repr_for_descr(self, descr): + is_oo = False + + def repr_of_descr(self, descr): from pypy.jit.backend.x86.runner import ConstDescr3 if isinstance(descr, ConstDescr3): - return (str(op.descr.v0) + "," + str(op.descr.v1) + - "," + str(op.descr.flag2)) - return Logger.repr_for_descr(descr) + return (str(descr.v0) + "," + str(descr.v1) + + "," + str(descr.flag2)) + return AbstractLogger.repr_of_descr(self, descr) class MachineCodeBlockWrapper(object): Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/compile.py Thu May 28 23:15:13 2009 @@ -272,7 +272,7 @@ if isinstance(box, BoxInt): srcvalue = cpu.get_latest_value_int(i) box.changevalue_int(srcvalue) - elif isinstance(box, BoxPtr): + elif not cpu.is_oo and isinstance(box, BoxPtr): srcvalue = cpu.get_latest_value_ptr(i) box.changevalue_ptr(srcvalue) elif cpu.is_oo and isinstance(box, BoxObj): @@ -290,7 +290,7 @@ dstbox = fail_op.args[i] if isinstance(dstbox, BoxInt): dstbox.changevalue_int(srcbox.getint()) - elif isinstance(dstbox, BoxPtr): + elif not metainterp_sd.cpu.is_oo and isinstance(dstbox, BoxPtr): dstbox.changevalue_ptr(srcbox.getptr_base()) elif isinstance(dstbox, Const): pass From antocuni at codespeak.net Fri May 29 00:12:36 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 May 2009 00:12:36 +0200 (CEST) Subject: [pypy-svn] r65485 - in pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli: . test Message-ID: <20090528221236.CB154169FF5@codespeak.net> Author: antocuni Date: Fri May 29 00:12:35 2009 New Revision: 65485 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py Log: we cannot use cached_method to cache FieldDescr, because we want to use the class where the field is really defined as a key, while cached_method blindly use the actual arguments. Instead, use the same approach as the llgraph backend. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/runner.py Fri May 29 00:12:35 2009 @@ -7,7 +7,6 @@ from pypy.jit.metainterp import executor from pypy.jit.metainterp.resoperation import rop, opname from pypy.jit.backend import model -from pypy.jit.backend.minimal.runner import cached_method from pypy.jit.backend.llgraph.runner import KeyManager from pypy.translator.cli import dotnet from pypy.translator.cli.dotnet import CLR @@ -58,30 +57,30 @@ self.inputargs = InputArgs() return self.inputargs - @cached_method('_callcache') - def calldescrof(self, FUNC, ARGS, RESULT): - return StaticMethDescr(FUNC, ARGS, RESULT) + @staticmethod + def calldescrof(FUNC, ARGS, RESULT): + return StaticMethDescr.new(FUNC, ARGS, RESULT) - @cached_method('_methcache') - def methdescrof(self, SELFTYPE, methname): + @staticmethod + def methdescrof(SELFTYPE, methname): if SELFTYPE in (ootype.String, ootype.Unicode): - return StringMethDescr(SELFTYPE, methname) - return MethDescr(SELFTYPE, methname) + return StringMethDescr.new(SELFTYPE, methname) + return MethDescr.new(SELFTYPE, methname) - @cached_method('_typecache') - def typedescrof(self, TYPE): - return TypeDescr(TYPE) + @staticmethod + def typedescrof(TYPE): + return TypeDescr.new(TYPE) - @cached_method('_arraycache') - def arraydescrof(self, A): + @staticmethod + def arraydescrof(A): assert isinstance(A, ootype.Array) TYPE = A.ITEM - return TypeDescr(TYPE) + return TypeDescr.new(TYPE) - @cached_method('_fieldcache') - def fielddescrof(self, T, fieldname): + @staticmethod + def fielddescrof(T, fieldname): T1, _ = T._lookup_field(fieldname) - return FieldDescr(T1, fieldname) + return FieldDescr.new(T1, fieldname) # ---------------------- @@ -221,9 +220,22 @@ # ---------------------------------------------------------------------- key_manager = KeyManager() +descr_cache = {} class DescrWithKey(AbstractDescr): key = -1 + @classmethod + def new(cls, *args): + 'NOT_RPYTHON' + key = (cls, args) + try: + return descr_cache[key] + except KeyError: + res = cls(*args) + descr_cache[key] = res + return res + + def __init__(self, key): self.key = key_manager.getkey(key) @@ -351,7 +363,9 @@ methname = '' has_result = False key = -1 - + + new = classmethod(DescrWithKey.new.im_func) + def __init__(self, SELFTYPE, methname): from pypy.jit.backend.llgraph.runner import boxresult, make_getargs _, meth = SELFTYPE._lookup(methname) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/cli/test/test_basic.py Fri May 29 00:12:35 2009 @@ -38,3 +38,13 @@ test_long_long = skip test_free_object = skip test_stopatxpolicy = skip + + +def test_fielddescr_ootype(): + from pypy.rpython.ootypesystem import ootype + from pypy.jit.backend.cli.runner import CliCPU + A = ootype.Instance("A", ootype.ROOT, {"foo": ootype.Signed}) + B = ootype.Instance("B", A) + descr1 = CliCPU.fielddescrof(A, "foo") + descr2 = CliCPU.fielddescrof(B, "foo") + assert descr1 is descr2 From fijal at codespeak.net Fri May 29 03:08:07 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 03:08:07 +0200 (CEST) Subject: [pypy-svn] r65486 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090529010807.65E7C169E04@codespeak.net> Author: fijal Date: Fri May 29 03:08:04 2009 New Revision: 65486 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: Fix the issue, unskip the test. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Fri May 29 03:08:04 2009 @@ -218,12 +218,18 @@ newoperations.append(op) print "Length of the loop:", len(newoperations) self.loop.operations = newoperations + + def cleanup_nodes(self): + for node in self.nodes.values(): + node.arrayfields.clear() + node.cleanfields.clear() def optimize_loop(self, loop): self.nodes = {} self.field_caches = {} self.loop = loop self.find_nodes() + self.cleanup_nodes() self.optimize_operations() class ConsecutiveGuardClassRemoval(object): @@ -244,6 +250,8 @@ field = op.descr if field not in instnode.vdesc.virtuals: return False + node = spec.getnode(op.args[1]) + instnode.cleanfields[field] = node return True @staticmethod @@ -254,6 +262,11 @@ field = op.descr if field not in instnode.vdesc.virtuals: return False + node = instnode.cleanfields.get(field, None) + if node: + spec.nodes[op.result] = node + node.virtualized = True + return True node = spec.getnode(op.result) node.virtualized = True return False @@ -263,9 +276,24 @@ instnode = spec.getnode(op.args[0]) if not instnode.virtualized: return False + field = op.args[1].getint() + node = spec.getnode(op.args[2]) + instnode.arrayfields[field] = node return True @staticmethod + def find_nodes_getarrayitem_gc(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtualized: + return False + field = op.args[1].getint() + node = instnode.arrayfields.get(field, None) + if node is not None: + spec.nodes[op.result] = node + return True + return False + + @staticmethod def find_nodes_guard_nonvirtualized(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.allocated_in_loop: Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Fri May 29 03:08:04 2009 @@ -429,7 +429,6 @@ def test_virtual_with_virtualizable_escapes(self): - py.test.skip("FIXME") pre_op = """ [p0] p1 = new_with_vtable(ConstClass(node_vtable)) From fijal at codespeak.net Fri May 29 03:22:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 03:22:04 +0200 (CEST) Subject: [pypy-svn] r65487 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090529012204.29F0C169FDB@codespeak.net> Author: fijal Date: Fri May 29 03:22:03 2009 New Revision: 65487 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: a test and a fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Fri May 29 03:22:03 2009 @@ -268,6 +268,7 @@ node.virtualized = True return True node = spec.getnode(op.result) + instnode.cleanfields[field] = node node.virtualized = True return False @@ -291,6 +292,7 @@ if node is not None: spec.nodes[op.result] = node return True + instnode.arrayfields[field] = node return False @staticmethod Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Fri May 29 03:22:03 2009 @@ -451,6 +451,29 @@ SimpleVirtualOpt()]), expected) + def test_virtualizable_double_read(self): + pre_op = """ + [p0] + p3 = new_with_vtable(ConstClass(node_vtable)) + guard_nonvirtualized(p0, vdesc=vdesc) + fail() + p1 = getfield_gc(p0, descr=list_node_desc) + setarrayitem_gc(p1, 0, p3) + p2 = getfield_gc(p0, descr=list_node_desc) + p4 = getarrayitem_gc(p2, 0) + fail(p4) + """ + expected = """ + [p0] + p3 = new_with_vtable(ConstClass(node_vtable)) + p1 = getfield_gc(p0, descr=list_node_desc) + fail(p3) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt(), + SimpleVirtualOpt()]), + expected) + + class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass @@ -459,3 +482,4 @@ py.test.skip("XXX") test_virtual_with_virtualizable_escapes = test_virtual_with_virtualizable + test_virtualizable_double_read = test_virtual_with_virtualizable From fijal at codespeak.net Fri May 29 03:31:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 03:31:15 +0200 (CEST) Subject: [pypy-svn] r65488 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090529013115.2CD93169FE7@codespeak.net> Author: fijal Date: Fri May 29 03:31:12 2009 New Revision: 65488 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: A trivial test and a fix for node without vtable Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Fri May 29 03:31:12 2009 @@ -135,8 +135,11 @@ def rebuild_virtual(self, ops, node): assert node.virtual - ops.append(ResOperation(rop.NEW_WITH_VTABLE, [node.cls], - node.source, node.size)) + if node.cls is not None: + ops.append(ResOperation(rop.NEW_WITH_VTABLE, [node.cls], + node.source, node.size)) + else: + ops.append(ResOperation(rop.NEW, [], node.source, node.size)) for field, valuenode in node.cleanfields.iteritems(): if valuenode.virtual: self.rebuild_virtual(ops, valuenode) @@ -381,6 +384,15 @@ return True @staticmethod + def optimize_new(op, spec): + node = spec.getnode(op.result) + if node.escaped: + return False + node.virtual = True + node.size = op.descr + return True + + @staticmethod def optimize_setfield_gc(op, spec): instnode = spec.getnode(op.args[0]) if not instnode.virtual: Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Fri May 29 03:31:12 2009 @@ -472,6 +472,22 @@ self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt(), SimpleVirtualOpt()]), expected) + + def test_virtual_without_vtable(self): + pre_op = """ + [i1] + p0 = new() + guard_true(i1) + fail(p0) + """ + expected = """ + [i1] + guard_true(i1) + p0 = new() + fail(p0) + """ + self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), + expected) class TestLLtype(LLtypeMixin, BaseTestOptimize2): From fijal at codespeak.net Fri May 29 04:04:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 04:04:21 +0200 (CEST) Subject: [pypy-svn] r65489 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090529020421.441CE169F4A@codespeak.net> Author: fijal Date: Fri May 29 04:04:20 2009 New Revision: 65489 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: more simple stuff. oononnull/ooisnull on virtuals Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Fri May 29 04:04:20 2009 @@ -411,6 +411,23 @@ spec.nodes[op.result] = instnode.cleanfields[field] return True + @staticmethod + def optimize_oononnull(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtual: + return False + spec.nodes[op.result] = InstanceNode(ConstInt(1), const=True) + return True + + @staticmethod + def optimize_ooisnull(op, spec): + instnode = spec.getnode(op.args[0]) + if not instnode.virtual: + return False + spec.nodes[op.result] = InstanceNode(ConstInt(0), const=True) + return True + + specializer = Specializer([SimpleVirtualizableOpt(), SimpleVirtualOpt(), ConsecutiveGuardClassRemoval()]) Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Fri May 29 04:04:20 2009 @@ -488,7 +488,21 @@ """ self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), expected) - + + def test_oononnull_on_virtual(self): + pre_op = """ + [] + p0 = new() + i1 = oononnull(p0) + guard_true(i1) + fail() + i2 = ooisnull(p0) + guard_false(i2) + fail() + """ + expected = "[]" + self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]), + expected) class TestLLtype(LLtypeMixin, BaseTestOptimize2): pass From fijal at codespeak.net Fri May 29 04:04:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 04:04:56 +0200 (CEST) Subject: [pypy-svn] r65490 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090529020456.49DC1169F4A@codespeak.net> Author: fijal Date: Fri May 29 04:04:55 2009 New Revision: 65490 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: getfield_gc_pure and getfield_gc are the same when it comes to virtuals Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Fri May 29 04:04:55 2009 @@ -411,6 +411,8 @@ spec.nodes[op.result] = instnode.cleanfields[field] return True + optimize_getfield_gc_pure = optimize_getfield_gc + @staticmethod def optimize_oononnull(op, spec): instnode = spec.getnode(op.args[0]) From fijal at codespeak.net Fri May 29 04:14:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 04:14:54 +0200 (CEST) Subject: [pypy-svn] r65491 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090529021454.0DA81169E7D@codespeak.net> Author: fijal Date: Fri May 29 04:14:53 2009 New Revision: 65491 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Log: translation fix Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Fri May 29 04:14:53 2009 @@ -27,7 +27,7 @@ self.vdesc = None self.escaped = escaped self.virtual = False - self.size = 0 + self.size = None def __repr__(self): flags = '' From fijal at codespeak.net Fri May 29 06:04:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 06:04:22 +0200 (CEST) Subject: [pypy-svn] r65492 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090529040422.C2BF4169F4A@codespeak.net> Author: fijal Date: Fri May 29 06:04:20 2009 New Revision: 65492 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/jitprof.py Log: Swallow broken data. Profiler seems to work, but _end is called when handling exception, which means that other exception is not displayed. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/jitprof.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/jitprof.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/jitprof.py Fri May 29 06:04:20 2009 @@ -69,10 +69,12 @@ t0 = self.t1 self.t1 = self.timer() if not self.current: - raise BrokenProfilerData + print "BROKEN PROFILER DATA!" + return ev1 = self.current.pop() if ev1 != event: - raise BrokenProfilerData + print "BROKEN PROFILER DATA!" + return self.times[ev1] += self.t1 - t0 def start_tracing(self): self._start(TRACING) From david at codespeak.net Fri May 29 12:26:19 2009 From: david at codespeak.net (david at codespeak.net) Date: Fri, 29 May 2009 12:26:19 +0200 (CEST) Subject: [pypy-svn] r65493 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090529102619.AD355169FD2@codespeak.net> Author: david Date: Fri May 29 12:26:17 2009 New Revision: 65493 Added: pypy/branch/io-lang/pypy/lang/io/map.py pypy/branch/io-lang/pypy/lang/io/test/test_map.py Modified: pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/objspace.py Log: Added map type for key value collections and two methods (clone, atPut) Added: pypy/branch/io-lang/pypy/lang/io/map.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/map.py Fri May 29 12:26:17 2009 @@ -0,0 +1,6 @@ +from pypy.lang.io.register import register_method + + at register_method('Map', 'atPut', unwrap_spec=[object, object, object]) +def map_at_put(space, target, key, value): + target.items[key] = value + return target \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Fri May 29 12:26:17 2009 @@ -73,6 +73,15 @@ l.items += items return l +class W_Map(W_Object): + """A key/value dictionary appropriate for holding large key/value collections.""" + def __init__(self, space, protos = [], items = {}): + W_Object.__init__(self, space, protos) + self.items = items + + def clone(self): + return W_Map(self.space, [self], dict(self.items)) + class W_ImmutableSequence(W_Object): def __init__(self, space, string): self.value = string Modified: pypy/branch/io-lang/pypy/lang/io/objspace.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/objspace.py (original) +++ pypy/branch/io-lang/pypy/lang/io/objspace.py Fri May 29 12:26:17 2009 @@ -1,5 +1,5 @@ from pypy.rlib.objectmodel import instantiate -from pypy.lang.io.model import W_Number, W_Object, W_CFunction, W_Block, W_Message, W_List +from pypy.lang.io.model import W_Number, W_Object, W_CFunction, W_Block, W_Message, W_List, W_Map from pypy.lang.io.register import cfunction_definitions import pypy.lang.io.number @@ -8,6 +8,8 @@ import pypy.lang.io.list import pypy.lang.io.call import pypy.lang.io.message +import pypy.lang.io.map + class ObjSpace(object): """docstring for ObjSpace""" def __init__(self): @@ -22,7 +24,7 @@ self.w_nil = W_Object(self, [self.w_object]) self.w_list = W_List(self, [self.w_object]) self.w_call = W_Object(self) - + self.w_map = W_Map(self, [self.w_object]) self.init_w_object() @@ -44,6 +46,12 @@ self.init_w_call() + self.init_w_map() + + def init_w_map(self): + for key, function in cfunction_definitions['Map'].items(): + self.w_map.slots[key] = W_CFunction(self, function) + def init_w_call(self): for key, function in cfunction_definitions['Call'].items(): self.w_call.slots[key] = W_CFunction(self, function) @@ -70,6 +78,7 @@ self.w_core.slots['nil'] = self.w_nil self.w_core.slots['List'] = self.w_list self.w_core.slots['Call'] = self.w_call + self.w_core.slots['Map'] = self.w_map def init_w_number(self): self.w_number = instantiate(W_Number) Added: pypy/branch/io-lang/pypy/lang/io/test/test_map.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_map.py Fri May 29 12:26:17 2009 @@ -0,0 +1,24 @@ +from pypy.lang.io.parserhack import parse, interpret +from pypy.lang.io.model import W_Map, W_Number, W_ImmutableSequence +import py.test + +def test_map_proto(): + inp = 'Lobby Core Map' + res, space = interpret(inp) + assert res == space.w_map + assert isinstance(res, W_Map) + +def test_map_clone(): + inp = 'Map clone' + res, space = interpret(inp) + assert isinstance(res, W_Map) + assert res.protos == [space.w_map] + assert space.w_map.protos == [space.w_object] + +def test_at_put(): + inp = 'Map clone atPut("foo", "bar")' + res, space = interpret(inp) + keys = [(key.value) for key in res.items.keys()] + assert keys == ['foo'] + values = [(val.value) for val in res.items.values()] + assert values == ['bar'] \ No newline at end of file From antocuni at codespeak.net Fri May 29 14:22:02 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 May 2009 14:22:02 +0200 (CEST) Subject: [pypy-svn] r65494 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090529122202.DBA15169EB0@codespeak.net> Author: antocuni Date: Fri May 29 14:22:01 2009 New Revision: 65494 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Log: fix ootype tests Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Fri May 29 14:22:01 2009 @@ -97,17 +97,21 @@ nodesize = cpu.sizeof(node) TP = ootype.Array(ootype.Signed) + NODE_ARRAY = ootype.Array(NODE) XY = ootype.Instance('XY', ootype.ROOT, {'ofield': ootype.Signed, 'oother_field': ootype.Signed, - 'olist': TP}, + 'olist': TP, + 'oitem_list': NODE_ARRAY, + }, _hints = {'virtualizable2': True, - 'virtuals': ('field','list')}) + 'virtuals': ('field','list', 'item_list')}) field_desc = cpu.fielddescrof(XY, 'ofield') array_descr = cpu.arraydescrof(TP) list_desc = cpu.fielddescrof(XY, 'olist') + list_node_desc = cpu.fielddescrof(XY, 'oitem_list') other_field_desc = cpu.fielddescrof(XY, 'oother_field') vdesc = VirtualizableDesc(cpu, XY, XY) xy_vtable = ootype.runtimeClass(XY) @@ -508,8 +512,4 @@ pass class TestOOtype(OOtypeMixin, BaseTestOptimize2): - def test_virtual_with_virtualizable(self): - py.test.skip("XXX") - - test_virtual_with_virtualizable_escapes = test_virtual_with_virtualizable - test_virtualizable_double_read = test_virtual_with_virtualizable + pass From cfbolz at codespeak.net Fri May 29 17:06:00 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 May 2009 17:06:00 +0200 (CEST) Subject: [pypy-svn] r65495 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test Message-ID: <20090529150600.7B42C169F86@codespeak.net> Author: cfbolz Date: Fri May 29 17:05:58 2009 New Revision: 65495 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py Log: support for functions that are annotated to be pure Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Fri May 29 17:05:58 2009 @@ -270,7 +270,8 @@ assert not portal, "portal has been hidden!" graph = make_calling_stub(codewriter.rtyper, graph) self.graph = graph - self.raise_analyzer = RaiseAnalyzer(self.cpu.rtyper.annotator.translator) + self.translator = self.cpu.rtyper.annotator.translator + self.raise_analyzer = RaiseAnalyzer(self.translator) def assemble(self): """Assemble the opcodes for self.bytecode.""" @@ -928,12 +929,18 @@ calldescr, non_void_args = self.codewriter.getcalldescr(op.args[0], args, op.result) + pure = False + if op.opname == "direct_call": + func = get_funcobj(op.args[0].value)._callable + pure = getattr(func, "_pure_function_", False) try: canraise = self.raise_analyzer.can_raise(op) except lltype.DelayedPointer: canraise = True # if we need to look into the delayed ptr that is # the portal, then it's certainly going to raise - if canraise: + if pure: + self.emit('residual_call_pure') + elif canraise: self.emit('residual_call') else: self.emit('residual_call_noexception') Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py Fri May 29 17:05:58 2009 @@ -1,5 +1,5 @@ import py -from pypy.rlib.jit import JitDriver, we_are_jitted +from pypy.rlib.jit import JitDriver, we_are_jitted, hint 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 @@ -265,6 +265,17 @@ assert res == 42 self.check_history_(int_add=1, int_mul=0, call=1, guard_no_exception=0) + def test_residual_call_pure(self): + def externfn(x, y): + return x * y + externfn._pure_function_ = True + def f(n): + n = hint(n, promote=True) + return externfn(n, n+1) + res = self.interp_operations(f, [6]) + assert res == 42 + self.check_history_(int_add=0, int_mul=0, call=0) + def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) class X(object): From pedronis at codespeak.net Fri May 29 17:24:57 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 May 2009 17:24:57 +0200 (CEST) Subject: [pypy-svn] r65496 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090529152457.D69DD16A008@codespeak.net> Author: pedronis Date: Fri May 29 17:24:57 2009 New Revision: 65496 Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt Log: proper talks link Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/announcement.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/announcement.txt Fri May 29 17:24:57 2009 @@ -73,4 +73,4 @@ .. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint .. _`the technical reports available and other relevant documentation`: http://codespeak.net/pypy/dist/pypy/doc/docindex.html -.. _`EuroPython schedule`: http://europython.eu/xxx +.. _`EuroPython schedule`: http://europython.eu/talks/timetable From cfbolz at codespeak.net Fri May 29 17:57:35 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 May 2009 17:57:35 +0200 (CEST) Subject: [pypy-svn] r65497 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090529155735.3758816A016@codespeak.net> Author: cfbolz Date: Fri May 29 17:57:33 2009 New Revision: 65497 Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt Log: (pedronis, cfbolz): trying to flesh out the announcement. Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/announcement.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/announcement.txt Fri May 29 17:57:33 2009 @@ -13,18 +13,30 @@ during the conference since it will give you a good overview of the status of development. -.. xxx When/if tutorial? -On the morning of the first sprint day we will also have a -tutorial session for those new to PyPy development. - ------------------------------- Goals and topics of the sprint ------------------------------ There are many possible and interesting sprint topics to work on - here we list some possible task areas: -TBA + - trying out software on PyPy's Python interpreter: + the CPython test suite is not all that complete, therefore the fact that we + pass most tests is no real indication of bug-freeness. We have tried and + know that frameworks like Django and Twisted work with PyPy. Therefore we would + like to try running more "real application" on top of the Python interpreter + (ideally ones that have a good test suite themselves and that don't need + unusual extension modules). Running things on windows is also interesting, + we know our coverage there is not as good as on Linux. + + - check and improve Mac OS X support + + - starting to work on porting 2.6 features to PyPy's Python interpreter + + - ongoing JIT generator work + + - of course we are open to other ideas for what to work on. Examples could + be working on other language interpreters, sandboxing, ... + ------------ Registration From cfbolz at codespeak.net Fri May 29 18:02:11 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 May 2009 18:02:11 +0200 (CEST) Subject: [pypy-svn] r65498 - pypy/extradoc/sprintinfo/ep2009 Message-ID: <20090529160211.056BE16A013@codespeak.net> Author: cfbolz Date: Fri May 29 18:02:10 2009 New Revision: 65498 Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt Log: (arigo) typos. Modified: pypy/extradoc/sprintinfo/ep2009/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/ep2009/announcement.txt (original) +++ pypy/extradoc/sprintinfo/ep2009/announcement.txt Fri May 29 18:02:10 2009 @@ -23,9 +23,9 @@ the CPython test suite is not all that complete, therefore the fact that we pass most tests is no real indication of bug-freeness. We have tried and know that frameworks like Django and Twisted work with PyPy. Therefore we would - like to try running more "real application" on top of the Python interpreter + like to try running more "real applications" on top of the Python interpreter (ideally ones that have a good test suite themselves and that don't need - unusual extension modules). Running things on windows is also interesting, + unusual extension modules). Running things on Windows is also interesting, we know our coverage there is not as good as on Linux. - check and improve Mac OS X support From cfbolz at codespeak.net Fri May 29 18:38:06 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 May 2009 18:38:06 +0200 (CEST) Subject: [pypy-svn] r65499 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test Message-ID: <20090529163806.C7A1E169E8E@codespeak.net> Author: cfbolz Date: Fri May 29 18:38:04 2009 New Revision: 65499 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py Log: a skipped test that I am not sure what to do with Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_basic.py Fri May 29 18:38:04 2009 @@ -276,6 +276,27 @@ assert res == 42 self.check_history_(int_add=0, int_mul=0, call=0) + def test_residual_call_pure_exception(self): + py.test.skip("fix this") + def externfn(x, y): + if x == 0: + raise IndexError + return x * y + externfn._pure_function_ = True + def f(n): + try: + n = hint(n, promote=True) + return externfn(n, n+1) + except IndexError: + return 5 + res = self.interp_operations(f, [6]) + assert res == 42 + self.check_history_(int_add=0, int_mul=0, call=0) + res = self.interp_operations(f, [0]) + assert res == 5 + # XXX what should go to the next line? + # self.check_history_(int_add=0, int_mul=0, call=0) + def test_constant_across_mp(self): myjitdriver = JitDriver(greens = [], reds = ['n']) class X(object): From cfbolz at codespeak.net Fri May 29 19:27:17 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 May 2009 19:27:17 +0200 (CEST) Subject: [pypy-svn] r65500 - pypy/branch/pyjitpl5-experiments/pypy/objspace/std Message-ID: <20090529172717.07909169ED4@codespeak.net> Author: cfbolz Date: Fri May 29 19:27:14 2009 New Revision: 65500 Modified: pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py Log: Rewrite shared dicts to be a bit more regular. Slightly slower in some cases, but less confusing and easier for the JIT. Modified: pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py Fri May 29 19:27:14 2009 @@ -4,6 +4,7 @@ from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX, OPTIMIZED_BUILTINS from pypy.rlib.objectmodel import r_dict, we_are_translated +from pypy.rlib.jit import purefunction def _is_str(space, w_key): return space.is_w(space.type(w_key), space.w_str) @@ -695,7 +696,7 @@ self.length = length self.back_struct = back_struct if other_structs is None: - other_structs = [] + other_structs = {} self.other_structs = other_structs self.last_key = last_key if last_key is not None: @@ -703,16 +704,11 @@ self.propagating = False def new_structure(self, added_key): - keys = {} - for key, item in self.keys.iteritems(): - if item >= 0: - keys[key] = item + keys = self.keys.copy() + keys[added_key] = len(self.keys) new_structure = SharedStructure(keys, self.length + 1, - [], added_key, self) - new_index = len(keys) - new_structure.keys[added_key] = new_index - self.keys[added_key] = ~len(self.other_structs) - self.other_structs.append(new_structure) + {}, added_key, self) + self.other_structs[added_key] = new_structure return new_structure @@ -751,18 +747,17 @@ return self._as_rdict().setitem(w_key, w_value) def setitem_str(self, w_key, w_value, shadows_type=True): - m = ~len(self.structure.other_structs) key = self.space.str_w(w_key) - i = self.structure.keys.get(key, m) + i = self.structure.keys.get(key, -1) if i >= 0: self.entries[i] = w_value return self if not self.structure.propagating: return self._as_rdict(as_strdict=True).setitem_str(w_key, w_value) - if i == m: + new_structure = self.structure.other_structs.get(key, None) + if new_structure is None: new_structure = self.structure.new_structure(key) else: - new_structure = self.structure.other_structs[~i] new_structure.propagating = True self.entries.append(w_value) assert self.structure.length + 1 == new_structure.length @@ -845,9 +840,8 @@ implementation = self.dictimplementation assert isinstance(implementation, SharedDictImplementation) for key, index in self.iterator: - if index >= 0: - w_value = implementation.entries[index] - return self.space.newtuple([self.space.wrap(key), w_value]) + w_value = implementation.entries[index] + return self.space.newtuple([self.space.wrap(key), w_value]) else: return None @@ -860,8 +854,7 @@ implementation = self.dictimplementation assert isinstance(implementation, SharedDictImplementation) for key, index in self.iterator: - if index >= 0: - return self.space.wrap(key) + return self.space.wrap(key) else: return None From cfbolz at codespeak.net Fri May 29 20:12:15 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 May 2009 20:12:15 +0200 (CEST) Subject: [pypy-svn] r65501 - in pypy/branch/pyjitpl5-experiments/pypy: module/pypyjit objspace/std Message-ID: <20090529181215.7672816A029@codespeak.net> Author: cfbolz Date: Fri May 29 20:12:14 2009 New Revision: 65501 Modified: pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/policy.py pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py Log: Remove one dictionary lookup in the residual code for an attribute access when using shared dicts. Modified: pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/policy.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/policy.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/module/pypyjit/policy.py Fri May 29 20:12:14 2009 @@ -35,7 +35,6 @@ # gc_id operation if func.__name__ == 'id__ANY': return False - return True # floats if mod == 'pypy.rlib.rbigint': #if func.__name__ == '_bigint_true_divide': Modified: pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/objspace/std/dictmultiobject.py Fri May 29 20:12:14 2009 @@ -711,6 +711,16 @@ self.other_structs[added_key] = new_structure return new_structure + def lookup_position(self, key): + # jit helper + self = hint(self, promote=True) + key = hint(key, promote=True) + return _lookup_position_shared(self, key) + + at purefunction +def _lookup_position_shared(self, key): + return self.keys.get(key, -1) + class State(object): def __init__(self, space): @@ -730,8 +740,8 @@ w_lookup_type = space.type(w_lookup) if space.is_w(w_lookup_type, space.w_str): lookup = space.str_w(w_lookup) - i = self.structure.keys.get(lookup, -1) - if i < 0: + i = self.structure.lookup_position(lookup) + if i == -1: return None return self.entries[i] elif _is_sane_hash(space, w_lookup_type): @@ -748,8 +758,8 @@ def setitem_str(self, w_key, w_value, shadows_type=True): key = self.space.str_w(w_key) - i = self.structure.keys.get(key, -1) - if i >= 0: + i = self.structure.lookup_position(key) + if i != -1: self.entries[i] = w_value return self if not self.structure.propagating: From fijal at codespeak.net Fri May 29 20:27:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 20:27:49 +0200 (CEST) Subject: [pypy-svn] r65502 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86 Message-ID: <20090529182749.8137416A030@codespeak.net> Author: fijal Date: Fri May 29 20:27:46 2009 New Revision: 65502 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py Log: different register allocator. it's horribly inneficient in terms of time it takes, but I want to measure the difference of resulting assembler first Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py Fri May 29 20:27:46 2009 @@ -285,6 +285,7 @@ def _walk_operations(self, operations): i = 0 + self.operations = operations while i < len(operations): op = operations[i] self.position = i @@ -572,6 +573,14 @@ except KeyError: return self.stack_bindings[v] + def _compute_next_usage(self, v, pos): + for i in range(pos, len(self.operations)): + if v in self.operations[i].args: + return i + if i > self.longevity[v][1]: + return -1 + return -1 + def pick_variable_to_spill(self, v, forbidden_vars, selected_reg=None): # XXX could be improved if v in self.jump_reg_candidates and (selected_reg is None or @@ -580,12 +589,24 @@ if (reg is self.jump_reg_candidates[v] and var not in forbidden_vars): return var - iter = self.reg_bindings.iterkeys() - while 1: - next = iter.next() + candidates = [] + for next in self.reg_bindings: if (next not in forbidden_vars and selected_reg is None or self.reg_bindings[next] is selected_reg): - return next + candidates.append(next) + assert candidates + if len(candidates) == 1: + return candidates[0] + max = 0 + choosen = None + for one in candidates: + next_usage = self._compute_next_usage(one, self.position) + if next_usage == -1: + return one + elif next_usage > max: + next_usage = max + chosen = one + return chosen def move_variable_away(self, v, prev_loc): reg = None From fijal at codespeak.net Fri May 29 20:29:50 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 20:29:50 +0200 (CEST) Subject: [pypy-svn] r65503 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86 Message-ID: <20090529182950.59CA216A033@codespeak.net> Author: fijal Date: Fri May 29 20:29:48 2009 New Revision: 65503 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py Log: typo Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py Fri May 29 20:29:48 2009 @@ -598,7 +598,7 @@ if len(candidates) == 1: return candidates[0] max = 0 - choosen = None + chosen = None for one in candidates: next_usage = self._compute_next_usage(one, self.position) if next_usage == -1: From fijal at codespeak.net Fri May 29 20:31:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 20:31:09 +0200 (CEST) Subject: [pypy-svn] r65504 - pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp Message-ID: <20090529183109.D196E16A020@codespeak.net> Author: fijal Date: Fri May 29 20:31:09 2009 New Revision: 65504 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Log: Ekhem Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/codewriter.py Fri May 29 20:31:09 2009 @@ -931,8 +931,11 @@ op.result) pure = False if op.opname == "direct_call": - func = get_funcobj(op.args[0].value)._callable - pure = getattr(func, "_pure_function_", False) + func = getattr(get_funcobj(op.args[0].value), '_callable', None) + if func is None: + pure = getattr(func, "_pure_function_", False) + else: + pure = False # a portal, likely try: canraise = self.raise_analyzer.can_raise(op) except lltype.DelayedPointer: From fijal at codespeak.net Fri May 29 21:19:06 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 21:19:06 +0200 (CEST) Subject: [pypy-svn] r65505 - pypy/branch/pyjitpl5-experiments/pypy/interpreter Message-ID: <20090529191906.2DB0B16A020@codespeak.net> Author: fijal Date: Fri May 29 21:19:03 2009 New Revision: 65505 Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/function.py Log: reintroduce the hint, it might have been a bad idea to remove Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/function.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/interpreter/function.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/interpreter/function.py Fri May 29 21:19:03 2009 @@ -11,6 +11,7 @@ from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.eval import Code from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack +from pypy.rlib.jit import hint funccallunrolling = unrolling_iterable(range(4)) @@ -45,7 +46,7 @@ return self.code.funcrun_obj(self, w_obj, args) def getcode(self): - return self.code + return hint(self.code, promote=True) def funccall(self, *args_w): # speed hack from pypy.interpreter import gateway From fijal at codespeak.net Fri May 29 21:27:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 21:27:15 +0200 (CEST) Subject: [pypy-svn] r65506 - in pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm: . test Message-ID: <20090529192715.DAF5F16A050@codespeak.net> Author: fijal Date: Fri May 29 21:27:12 2009 New Revision: 65506 Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/conftest.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/demo2.cpp pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/test/test_runner.py Log: unskip the test and disable tail calls. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/conftest.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/conftest.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/conftest.py Fri May 29 21:27:12 2009 @@ -1,5 +1 @@ import py - -class Directory(py.test.collect.Directory): - def consider_dir(self, path): - py.test.skip("llvm-jit tests skipped") Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/demo2.cpp ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/demo2.cpp (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/demo2.cpp Fri May 29 21:27:12 2009 @@ -1,7 +1,5 @@ /* LLVM includes */ - #include -#include "llvm/LinkAllPasses.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" @@ -15,7 +13,7 @@ */ void _LLVM_SetFlags(void) { - PerformTailCallOpt = true; + //PerformTailCallOpt = true; } /* This piece of code regroups conveniently a part of the initialization. Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py Fri May 29 21:27:12 2009 @@ -31,10 +31,10 @@ o1name = os.path.join(dirname, 'demo1.o') o2name = os.path.join(dirname, 'demo2.o') - do("gcc -c '%s' -o '%s' -I/home/fijal/load/llvm/include" % (cname, o1name)) - do("g++ -c '%s' -o '%s' `%s --cppflags`" % (cppname, o2name, llvm_config)) - do("g++ -shared '%s' '%s' -o '%s' " % (o1name, o2name, libname) + - " `%s --cflags --ldflags --libs jit engine` -lLLVMInstrumentation -lLLVMipo -lLLVMipa -lLLVMTransformUtils -lLLVMAnalysis -lLLVMCore" % llvm_config) + do("g++ -g -c '%s' -o '%s' `%s --cppflags`" % (cname, o1name, llvm_config)) + do("g++ -g -c '%s' -o '%s' `%s --cppflags`" % (cppname, o2name, llvm_config)) + do("g++ -g -shared '%s' '%s' -o '%s'" % (o1name, o2name, libname) + + " `%s --cflags --ldflags --libs jit engine`" % llvm_config) compilation_info = ExternalCompilationInfo( library_dirs = [dirname], Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py Fri May 29 21:27:12 2009 @@ -26,8 +26,8 @@ def setup_once(self): if not we_are_translated(): teardown_now() - self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit") llvm_rffi.LLVM_SetFlags() + self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit") if sys.maxint == 2147483647: self.ty_int = llvm_rffi.LLVMInt32Type() else: @@ -269,7 +269,7 @@ def execute_operations(self, loop): print 'execute_operations: %s' % (loop._llvm_func_addr,) - import time; time.sleep(2) + #import time; time.sleep(2) res = loop._llvm_entry_stub(loop._llvm_func_addr) print '\t--->', res return self.fail_ops[res] Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/test/test_runner.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/test/test_runner.py Fri May 29 21:27:12 2009 @@ -50,6 +50,7 @@ cpu.set_future_value_int(2, 0) cpu.execute_operations(loop) assert cpu.get_latest_value_int(0) == 3*(2**11) + py.test.skip("fails because tail-recursion is not handled yet") cpu.set_future_value_int(0, 2**29) cpu.set_future_value_int(1, 3) cpu.set_future_value_int(2, 0) From fijal at codespeak.net Fri May 29 22:20:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 29 May 2009 22:20:58 +0200 (CEST) Subject: [pypy-svn] r65507 - pypy/branch/pyjitpl5-experiments/pypy/interpreter Message-ID: <20090529202058.07AC5169E97@codespeak.net> Author: fijal Date: Fri May 29 22:20:58 2009 New Revision: 65507 Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/nestedscope.py pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py Log: move a hints a bit around, change the way things are called to pass args instead of attributes on self Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/interpreter/nestedscope.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/interpreter/nestedscope.py Fri May 29 22:20:58 2009 @@ -82,9 +82,8 @@ cells = None - def initialize_frame_scopes(self, closure): - super_initialize_frame_scopes(self, closure) - code = self.pycode + def initialize_frame_scopes(self, closure, code): + super_initialize_frame_scopes(self, closure, code) ncellvars = len(code.co_cellvars) nfreevars = len(code.co_freevars) if not nfreevars: Modified: pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py (original) +++ pypy/branch/pyjitpl5-experiments/pypy/interpreter/pyframe.py Fri May 29 22:20:58 2009 @@ -58,10 +58,10 @@ self.builtin = space.builtin.pick_builtin(w_globals) # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. # class bodies only have CO_NEWLOCALS. - self.initialize_frame_scopes(closure) + self.initialize_frame_scopes(closure, code) self.fastlocals_w = [None]*self.numlocals make_sure_not_resized(self.fastlocals_w) - self.f_lineno = self.pycode.co_firstlineno + self.f_lineno = code.co_firstlineno def get_builtin(self): if self.space.config.objspace.honor__builtins__: @@ -69,13 +69,13 @@ else: return self.space.builtin - def initialize_frame_scopes(self, closure): + def initialize_frame_scopes(self, closure, code): # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. # class bodies only have CO_NEWLOCALS. # CO_NEWLOCALS: make a locals dict unless optimized is also set # CO_OPTIMIZED: no locals dict needed at all # NB: this method is overridden in nestedscope.py - flags = self.pycode.co_flags + flags = code.co_flags if flags & pycode.CO_OPTIMIZED: return if flags & pycode.CO_NEWLOCALS: @@ -86,7 +86,7 @@ def run(self): """Start this frame's execution.""" - if self.pycode.co_flags & pycode.CO_GENERATOR: + if self.getcode().co_flags & pycode.CO_GENERATOR: from pypy.interpreter.generator import GeneratorIterator return self.space.wrap(GeneratorIterator(self)) else: @@ -361,7 +361,7 @@ return self.pycode.hidden_applevel def getcode(self): - return self.pycode + return hint(self.pycode, promote=True) def getfastscope(self): "Get the fast locals as a list." From david at codespeak.net Sat May 30 15:57:31 2009 From: david at codespeak.net (david at codespeak.net) Date: Sat, 30 May 2009 15:57:31 +0200 (CEST) Subject: [pypy-svn] r65508 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090530135731.751A216A054@codespeak.net> Author: david Date: Sat May 30 15:57:28 2009 New Revision: 65508 Modified: pypy/branch/io-lang/pypy/lang/io/map.py pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/test/test_map.py Log: Added Map type for key value based collections, extended all types by a hash method and impelemented some Map methods Modified: pypy/branch/io-lang/pypy/lang/io/map.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/map.py (original) +++ pypy/branch/io-lang/pypy/lang/io/map.py Sat May 30 15:57:28 2009 @@ -1,6 +1,10 @@ from pypy.lang.io.register import register_method @register_method('Map', 'atPut', unwrap_spec=[object, object, object]) -def map_at_put(space, target, key, value): - target.items[key] = value - return target \ No newline at end of file +def map_at_put(space, w_target, w_key, w_value): + w_target.at_put(w_key, w_value) + return w_target + + at register_method('Map', 'at', unwrap_spec=[object, object]) +def map_at(space, w_target, w_key): + return w_target.at(w_key) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Sat May 30 15:57:28 2009 @@ -11,7 +11,16 @@ def __ne__(self, other): return not self == other - + + def hash(self): + h = 0 + for w_x in self.slots: + h += w_x.hash() + for x in self.protos: + h += hash(x) + + return h + def lookup(self, name, seen=None): if seen is None: seen = {} @@ -49,6 +58,9 @@ cloned = W_Number(self.space, self.value) cloned.protos = [self] return cloned + + def hash(self): + return hash(self.value) class W_List(W_Object): def __init__(self, space, protos = [], items = []): @@ -72,6 +84,12 @@ l = self.clone() l.items += items return l + + def hash(self): + h = 0 + for x in self.items: + h += x.hash() + return h class W_Map(W_Object): """A key/value dictionary appropriate for holding large key/value collections.""" @@ -82,10 +100,30 @@ def clone(self): return W_Map(self.space, [self], dict(self.items)) + def hash(self): + h = 0 + for key, val in self.items: + h += key + val.hash() + return h + + def at(self, w_key): + return self.items[w_key.hash()].value + + def at_put(self, w_key, w_value): + self.items[w_key.hash()] = MapEntry(w_key, w_value) + +class MapEntry(object): + def __init__(self, w_key, w_value): + self.key = w_key + self.value = w_value + + class W_ImmutableSequence(W_Object): def __init__(self, space, string): self.value = string - + + def hash(self): + return hash(self.value) class W_CFunction(W_Object): def __init__(self, space, function): @@ -95,6 +133,9 @@ def apply(self, space, w_receiver, w_message, w_context): return self.function(space, w_receiver, w_message, w_context) + def hash(self): + return hash(self.function) + class W_Message(W_Object): def __init__(self, space, name, arguments, next = None): self.name = name @@ -106,7 +147,12 @@ def __repr__(self): return "Message(%r, %r, %r)" % (self.name, self.arguments, self.next) - + def hash(self): + h = hash(self.name) + for x in self.arguments: + h += x.hash() + return h + def eval(self, space, w_receiver, w_context): if self.name == ';': # xxx is this correct? @@ -168,6 +214,13 @@ def clone_and_init(self, space, arguments, body, activateable): return W_Block(space, arguments, body, activateable, [self]) + def hash(self): + h = self.body.hash() + for x in self.arguments: + h += x.hash() + return h + + def parse_hex(string): if not string.startswith("0x"): raise ValueError Modified: pypy/branch/io-lang/pypy/lang/io/test/test_map.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_map.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_map.py Sat May 30 15:57:28 2009 @@ -18,7 +18,17 @@ def test_at_put(): inp = 'Map clone atPut("foo", "bar")' res, space = interpret(inp) - keys = [(key.value) for key in res.items.keys()] + keys = [(entry.key.value) for entry in res.items.values()] assert keys == ['foo'] - values = [(val.value) for val in res.items.values()] - assert values == ['bar'] \ No newline at end of file + values = [(entry.value.value) for entry in res.items.values()] + assert values == ['bar'] + +def test_at(): + inp = 'Map clone atPut("foo", "bar") atPut("lorem", "ipsum") at("foo")' + res, space = interpret(inp) + assert res.value == 'bar' + +def test_key_hashing(): + inp = 'Map clone atPut(1, "bar") atPut(nil, "ipsum") atPut("foo", 123) at(nil)' + res, space = interpret(inp) + assert res.value == 'ipsum' \ No newline at end of file From david at codespeak.net Sat May 30 16:10:58 2009 From: david at codespeak.net (david at codespeak.net) Date: Sat, 30 May 2009 16:10:58 +0200 (CEST) Subject: [pypy-svn] r65509 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090530141058.ED1C516A03F@codespeak.net> Author: david Date: Sat May 30 16:10:56 2009 New Revision: 65509 Modified: pypy/branch/io-lang/pypy/lang/io/map.py pypy/branch/io-lang/pypy/lang/io/test/test_map.py Log: Restricted keys in maps to strings Modified: pypy/branch/io-lang/pypy/lang/io/map.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/map.py (original) +++ pypy/branch/io-lang/pypy/lang/io/map.py Sat May 30 16:10:56 2009 @@ -1,10 +1,12 @@ from pypy.lang.io.register import register_method - +from pypy.lang.io.model import W_ImmutableSequence @register_method('Map', 'atPut', unwrap_spec=[object, object, object]) def map_at_put(space, w_target, w_key, w_value): + assert isinstance(w_key, W_ImmutableSequence) w_target.at_put(w_key, w_value) return w_target @register_method('Map', 'at', unwrap_spec=[object, object]) def map_at(space, w_target, w_key): + assert isinstance(w_key, W_ImmutableSequence) return w_target.at(w_key) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_map.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_map.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_map.py Sat May 30 16:10:56 2009 @@ -29,6 +29,6 @@ assert res.value == 'bar' def test_key_hashing(): - inp = 'Map clone atPut(1, "bar") atPut(nil, "ipsum") atPut("foo", 123) at(nil)' + inp = 'Map clone atPut("1", "bar") atPut("nil", "ipsum") atPut("foo", 123) at("nil")' res, space = interpret(inp) assert res.value == 'ipsum' \ No newline at end of file From david at codespeak.net Sat May 30 17:14:44 2009 From: david at codespeak.net (david at codespeak.net) Date: Sat, 30 May 2009 17:14:44 +0200 (CEST) Subject: [pypy-svn] r65510 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090530151444.9A259169FD1@codespeak.net> Author: david Date: Sat May 30 17:14:42 2009 New Revision: 65510 Modified: pypy/branch/io-lang/pypy/lang/io/map.py pypy/branch/io-lang/pypy/lang/io/model.py pypy/branch/io-lang/pypy/lang/io/test/test_map.py Log: Implemented Builtin Map CFunction methods Modified: pypy/branch/io-lang/pypy/lang/io/map.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/map.py (original) +++ pypy/branch/io-lang/pypy/lang/io/map.py Sat May 30 17:14:42 2009 @@ -1,5 +1,6 @@ from pypy.lang.io.register import register_method -from pypy.lang.io.model import W_ImmutableSequence +from pypy.lang.io.model import W_ImmutableSequence, W_Number, W_List + @register_method('Map', 'atPut', unwrap_spec=[object, object, object]) def map_at_put(space, w_target, w_key, w_value): assert isinstance(w_key, W_ImmutableSequence) @@ -9,4 +10,57 @@ @register_method('Map', 'at', unwrap_spec=[object, object]) def map_at(space, w_target, w_key): assert isinstance(w_key, W_ImmutableSequence) - return w_target.at(w_key) \ No newline at end of file + return w_target.at(w_key) + + at register_method('Map', 'empty') +def map_empty(space, w_target, w_message, w_context): + w_target.empty() + return w_target + + at register_method('Map', 'atIfAbsentPut', unwrap_spec=[object, object, object]) +def map_at_if_absent_put(space, w_target, w_key, w_value): + assert isinstance(w_key, W_ImmutableSequence) + if w_target.has_key(w_key): + return w_target.at(w_key) + w_target.at_put(w_key, w_value) + return w_value + + at register_method('Map', 'hasKey', unwrap_spec=[object, object]) +def map_has_key(space, w_target, w_key): + assert isinstance(w_key, W_ImmutableSequence) + if w_target.has_key(w_key): + return space.w_true + return space.w_false + + at register_method('Map', 'size') +def map_size(space, w_target, w_message, w_context): + return W_Number(space, w_target.size()) + + at register_method('Map', 'removeAt', unwrap_spec=[object, object]) +def map_has_key(space, w_target, w_key): + assert isinstance(w_key, W_ImmutableSequence) + w_target.remove_at(w_key) + return w_target + + at register_method('Map', 'hasValue', unwrap_spec=[object, object]) +def map_has_value(space, w_target, w_value): + if w_target.has_value(w_value): + return space.w_true + return space.w_false + + at register_method('Map', 'values') +def map_values(space, w_target, w_message, w_context): + return space.w_list.clone_and_init(space, w_target.values()) + + at register_method('Map', 'foreach') +def map_foreach(space, w_target, w_message, w_context): + argcount = len(w_message.arguments) + assert argcount == 3 + key = w_message.arguments[0].name + value = w_message.arguments[1].name + + return w_target.foreach(space, key, value, w_message.arguments[2], w_context) + + at register_method('Map', 'keys') +def map_keys(space, w_target, w_message, w_context): + return space.w_list.clone_and_init(space, w_target.keys()) \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/model.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/model.py (original) +++ pypy/branch/io-lang/pypy/lang/io/model.py Sat May 30 17:14:42 2009 @@ -112,6 +112,40 @@ def at_put(self, w_key, w_value): self.items[w_key.hash()] = MapEntry(w_key, w_value) + def empty(self): + self.items.clear() + + def has_key(self, w_key): + return w_key.hash() in self.items + + def size(self): + return len(self.items) + + def remove_at(self, w_key): + try: + del(self.items[w_key.hash()]) + except Exception, e: + pass + + def has_value(self, w_value): + for x in self.items.values(): + if x.value == x: + return True + return False + + def values(self): + return [x.value for x in self.items.values()] + + def foreach(self, space, key_name, value_name, w_body, w_context): + for item in self.items.values(): + w_context.slots[key_name] = item.key + w_context.slots[value_name] = item.value + t = w_body.eval(space, w_context, w_context) + return t + + def keys(self): + return [x.key for x in self.items.values()] + class MapEntry(object): def __init__(self, w_key, w_value): self.key = w_key Modified: pypy/branch/io-lang/pypy/lang/io/test/test_map.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_map.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_map.py Sat May 30 17:14:42 2009 @@ -1,5 +1,5 @@ from pypy.lang.io.parserhack import parse, interpret -from pypy.lang.io.model import W_Map, W_Number, W_ImmutableSequence +from pypy.lang.io.model import W_Map, W_Number, W_ImmutableSequence, W_List import py.test def test_map_proto(): @@ -31,4 +31,88 @@ def test_key_hashing(): inp = 'Map clone atPut("1", "bar") atPut("nil", "ipsum") atPut("foo", 123) at("nil")' res, space = interpret(inp) - assert res.value == 'ipsum' \ No newline at end of file + assert res.value == 'ipsum' + +def test_empty(): + inp = 'Map clone atPut("1", "bar") atPut("nil", "ipsum") atPut("foo", 123) empty' + res, space = interpret(inp) + assert res.items == {} + +def test_atIfAbsentPut(): + inp = 'Map clone atPut("1", nil) atIfAbsentPut("1", "lorem")' + res, space = interpret(inp) + assert res == space.w_nil + + inp = 'Map clone atPut("2", "bar") atIfAbsentPut("1", "lorem")' + res, space = interpret(inp) + assert res.value == 'lorem' + +def test_has_key(): + inp = 'Map clone atPut("1", nil) atPut("2", "lorem") hasKey("1")' + res, space = interpret(inp) + assert res == space.w_true + + inp = 'Map clone atPut("1", nil) atPut("2", "lorem") hasKey("99")' + res, space = interpret(inp) + assert res == space.w_false + +def test_size(): + inp = 'Map clone size' + res, space = interpret(inp) + assert res.value == 0 + + inp = 'Map clone atPut("1", nil) atPut("2", "lorem") size' + res, space = interpret(inp) + assert res.value == 2 + +def test_remve_at(): + inp = 'Map clone atPut("1", "nil") atPut("2", "lorem") atPut("3", 3) atPut("4", 234) removeAt("2")' + res, space = interpret(inp) + keys = [(entry.key.value) for entry in res.items.values()] + assert keys == ['1', '3', '4'] + values = [(entry.value.value) for entry in res.items.values()] + assert values == ['nil', 3, 234] + +def test_has_value(): + inp = 'Map clone atPut("1", "nil") atPut("2", "lorem") atPut("3", 3) atPut("4", 234) hasValue("234")' + res, space = interpret(inp) + assert res == space.w_true + + inp = 'Map clone atPut("1", "nil") atPut("2", "lorem") atPut("3", 3) atPut("4", 234) hasValue("1234567890")' + res, space = interpret(inp) + assert res == space.w_false + +def test_values(): + inp = 'Map clone atPut("1", 12345) atPut("2", 99) atPut("3", 3) atPut("4", 234) values' + res, space = interpret(inp) + assert isinstance(res, W_List) + values = [x.value for x in res.items] + should = [12345, 99, 3, 234] + assert len(should) == len(values) + for x in values: + assert x in should + +def test_foreach(): + inp = """b := Map clone do( + atPut("1", 12345) + atPut("2", 99) + atPut("3", 3) + atPut("4", 234) + ) + c := list() + b foreach(key, value, c append(list(key, value))); c""" + res,space = interpret(inp) + value = sorted([(x.items[0].value, x.items[1].value) for x in res.items]) + assert value == [('1', 12345), ('2', 99), ('3', 3), ('4', 234)] + +def test_keys(): + inp = """b := Map clone do( + atPut("1", 12345) + atPut("2", 99) + atPut("3", 3) + atPut("4", 234) + ) + b keys""" + res, space = interpret(inp) + keys = sorted([x.value for x in res.items]) + assert keys == ['1', '2', '3', '4'] \ No newline at end of file From david at codespeak.net Sun May 31 18:06:24 2009 From: david at codespeak.net (david at codespeak.net) Date: Sun, 31 May 2009 18:06:24 +0200 (CEST) Subject: [pypy-svn] r65515 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090531160624.2033C169F53@codespeak.net> Author: david Date: Sun May 31 18:06:24 2009 New Revision: 65515 Modified: pypy/branch/io-lang/pypy/lang/io/list.py pypy/branch/io-lang/pypy/lang/io/test/test_list.py Log: fixed List first, when called w/o a number, added last, reverseInPlace, removeAll, atPut methods to list Modified: pypy/branch/io-lang/pypy/lang/io/list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/list.py Sun May 31 18:06:24 2009 @@ -65,7 +65,7 @@ return W_Number(space, len(w_target.items)) @register_method('List', 'first') -def list_size(space, w_target, w_message, w_context): +def list_first(space, w_target, w_message, w_context): if len(w_message.arguments) != 0: t = w_message.arguments[0].eval(space, w_target, w_context) assert isinstance(t, W_Number) @@ -75,10 +75,61 @@ if len(w_target.items) == 0 and nfirst == 1: return space.w_nil - + + if nfirst == 1: + return w_target.items[0] flist_w = w_target.clone() if nfirst < 1: flist_w.items = [] else: flist_w.items = flist_w.items[0:nfirst] - return flist_w \ No newline at end of file + return flist_w + + at register_method('List', 'last') +def list_last(space, w_target, w_message, w_context): + if len(w_message.arguments) != 0: + t = w_message.arguments[0].eval(space, w_target, w_context) + assert isinstance(t, W_Number) + nlast = t.value + else: + nlast = 1 + + if len(w_target.items) == 0 and nlast == 1: + return space.w_nil + + if nlast == 1: + return w_target.items[-1] + flist_w = w_target.clone() + if nlast < 1: + flist_w.items = [] + else: + flist_w.items = flist_w.items[len(flist_w.items)-nlast:] + return flist_w + + at register_method('List', 'reverseInPlace') +def list_reverse_in_place(space, w_target, w_message, w_context): + w_target.items.reverse() + return w_target + + at register_method('List', 'removeAll') +def list_remove_all(space, w_target, w_message, w_context): + try: + w_target.items = [] + except Exception, e: + raise Exception, 'index out of bounds' + + return w_target + + at register_method('List', 'atPut') +def list_reverse_in_place(space, w_target, w_message, w_context): + w_key = w_message.arguments[0].eval(space, w_target, w_context) + assert isinstance(w_key, W_Number), "argument 0 to method 'atPut' must be a Number" + key = w_key.value + if len(w_message.arguments) > 1: + w_value = w_message.arguments[1].eval(space, w_target, w_context) + else: + w_value = space.w_nil + + w_target.items[key] = w_value + return w_target + \ No newline at end of file Modified: pypy/branch/io-lang/pypy/lang/io/test/test_list.py ============================================================================== --- pypy/branch/io-lang/pypy/lang/io/test/test_list.py (original) +++ pypy/branch/io-lang/pypy/lang/io/test/test_list.py Sun May 31 18:06:24 2009 @@ -133,13 +133,86 @@ def test_list_first(): inp = 'a := list(9,8,7,6,5,4,3,2,1,1); a first' res, space = interpret(inp) - assert isinstance(res, W_List) - assert res.items[0].value == 9 - assert res.protos == [space.w_lobby.slots['a']] + assert isinstance(res, W_Number) + assert res.value == 9 def test_list_first_n(): inp = 'a := list(9,8,7,6,5,4,3,2,1,1); a first(3)' res, space = interpret(inp) assert isinstance(res, W_List) assert [x.value for x in res.items] == [9,8,7] - assert res.protos == [space.w_lobby.slots['a']] \ No newline at end of file + assert res.protos == [space.w_lobby.slots['a']] + +def test_list_last(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a last' + res, space = interpret(inp) + assert isinstance(res, W_Number) + assert res.value == 100 + +def test_list_last_n(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a last(3)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [2, 1, 100] + assert res.protos == [space.w_lobby.slots['a']] + +def test_list_first_n_overflow(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a first(20)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [9,8,7,6,5,4,3,2,1,100] + assert res.protos == [space.w_lobby.slots['a']] + + +def test_list_last_n_overflow(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a last(20)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [9,8,7,6,5,4,3,2,1,100] + assert res.protos == [space.w_lobby.slots['a']] + + +def test_empty_list_first_n(): + inp = 'a := list(); a first(20)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [] + assert res.protos == [space.w_lobby.slots['a']] + +def test_empty_list_last_n(): + inp = 'a := list(); a last(20)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [] + assert res.protos == [space.w_lobby.slots['a']] + +def test_reverse_in_place(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a reverseInPlace' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [100,1,2,3,4,5,6,7,8,9] + +def test_remove_all(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a removeAll; a' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [] + +def test_at_put(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a atPut(3, 1045)' + res, space = interpret(inp) + assert isinstance(res, W_List) + assert [x.value for x in res.items] == [9,8,7, 1045, 5, 4, 3, 2, 1, 100] + +def test_at_put_raises(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a atPut(1000, 1045)' + py.test.raises(Exception, 'interpret(inp)') + +def test_at_put_wo_value(): + inp = 'a := list(9,8,7,6,5,4,3,2,1,100); a atPut(3)' + res, space = interpret(inp) + assert isinstance(res, W_List) + nums = [W_Number(space, i) for i in range(9, 0, -1)] + nums[3] = space.w_nil + nums.append(W_Number(space, 100)) + assert [x for x in res.items] == nums From arigo at codespeak.net Sun May 31 18:57:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 May 2009 18:57:09 +0200 (CEST) Subject: [pypy-svn] r65516 - pypy/trunk/pypy/rpython/memory/gc Message-ID: <20090531165709.95253169F87@codespeak.net> Author: arigo Date: Sun May 31 18:57:08 2009 New Revision: 65516 Modified: pypy/trunk/pypy/rpython/memory/gc/semispace.py Log: Fix nonsense output when config.gcconfig.debugprint is set. Modified: pypy/trunk/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/trunk/pypy/rpython/memory/gc/semispace.py Sun May 31 18:57:08 2009 @@ -208,11 +208,12 @@ "| used before collection: ", start_usage, "bytes") start_time = time.time() + else: + start_time = 0 # Help the flow space + start_usage = 0 # Help the flow space #llop.debug_print(lltype.Void, 'semispace_collect', int(size_changing)) tospace = self.fromspace fromspace = self.tospace - start_time = 0 # Help the flow space - start_usage = 0 # Help the flow space self.fromspace = fromspace self.tospace = tospace self.top_of_space = tospace + self.space_size From pedronis at codespeak.net Sun May 31 22:21:23 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 31 May 2009 22:21:23 +0200 (CEST) Subject: [pypy-svn] r65518 - pypy/build/bot2/pypybuildbot Message-ID: <20090531202123.2B806169E44@codespeak.net> Author: pedronis Date: Sun May 31 22:21:21 2009 New Revision: 65518 Modified: pypy/build/bot2/pypybuildbot/master.py Log: try the current jit branch tonight Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sun May 31 22:21:21 2009 @@ -54,8 +54,10 @@ Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, STACKLESSAPPLVLLINUX32], hour=4, minute=45), + #Nightly("nightly-jit", [LINUX32, JITLINUX32], + # hour=1, minute=45, branch="branch/pyjitpl5"), Nightly("nightly-jit", [LINUX32, JITLINUX32], - hour=1, minute=45, branch="branch/pyjitpl5"), + hour=1, minute=45, branch="branch/pyjitpl5-experiments"), ], 'status': [status],