From arigo at codespeak.net Fri Sep 1 09:50:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Sep 2006 09:50:07 +0200 (CEST) Subject: [pypy-svn] r31905 - pypy/dist/pypy/annotation/test Message-ID: <20060901075007.7DC5A10060@code0.codespeak.net> Author: arigo Date: Fri Sep 1 09:50:06 2006 New Revision: 31905 Modified: pypy/dist/pypy/annotation/test/test_annrpython.py Log: A pair of (passing) tests about range() returning a list of nonneg integers. Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Fri Sep 1 09:50:06 2006 @@ -2284,6 +2284,30 @@ self.show(a) assert isinstance(s, annmodel.SomeChar) + def test_range_nonneg(self): + def fun(n, k): + for i in range(n): + if k == 17: + return i + return 0 + a = self.RPythonAnnotator() + s = a.build_types(fun, [int, int]) + self.show(a) + assert isinstance(s, annmodel.SomeInteger) + assert s.nonneg + + def test_reverse_range_nonneg(self): + def fun(n, k): + for i in range(n-1, -1, -1): + if k == 17: + return i + return 0 + a = self.RPythonAnnotator() + s = a.build_types(fun, [int, int]) + self.show(a) + assert isinstance(s, annmodel.SomeInteger) + assert s.nonneg + def g(n): return [0,1,2,n] From arigo at codespeak.net Fri Sep 1 13:20:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Sep 2006 13:20:57 +0200 (CEST) Subject: [pypy-svn] r31917 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060901112057.893FA10060@code0.codespeak.net> Author: arigo Date: Fri Sep 1 13:20:56 2006 New Revision: 31917 Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/test/test_tlr.py Log: (pedronis, arigo) Bug, test and fix. The diff looks short but don't underestimate the time it took to get it. In case of generalization, instead of trying to build the next generalized block "by hand", we now only generalize the redboxes state and reuse the existing logic to start a new block from this state. Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Fri Sep 1 13:20:56 2006 @@ -137,27 +137,31 @@ def enter_graph(builder, backstate=None): return builder.build_jitstate(backstate) -def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes): +def start_new_block(states_dic, jitstate, key, redboxes): rgenop = jitstate.rgenop + memo = rvalue.freeze_memo() + frozens = [redbox.freeze(memo) for redbox in redboxes] + memo = rvalue.exactmatch_memo() + outgoingvarboxes = [] + for i in range(len(redboxes)): + res = frozens[i].exactmatch(redboxes[i], outgoingvarboxes, memo) + assert res, "exactmatch() failed" + newblock = rgenop.newblock() + linkargs = [] + for box in outgoingvarboxes: + linkargs.append(box.getgenvar(None)) + box.genvar = newblock.geninputarg(box.kind) + jitstate.curbuilder.enter_block(linkargs, newblock) + states_dic[key] = frozens, newblock + return jitstate +start_new_block._annspecialcase_ = "specialize:arglltype(2)" + +def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes): mylocalredboxes = redboxes redboxes = list(redboxes) jitstate.extend_with_parent_locals(redboxes) if key not in states_dic: - memo = rvalue.freeze_memo() - frozens = [redbox.freeze(memo) for redbox in redboxes] - memo = rvalue.exactmatch_memo() - outgoingvarboxes = [] - for i in range(len(redboxes)): - res = frozens[i].exactmatch(redboxes[i], outgoingvarboxes, memo) - assert res, "exactmatch() failed" - newblock = rgenop.newblock() - linkargs = [] - for box in outgoingvarboxes: - linkargs.append(box.getgenvar(None)) - box.genvar = newblock.geninputarg(box.kind) - jitstate.curbuilder.enter_block(linkargs, newblock) - states_dic[key] = frozens, newblock - return jitstate + return start_new_block(states_dic, jitstate, key, redboxes) frozens, oldblock = states_dic[key] memo = rvalue.exactmatch_memo() @@ -176,28 +180,20 @@ jitstate.curbuilder.leave_block() jitstate.curbuilder.finish_and_goto(linkargs, oldblock) return None - - # Make a more general block + + # We need a more general block. Do it by generalizing all the + # redboxes from outgoingvarboxes, by making them variables. + # Then we make a new block based on this new state. jitstate = dyn_enter_block(jitstate, outgoingvarboxes) - newblock = rgenop.newblock() - linkargs = [] replace_memo = rvalue.copy_memo() for box in outgoingvarboxes: - linkargs.append(box.getgenvar(jitstate.curbuilder)) - for box in outgoingvarboxes: - if box.is_constant(): # constant boxes considered immutable: - box = box.copy(replace_memo) # copy to avoid patching the original - box.genvar = newblock.geninputarg(box.kind) + box = box.forcevar(jitstate.curbuilder, replace_memo) if replace_memo.boxes: for i in range(len(mylocalredboxes)): newbox = redboxes[i].replace(replace_memo) mylocalredboxes[i] = redboxes[i] = newbox jitstate.curbuilder.leave_block() - jitstate.curbuilder.enter_block(linkargs, newblock) - memo = rvalue.freeze_memo() - frozens = [redbox.freeze(memo) for redbox in redboxes] - states_dic[key] = frozens, newblock - return jitstate + return start_new_block(states_dic, jitstate, key, redboxes) retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)" def enter_block(jitstate, redboxes): Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Fri Sep 1 13:20:56 2006 @@ -45,6 +45,17 @@ memo[self] = None self.genvar = newblock.geninputarg(self.kind) + def forcevar(self, builder, memo): + if self.is_constant(): + # cannot mutate constant boxes in-place + box = self.copy(memo) + box.genvar = builder.genop("same_as", [self.genvar], self.kind) + return box + else: + # force virtual containers + self.getgenvar(builder) + return self + def replace(self, memo): memo = memo.boxes return memo.setdefault(self, self) Modified: pypy/dist/pypy/jit/timeshifter/test/test_tlr.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_tlr.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_tlr.py Fri Sep 1 13:20:56 2006 @@ -22,7 +22,6 @@ policy=P_OOPSPEC) assert res == 3111696 - import py; py.test.skip("XXX the following fails") res = self.timeshift(tlr_interpret, [bytecode, 9], [0, 1], policy=P_OOPSPEC) assert res == 81 From arigo at codespeak.net Fri Sep 1 15:18:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Sep 2006 15:18:48 +0200 (CEST) Subject: [pypy-svn] r31925 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20060901131848.F371C10060@code0.codespeak.net> Author: arigo Date: Fri Sep 1 15:18:46 2006 New Revision: 31925 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py Log: (pedronis, arigo) Implemented same_as. Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Fri Sep 1 15:18:46 2006 @@ -286,6 +286,12 @@ def op_cast_pointer(self, (gv_x,), gv_RESTYPE): return gv_x + def op_same_as(self, (gv_x,), gv_RESTYPE): + if gv_x.is_const: # must always return a var + return self.returnvar(gv_x.operand(self)) + else: + return gv_x + def emit_malloc_fixedsize(self, size): # XXX boehm only, no atomic/non atomic distinction for now self.push(imm(size)) From bea at codespeak.net Fri Sep 1 15:28:03 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Fri, 1 Sep 2006 15:28:03 +0200 (CEST) Subject: [pypy-svn] r31926 - pypy/extradoc/planning Message-ID: <20060901132803.741C310060@code0.codespeak.net> Author: bea Date: Fri Sep 1 15:28:01 2006 New Revision: 31926 Modified: pypy/extradoc/planning/sprint-planning.txt Log: updated file with sprint planning from yesterdays sync-meeting Modified: pypy/extradoc/planning/sprint-planning.txt ============================================================================== --- pypy/extradoc/planning/sprint-planning.txt (original) +++ pypy/extradoc/planning/sprint-planning.txt Fri Sep 1 15:28:01 2006 @@ -76,13 +76,23 @@ Primary organizer: Bea -October/? ----------------------------- - -November/? ----------------------------- - - Other general possibilities: Romania, Switzerland (Leysin,Bern), Bristol, Uganda (Nkozi), Bruxelles + +October/University D?sseldorf (HHU) +-------------------------------------- +Time and location: 30th October - 5th November 2006, +at HHU Duesseldorf, Germany + +Nature: open, also possible invite specific people, SOP + +Primary organizer: Carl Friedrich - location, Armin sprint +announcement + +Late autumn sprint dates and possible locations (TBD): +-------------------------------------------------------- +8th-14th January 2007, Poland (fijal checks) or GBorg + +26th feb-4th March 2006, Hildesheim / Trillke (offered, or + somewhere else) From benyoung at codespeak.net Fri Sep 1 17:00:54 2006 From: benyoung at codespeak.net (benyoung at codespeak.net) Date: Fri, 1 Sep 2006 17:00:54 +0200 (CEST) Subject: [pypy-svn] r31934 - in pypy/dist/pypy: bin interpreter objspace/std objspace/std/test Message-ID: <20060901150054.4EDBA10068@code0.codespeak.net> Author: benyoung Date: Fri Sep 1 17:00:40 2006 New Revision: 31934 Modified: pypy/dist/pypy/bin/py.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/objspace/std/dictmultiobject.py pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Log: Update bytecode reporting. Should now work when compiled as well Modified: pypy/dist/pypy/bin/py.py ============================================================================== --- pypy/dist/pypy/bin/py.py (original) +++ pypy/dist/pypy/bin/py.py Fri Sep 1 17:00:40 2006 @@ -145,13 +145,6 @@ space.finish() main.run_toplevel(space, doit, verbose=Options.verbose) - if space.config.objspace.logbytecodes: - import dis - counts = space.bytecodecounts.items() - counts.sort(key = (lambda x: (-x[1], x[0]))) - print [(dis.opname[opcode], count) for opcode, count in counts] - print [opcode for opcode, count in counts] - return exit_status ##def main_(argv=None): Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Sep 1 17:00:40 2006 @@ -166,7 +166,17 @@ if self.config.objspace.std.withdictmeasurement: from pypy.objspace.std.dictmultiobject import report report() + if self.config.objspace.logbytecodes: + self.reportbytecodecounts() + def reportbytecodecounts(self): + os.write(2, "Starting bytecode report.\n") + fd = os.open('bytecode.txt', os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0644) + for opcode, count in self.bytecodecounts.items(): + os.write(fd, str(opcode) + ", " + str(count) + "\n") + os.close(fd) + os.write(2, "Reporting done.\n") + def __repr__(self): try: return self._this_space_repr_ Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Fri Sep 1 17:00:40 2006 @@ -417,7 +417,7 @@ def STORE_NAME(f, varindex): w_varname = f.getname_w(varindex) w_newvalue = f.valuestack.pop() - f.space.setitem(f.w_locals, w_varname, w_newvalue) + f.space.set_str_keyed_item(f.w_locals, w_varname, w_newvalue) def DELETE_NAME(f, varindex): w_varname = f.getname_w(varindex) @@ -456,7 +456,7 @@ def STORE_GLOBAL(f, nameindex): w_varname = f.getname_w(nameindex) w_newvalue = f.valuestack.pop() - f.space.setitem(f.w_globals, w_varname, w_newvalue) + f.space.set_str_keyed_item(f.w_globals, w_varname, w_newvalue) def DELETE_GLOBAL(f, nameindex): w_varname = f.getname_w(nameindex) @@ -535,25 +535,25 @@ def cmp_exc_match(f, w_1, w_2): return f.space.newbool(f.space.exception_match(w_1, w_2)) - compare_dispatch_table = { - 0: cmp_lt, # "<" - 1: cmp_le, # "<=" - 2: cmp_eq, # "==" - 3: cmp_ne, # "!=" - 4: cmp_gt, # ">" - 5: cmp_ge, # ">=" - 6: cmp_in, - 7: cmp_not_in, - 8: cmp_is, - 9: cmp_is_not, - 10: cmp_exc_match, - } + compare_dispatch_table = [ + cmp_lt, # "<" + cmp_le, # "<=" + cmp_eq, # "==" + cmp_ne, # "!=" + cmp_gt, # ">" + cmp_ge, # ">=" + cmp_in, + cmp_not_in, + cmp_is, + cmp_is_not, + cmp_exc_match, + ] def COMPARE_OP(f, testnum): w_2 = f.valuestack.pop() w_1 = f.valuestack.pop() try: testfn = f.compare_dispatch_table[testnum] - except KeyError: + except IndexError: raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg" w_result = testfn(f, w_1, w_2) f.valuestack.push(w_result) Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Fri Sep 1 17:00:40 2006 @@ -577,13 +577,13 @@ def report(): if not DictInfo._dict_infos: return - os.write(2, "starting to report!\n") + os.write(2, "Starting multidict report.\n") fd = os.open('dictinfo.txt', os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0644) for info in DictInfo._dict_infos: os.write(fd, '------------------\n') _report_one(fd, info) os.close(fd) - os.write(2, "reporting done!\n") + os.write(2, "Reporting done.\n") class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Fri Sep 1 17:00:40 2006 @@ -52,8 +52,8 @@ self.space = FakeSpace() self.space.DictObjectCls = W_DictMultiObject self.space.emptydictimpl = EmptyDictImplementation(self.space) - self.string = self.space.str_w("fish") - self.string2 = self.space.str_w("fish2") + self.string = self.space.wrap("fish") + self.string2 = self.space.wrap("fish2") self.impl = self.get_impl() def get_impl(self): @@ -66,7 +66,7 @@ assert self.impl.get(self.string) == 1000 def test_setitem_str(self): - assert self.impl.setitem_str(self.string, 1000) is self.impl + assert self.impl.setitem_str(self.space.str_w(self.string), 1000) is self.impl assert self.impl.length() == 1 assert self.impl.get(self.string) == 1000 From arigo at codespeak.net Sat Sep 2 12:50:24 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 12:50:24 +0200 (CEST) Subject: [pypy-svn] r31942 - in pypy/dist/pypy/jit: codegen/llgraph codegen/llgraph/test llabstractinterp timeshifter timeshifter/test Message-ID: <20060902105024.90F051006F@code0.codespeak.net> Author: arigo Date: Sat Sep 2 12:50:18 2006 New Revision: 31942 Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (pedronis, arigo) Simplify rcontainer.VirtualStruct: remove the list of equivalent-but-differently-typed boxes. In order to do this we had to change the rgenop interface to no longer care about the exact pointer types in case of GcStruct starting with a nested GcStruct. Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Sat Sep 2 12:50:18 2006 @@ -36,7 +36,7 @@ assert block.exits == [], "block already closed" CONCRETE_TYPE = from_opaque_object(gv_CONCRETE_TYPE).value v = flowmodel.Variable() - v.concretetype = CONCRETE_TYPE + v.concretetype = lltype.erasedType(CONCRETE_TYPE) block.inputargs.append(v) return to_opaque_object(v) @@ -66,6 +66,29 @@ res.append(v) return res +def cast(blockcontainer, gv_TYPE, gv_var): + TYPE = from_opaque_object(gv_TYPE).value + v = from_opaque_object(gv_var) + if TYPE != v.concretetype: + assert v.concretetype == lltype.erasedType(TYPE) + block = from_opaque_object(blockcontainer.obj) + v2 = flowmodel.Variable() + v2.concretetype = TYPE + op = flowmodel.SpaceOperation('cast_pointer', [v], v2) + block.operations.append(op) + v = v2 + return to_opaque_object(v) + +def erasedvar(v, block): + T = lltype.erasedType(v.concretetype) + if T != v.concretetype: + v2 = flowmodel.Variable() + v2.concretetype = T + op = flowmodel.SpaceOperation("cast_pointer", [v], v2) + block.operations.append(op) + return v2 + return v + def genop(blockcontainer, opname, vars_gv, gv_RESULT_TYPE): # 'opname' is a constant string # gv_RESULT_TYPE comes from constTYPE @@ -82,7 +105,7 @@ v.concretetype = RESULT_TYPE op = flowmodel.SpaceOperation(opname, opvars, v) block.operations.append(op) - return to_opaque_object(v) + return to_opaque_object(erasedvar(v, block)) def gencallableconst(name, targetcontainer, gv_FUNCTYPE): # 'name' is just a way to track things @@ -91,12 +114,16 @@ target = from_opaque_object(targetcontainer.obj) FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value fptr = lltype.functionptr(FUNCTYPE, name, - graph=_buildgraph(target)) + graph=_buildgraph(target, FUNCTYPE)) return genconst(fptr) def genconst(llvalue): + T = lltype.typeOf(llvalue) + T1 = lltype.erasedType(T) + if T1 != T: + llvalue = lltype.cast_pointer(T1, llvalue) v = flowmodel.Constant(llvalue) - v.concretetype = lltype.typeOf(llvalue) + v.concretetype = T1 if v.concretetype == lltype.Void: # XXX genconst should not really be used for Void constants assert not isinstance(llvalue, str) and not isinstance(llvalue, lltype.LowLevelType) return to_opaque_object(v) @@ -202,8 +229,9 @@ pseudoreturnblock.operations = () _closelink(link, [returnvar], pseudoreturnblock) -def _patchgraph(graph): +def _patchgraph(graph, RESULT): returntype = None + links = [] for link in graph.iterlinks(): if link.target.operations == (): assert len(link.args) == 1 # for now @@ -211,28 +239,59 @@ returntype = link.target.inputargs[0].concretetype else: assert returntype == link.target.inputargs[0].concretetype - link.target = graph.returnblock + links.append(link) if returntype is None: returntype = lltype.Void - graph.returnblock.inputargs[0].concretetype = returntype + graph.returnblock.inputargs[0].concretetype = RESULT + targetblock = casting_bridge([returntype], [RESULT], graph.returnblock) + for link in links: + link.target = targetblock class PseudoRTyper(object): def __init__(self): from pypy.rpython.typesystem import LowLevelTypeSystem self.type_system = LowLevelTypeSystem.instance -def _buildgraph(block): - graph = flowmodel.FunctionGraph('generated', block) - _patchgraph(graph) +def casting_bridge(FROMS, TOS, target): + if FROMS != TOS: + operations = [] + inputargs = [] + linkargs = [] + for FROM, TO in zip(FROMS, TOS): + v = flowmodel.Variable() + v.concretetype = FROM + inputargs.append(v) + if FROM == TO: + linkargs.append(v) + else: + erasedv = flowmodel.Variable() + erasedv.concretetype = TO + operations.append(flowmodel.SpaceOperation('cast_pointer', + [v], + erasedv)) + linkargs.append(erasedv) + bridgeblock = flowmodel.Block(inputargs) + bridgeblock.operations = operations + bridge = flowmodel.Link(linkargs, target) + bridgeblock.closeblock(bridge) + return bridgeblock + else: + return target + +def _buildgraph(block, FUNCTYPE): + ARGS = [v.concretetype for v in block.inputargs] + startblock =casting_bridge(FUNCTYPE.ARGS, ARGS, block) + graph = flowmodel.FunctionGraph('generated', startblock) + _patchgraph(graph, FUNCTYPE.RESULT) flowmodel.checkgraph(graph) eliminate_empty_blocks(graph) join_blocks(graph) graph.rgenop = True return graph -def buildgraph(blockcontainer): +def buildgraph(blockcontainer, FUNCTYPE): block = from_opaque_object(blockcontainer.obj) - return _buildgraph(block) + return _buildgraph(block, FUNCTYPE) def testgengraph(gengraph, args, viewbefore=False, executor=LLInterpreter): if viewbefore: @@ -240,8 +299,9 @@ llinterp = executor(PseudoRTyper()) return llinterp.eval_graph(gengraph, args) -def runblock(blockcontainer, args, viewbefore=False, executor=LLInterpreter): - graph = buildgraph(blockcontainer) +def runblock(blockcontainer, FUNCTYPE, args, + viewbefore=False, executor=LLInterpreter): + graph = buildgraph(blockcontainer, FUNCTYPE) return testgengraph(graph, args, viewbefore, executor) # ____________________________________________________________ @@ -310,6 +370,7 @@ setannotation(genop, s_ConstOrVar) setannotation(gencallableconst, s_ConstOrVar) setannotation(genconst, s_ConstOrVar) +setannotation(cast, s_ConstOrVar) setannotation(revealconst, lambda s_T, s_gv: annmodel.lltype_to_annotation( s_T.const)) setannotation(isconst, annmodel.SomeBool()) Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Sat Sep 2 12:50:18 2006 @@ -40,18 +40,21 @@ return LLVar(llimpl.genop(self.b, opname, vars_gv, (gv_RESULT_TYPE or gv_Void).v)) - def genop_getfield(self, (gv_name, gv_FIELDTYPE), gv_ptr): - vars_gv = [gv_ptr.v, gv_name.v] + def genop_getfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr): + vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v] return LLVar(llimpl.genop(self.b, 'getfield', vars_gv, gv_FIELDTYPE.v)) - def genop_setfield(self, (gv_name, gv_FIELDTYPE), gv_ptr, gv_value): - vars_gv = [gv_ptr.v, gv_name.v, gv_value.v] + def genop_setfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr, + gv_value): + vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), + gv_name.v, + llimpl.cast(self.b, gv_FIELDTYPE.v, gv_value.v)] return LLVar(llimpl.genop(self.b, 'setfield', vars_gv, gv_Void.v)) - def genop_getsubstruct(self, (gv_name, gv_FIELDTYPE), gv_ptr): - vars_gv = [gv_ptr.v, gv_name.v] + def genop_getsubstruct(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr): + vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v] return LLVar(llimpl.genop(self.b, 'getsubstruct', vars_gv, gv_FIELDTYPE.v)) @@ -113,6 +116,7 @@ if isinstance(FIELDTYPE, lltype.ContainerType): FIELDTYPE = lltype.Ptr(FIELDTYPE) return (LLConst(llimpl.constFieldName(name)), + LLConst(llimpl.constTYPE(lltype.Ptr(T))), LLConst(llimpl.constTYPE(FIELDTYPE))) @staticmethod @@ -156,12 +160,12 @@ # Builds a real flow.model.FunctionGraph. Specific to llgraph. @staticmethod - def buildgraph(block): + def buildgraph(block, FUNCTYPE): if hasattr(block, 'b'): b = block.b else: b = fishllattr(block, 'b') - return llimpl.buildgraph(b) + return llimpl.buildgraph(b, FUNCTYPE) def _freeze_(self): return True # no real point in using a full class in llgraph Modified: pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py Sat Sep 2 12:50:18 2006 @@ -4,6 +4,7 @@ from pypy.rpython.module.support import from_opaque_object from pypy.objspace.flow import model as flowmodel +F1 = FuncType([Signed], Signed) def build_square(): """def square(v0): return v0*v0""" @@ -16,7 +17,7 @@ def test_square(): block = build_square() - res = runblock(block, [17]) + res = runblock(block, F1, [17]) assert res == 289 def test_rtype_newblock(): @@ -37,7 +38,7 @@ def test_rtype_build_square(): blockcontainer = interpret(build_square, []) - res = runblock(blockcontainer, [17]) + res = runblock(blockcontainer, F1, [17]) assert res == 289 def build_if(): @@ -59,16 +60,16 @@ def test_if(): block = build_if() - res = runblock(block, [-1]) + res = runblock(block, F1, [-1]) assert res == 0 - res = runblock(block, [42]) + res = runblock(block, F1, [42]) assert res == 42 def test_rtype_build_if(): blockcontainer = interpret(build_if, []) - res = runblock(blockcontainer, [-1]) + res = runblock(blockcontainer, F1, [-1]) assert res == 0 - res = runblock(blockcontainer, [42]) + res = runblock(blockcontainer, F1, [42]) assert res == 42 def build_loop(): @@ -101,20 +102,20 @@ def test_loop(): block = build_loop() - res = runblock(block, [0]) + res = runblock(block, F1, [0]) assert res == 1 - res = runblock(block, [1]) + res = runblock(block, F1, [1]) assert res == 1 - res = runblock(block, [7]) + res = runblock(block, F1, [7]) assert res == 5040 def test_rtype_build_loop(): blockcontainer = interpret(build_loop, []) - res = runblock(blockcontainer, [0]) + res = runblock(blockcontainer, F1, [0]) assert res == 1 - res = runblock(blockcontainer, [1]) + res = runblock(blockcontainer, F1, [1]) assert res == 1 - res = runblock(blockcontainer, [7]) + res = runblock(blockcontainer, F1, [7]) assert res == 5040 def test_rtype_void_constant_construction(): Modified: pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py Sat Sep 2 12:50:18 2006 @@ -172,16 +172,19 @@ def eval(self, origgraph, arghints): # 'arghints' maps argument index to a given ll value args_a = [] + ARGS = [] for i, v in enumerate(origgraph.getargs()): if i in arghints: a = LLAbstractValue(AConstant(arghints[i])) a.concrete = self.policy.concrete_args else: + ARGS.append(v.concretetype) a = LLAbstractValue(AVariable(v.concretetype)) args_a.append(a) graphstate = self.schedule_graph(args_a, origgraph) graphstate.complete() - return rgenop.buildgraph(graphstate.startblock) + FUNCTYPE = lltype.FuncType(ARGS, origgraph.getreturnvar().concretetype) + return rgenop.buildgraph(graphstate.startblock, FUNCTYPE) def schedule_graph(self, args_a, origgraph): inputstate = LLBlockState(None, args_a, origgraph.startblock) Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Sat Sep 2 12:50:18 2006 @@ -34,40 +34,37 @@ self.PTRTYPE = lltype.Ptr(TYPE) self.alloctoken = RGenOp.allocToken(self.TYPE) self.ptrkind = RGenOp.kindToken(self.PTRTYPE) + innermostdesc = self fielddescs = [] + fielddesc_by_name = {} for name in self.TYPE._names: FIELDTYPE = getattr(self.TYPE, name) if isinstance(FIELDTYPE, lltype.ContainerType): substructdesc = StructTypeDesc(RGenOp, FIELDTYPE) assert name == self.TYPE._names[0], ( "unsupported: inlined substructures not as first field") + fielddescs.extend(substructdesc.fielddescs) self.firstsubstructdesc = substructdesc - for subfielddesc in substructdesc.fielddescs: - dottedname = '%s.%s' % (name, subfielddesc.fieldname) - index = len(fielddescs) - fielddescs.append(StructFieldDesc(RGenOp, self.PTRTYPE, - dottedname, index)) + innermostdesc = substructdesc.innermostdesc else: index = len(fielddescs) - fielddescs.append(StructFieldDesc(RGenOp, self.PTRTYPE, - name, index)) + desc = StructFieldDesc(RGenOp, self.PTRTYPE, name, index) + fielddescs.append(desc) + fielddesc_by_name[name] = desc self.fielddescs = fielddescs + self.fielddesc_by_name = fielddesc_by_name + self.innermostdesc = innermostdesc def getfielddesc(self, name): - index = operator.indexOf(self.TYPE._names, name) - return self.fielddescs[index] + return self.fielddesc_by_name[name] def ll_factory(self): vstruct = VirtualStruct(self) - vstruct.substruct_boxes = [] - typedesc = self - while typedesc is not None: - box = rvalue.PtrRedBox(typedesc.ptrkind) - box.content = vstruct - vstruct.substruct_boxes.append(box) - typedesc = typedesc.firstsubstructdesc - return vstruct.substruct_boxes[0] + box = rvalue.PtrRedBox(self.innermostdesc.ptrkind) + box.content = vstruct + vstruct.ownbox = box + return box def _freeze_(self): return True @@ -84,6 +81,7 @@ if isinstance(RESTYPE, lltype.ContainerType): RESTYPE = lltype.Ptr(RESTYPE) self.RESTYPE = RESTYPE + self.ptrkind = RGenOp.kindToken(PTRTYPE) self.kind = RGenOp.kindToken(RESTYPE) self.redboxcls = rvalue.ll_redboxcls(RESTYPE) self.immutable = PTRTYPE.TO._hints.get('immutable', False) @@ -95,56 +93,36 @@ def __init__(self, RGenOp, PTRTYPE, name): FieldDesc.__init__(self, RGenOp, PTRTYPE, getattr(PTRTYPE.TO, name)) - self.structdepth = 0 T = self.PTRTYPE.TO self.fieldname = name self.fieldtoken = RGenOp.fieldToken(T, name) - while (T._names and - isinstance(getattr(T, T._names[0]), lltype.ContainerType)): - self.structdepth += 1 - T = getattr(T, T._names[0]) -class ArrayFieldDesc(FieldDesc): - def __init__(self, RGenOp, PTRTYPE): - assert isinstance(PTRTYPE.TO, lltype.Array) - FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF) - self.arraytoken = RGenOp.arrayToken(PTRTYPE.TO) + def compact_repr(self): # goes in ll helper names + return "Fld_%s_in_%s" % (self.fieldname, self.PTRTYPE._short_name()) -class StructFieldDesc(object): - __metaclass__ = cachedtype + def generate_get(self, builder, genvar): + gv_item = builder.genop_getfield(self.fieldtoken, genvar) + return self.redboxcls(self.kind, gv_item) - def __init__(self, RGenOp, PTRTYPE, fieldname, index): - assert isinstance(PTRTYPE.TO, lltype.Struct) - RES1 = PTRTYPE.TO - accessors = [] - for component in fieldname.split('.'): - LASTSTRUCT = RES1 - accessors.append((RES1, component)) - RES1 = getattr(RES1, component) - assert not isinstance(RES1, lltype.ContainerType) - self.PTRTYPE = PTRTYPE - self.RESTYPE = RES1 - self.kind = RGenOp.kindToken(RES1) - self.fieldname = fieldname - self.fieldtokens = [RGenOp.fieldToken(T, component) - for T, component in accessors] - self.fieldindex = index - self.gv_default = RGenOp.constPrebuiltGlobal(RES1._defl()) - self.redboxcls = rvalue.ll_redboxcls(RES1) - self.immutable = LASTSTRUCT._hints.get('immutable', False) + def generate_set(self, builder, genvar, box): + builder.genop_setfield(self.fieldtoken, genvar, box.getgenvar(builder)) - def _freeze_(self): - return True + def generate_getsubstruct(self, builder, genvar): + gv_sub = builder.genop_getsubstruct(self.fieldtoken, genvar) + return self.redboxcls(self.kind, gv_sub) - def compact_repr(self): # goes in ll helper names - return "Fld_%s_in_%s" % (self.fieldname.replace('.','_'), - self.PTRTYPE._short_name()) +class StructFieldDesc(NamedFieldDesc): - def generate_set(self, builder, genvar, box): - gv_sub = genvar - for i in range(len(self.fieldtokens)-1): - gv_sub = builder.genop_getsubstruct(self.fieldtokens[i], gv_sub) - builder.genop_setfield(self.fieldtokens[-1], gv_sub, box.getgenvar(builder)) + def __init__(self, RGenOp, PTRTYPE, name, index): + NamedFieldDesc.__init__(self, RGenOp, PTRTYPE, name) + self.fieldindex = index + self.gv_default = RGenOp.constPrebuiltGlobal(self.RESTYPE._defl()) + +class ArrayFieldDesc(FieldDesc): + def __init__(self, RGenOp, PTRTYPE): + assert isinstance(PTRTYPE.TO, lltype.Array) + FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF) + self.arraytoken = RGenOp.arrayToken(PTRTYPE.TO) # ____________________________________________________________ @@ -159,14 +137,14 @@ if self in contmemo: ok = vstruct is contmemo[self] if not ok: - outgoingvarboxes.extend(vstruct.substruct_boxes) + outgoingvarboxes.append(vstruct.ownbox) return ok if vstruct in contmemo: assert contmemo[vstruct] is not self - outgoingvarboxes.extend(vstruct.substruct_boxes) + outgoingvarboxes.append(vstruct.ownbox) return False if self.typedesc is not vstruct.typedesc: - outgoingvarboxes.extend(vstruct.substruct_boxes) + outgoingvarboxes.append(vstruct.ownbox) return False contmemo[self] = vstruct contmemo[vstruct] = self @@ -189,7 +167,7 @@ self.content_boxes = [desc.redboxcls(desc.kind, desc.gv_default) for desc in typedesc.fielddescs] - #self.substruct_boxes = ... + #self.ownbox = ... set in ll_factory() def enter_block(self, newblock, incoming, memo): contmemo = memo.containers @@ -203,18 +181,13 @@ boxes = self.content_boxes self.content_boxes = None genvar = builder.genop_malloc_fixedsize(typedesc.alloctoken) - # force all the boxes pointing to this VirtualStruct - for box in self.substruct_boxes: - # XXX using getsubstruct would be nicer - op_args = [genvar] - box.genvar = builder.genop('cast_pointer', op_args, box.kind) - box.content = None - self.substruct_boxes = None + # force the box pointing to this VirtualStruct + self.ownbox.genvar = genvar + self.ownbox.content = None fielddescs = typedesc.fielddescs for i in range(len(fielddescs)): fielddesc = fielddescs[i] box = boxes[i] - # xxx a bit inefficient fielddesc.generate_set(builder, genvar, box) def freeze(self, memo): @@ -235,8 +208,7 @@ result = contmemo[self] = VirtualStruct(self.typedesc) result.content_boxes = [box.copy(memo) for box in self.content_boxes] - result.substruct_boxes = [box.copy(memo) - for box in self.substruct_boxes] + result.ownbox = self.ownbox.copy(memo) return result def replace(self, memo): @@ -245,8 +217,7 @@ contmemo[self] = None for i in range(len(self.content_boxes)): self.content_boxes[i] = self.content_boxes[i].replace(memo) - for i in range(len(self.substruct_boxes)): - self.substruct_boxes[i] = self.substruct_boxes[i].replace(memo) + self.ownbox = self.ownbox.replace(memo) def op_getfield(self, jitstate, fielddesc): return self.content_boxes[fielddesc.fieldindex] @@ -255,5 +226,4 @@ self.content_boxes[fielddesc.fieldindex] = valuebox def op_getsubstruct(self, jitstate, fielddesc): - #assert fielddesc.fieldindex == 0 - return self.substruct_boxes[-fielddesc.structdepth] + return self.ownbox Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Sat Sep 2 12:50:18 2006 @@ -90,19 +90,16 @@ return rvalue.ll_fromvalue(jitstate, res) assert isinstance(argbox, rvalue.PtrRedBox) if argbox.content is None: - genvar = jitstate.curbuilder.genop_getfield(fielddesc.fieldtokens[-1], - argbox.getgenvar(jitstate.curbuilder)) - return fielddesc.redboxcls(fielddesc.kind, genvar) + gv_ptr = argbox.getgenvar(jitstate.curbuilder) + return fielddesc.generate_get(jitstate.curbuilder, gv_ptr) else: return argbox.content.op_getfield(jitstate, fielddesc) def ll_generate_setfield(jitstate, fielddesc, destbox, valuebox): assert isinstance(destbox, rvalue.PtrRedBox) if destbox.content is None: - builder = jitstate.curbuilder - builder.genop_setfield(fielddesc.fieldtokens[-1], - destbox.getgenvar(builder), - valuebox.getgenvar(builder)) + gv_ptr = destbox.getgenvar(jitstate.curbuilder) + fielddesc.generate_set(jitstate.curbuilder, gv_ptr, valuebox) else: destbox.content.op_setfield(jitstate, fielddesc, valuebox) @@ -113,8 +110,8 @@ return rvalue.ll_fromvalue(jitstate, res) assert isinstance(argbox, rvalue.PtrRedBox) if argbox.content is None: - genvar = jitstate.curbuilder.genop_getsubstruct(fielddesc.fieldtoken, argbox.getgenvar(jitstate.curbuilder)) - return fielddesc.redboxcls(fielddesc.kind, genvar) + gv_ptr = argbox.getgenvar(jitstate.curbuilder) + return fielddesc.generate_getsubstruct(jitstate.curbuilder, gv_ptr) else: return argbox.content.op_getsubstruct(jitstate, fielddesc) Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sat Sep 2 12:50:18 2006 @@ -178,15 +178,14 @@ annmodel.s_None) def translate_op_getsubstruct(self, hop): - if isinstance(hop.args_r[0], BlueRepr): - return hop.args_r[0].timeshift_getsubstruct(hop) - # non virtual case + ##if isinstance(hop.args_r[0], BlueRepr): + ## return hop.args_r[0].timeshift_getsubstruct(hop) ts = self.timeshifter PTRTYPE = originalconcretetype(hop.args_s[0]) v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE), green_void_repr) fielddesc = rcontainer.NamedFieldDesc(self.RGenOp, PTRTYPE, - c_fieldname.value) # XXX + c_fieldname.value) c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() @@ -194,7 +193,11 @@ [ts.s_JITState, s_fielddesc, ts.s_RedBox], [v_jitstate, c_fielddesc, v_argbox ], ts.s_RedBox) - + + def translate_op_cast_pointer(self, hop): + FROM_TYPE = originalconcretetype(hop.args_s[0]) + v_argbox = hop.inputargs(self.getredrepr(FROM_TYPE)) + return v_argbox def translate_op_malloc(self, hop): r_result = hop.r_result Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Sat Sep 2 12:50:18 2006 @@ -525,7 +525,7 @@ def test_inlined_substructure(self): py.test.skip("blue containers: to be reimplemented") - S = lltype.Struct('S', ('n', lltype.Signed)) + S = lltype.GcStruct('S', ('n', lltype.Signed)) T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) def ll_function(k): t = lltype.malloc(T) @@ -674,7 +674,7 @@ self.check_insns({'int_lt': 1, 'int_mul': 1}) def test_red_subcontainer(self): - S = lltype.Struct('S', ('n', lltype.Signed)) + S = lltype.GcStruct('S', ('n', lltype.Signed)) T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) def ll_function(k): t = lltype.malloc(T) From fijal at codespeak.net Sat Sep 2 12:59:37 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 Sep 2006 12:59:37 +0200 (CEST) Subject: [pypy-svn] r31943 - in pypy/dist/pypy/translator/transformer: . test Message-ID: <20060902105937.936241006F@code0.codespeak.net> Author: fijal Date: Sat Sep 2 12:59:35 2006 New Revision: 31943 Added: pypy/dist/pypy/translator/transformer/ pypy/dist/pypy/translator/transformer/__init__.py (contents, props changed) pypy/dist/pypy/translator/transformer/basictransform.py (contents, props changed) pypy/dist/pypy/translator/transformer/test/ pypy/dist/pypy/translator/transformer/test/__init__.py (contents, props changed) pypy/dist/pypy/translator/transformer/test/test_basictransform.py (contents, props changed) Log: Added really simple graph (after annotation) transformation helpers. This is extend of transform.py in some sense. Added: pypy/dist/pypy/translator/transformer/__init__.py ============================================================================== Added: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/transformer/basictransform.py Sat Sep 2 12:59:35 2006 @@ -0,0 +1,145 @@ + +""" basic transform - some play around graph transformations +""" + +# this is RPython code which handles proper base elements for +# stack tracing + +from pypy.translator import unsimplify, simplify +from pypy.translator.unsimplify import varoftype +from pypy.annotation import model as annmodel +from pypy.objspace.flow import model +from pypy.translator.js.helper import main_exception_helper, ExceptionHelper +from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem import rclass +from pypy.rpython.annlowlevel import MixLevelHelperAnnotator + +class BasicTransformer(object): + """ This is basic transformer which applies after annotation level. + Some more high-level stuff defined here, needed for ie. changing + block operations, reflowing, etc. etc. + """ + def __init__(self, translator): + # some shortcuts + self.translator = translator + self.annotator = translator.annotator + self.bookkeeper = self.annotator.bookkeeper + + def genop(self, name, args): + """ Pass here (example, is_constant) list as args, you'll + get retval + """ + real_args = [] + bk = self.bookkeeper + for arg in args: + if isinstance(arg, (model.Constant, model.Variable)): + real_args.append(arg) + else: + arg_example, is_constant = arg + if is_constant: + real_args.append(model.Constant(arg_example, concretetype=bk.immutablevalue(arg_example))) + else: + real_args.append(model.Variable(bk.annotation_from_example(arg_example))) + retval = model.Variable() + return model.SpaceOperation(name, real_args, retval), retval + + def add_block(self, graph, block): + ann = self.annotator + args_s = [ann.bindings[v] for v in block.inputargs] + try: + del ann.annotated[block] + except KeyError: + pass + ann.addpendingblock(graph, block, args_s) + + def flow_method(self, _class, func_name, args): + ann = self.annotator + bk = self.bookkeeper + example_ann = bk.annotation_from_example + s_args = [example_ann(arg) for arg in args] + graph = ann.annotate_helper_method(_class, func_name, s_args) + return graph + + def transform_all(self): + bk = self.translator.annotator.bookkeeper + for graph in self.translator.graphs: + self.transform_graph(graph) + self.translator.annotator.complete() + +##class Transformer(object): +## def __init__(self, translator): +## self.translator = translator +## self.register_helpers() +## +## def register_helpers(self): +## """ Flow necessary additional functions +## """ +## ann = self.translator.annotator +## bk = ann.bookkeeper +## +## for func_name, func_args in [("enter", [3]), ("leave", []), +## ("traceback", [])]: +## self.flow_exc_handler_method(func_name, func_args) +## self.excdef = bk.getuniqueclassdef(ExceptionHelper) +## +## def flow_exc_handler_method(self, func_name, args): +## ann = self.translator.annotator +## example_ann = ann.bookkeeper.annotation_from_example +## s_args = [example_ann(arg) for arg in args] +## graph = ann.annotate_helper_method(ExceptionHelper, func_name, s_args) +## graph.exception_handler_explicit = True +## +## def transform_graph(self, graph): +## # XXX: we do not want to flow low level helpers as well +## # but for now I do not see how to see them +## ann = self.translator.annotator +## if graph.name.startswith("ll_"): +## return +## if getattr(graph, 'exception_handler_explicit', False): +## return +## # for each graph block enter operation which calls apropriate functions +## old_start_block = graph.startblock +## new_start_block = model.Block(old_start_block.inputargs[:]) +## newoutputargs = [unsimplify.copyvar(ann, v) +## for v in old_start_block.inputargs] +## +## mapping = {} +## for old, new in zip(old_start_block.inputargs, newoutputargs): +## mapping[old] = new +## old_start_block.renamevariables(mapping) +## new_start_block.closeblock(model.Link( \ +## new_start_block.inputargs, old_start_block)) +## +## old_start_block.isstartblock = False +## new_start_block.isstartblock = True +## +## self.add_start_operations(graph, new_start_block) +## +## args_s = [ann.bindings[v] for v in new_start_block.inputargs] +## ann.addpendingblock(graph, new_start_block, args_s) +## graph.startblock = new_start_block +## +## #simplify.simplify_graph(graph, [simplify.eliminate_empty_blocks, +## # simplify.join_blocks, +## # simplify.transform_dead_op_vars]) +## +## #def add_same_as_operations(self, new_block, old_block, old_args, new_args): +## # mapping = {} +## # for old, new in zip(old_args, new_args): +## # new_block.operations.append(model.SpaceOperation("same_as", [old], new)) +## # mapping[old] = new +## # old_block.renamevariables(mapping) +## +## def add_start_operations(self, graph, block): +## assert len(block.operations) == 0 +## retval = model.Variable() +## bk = self.translator.annotator.bookkeeper +## arg = model.Constant(bk.immutablevalue("enter")) +## block.operations.append(model.SpaceOperation("getattr", [self.main_instance, arg], retval)) +## +## def transform_all(self): +## bk = self.translator.annotator.bookkeeper +## self.main_instance = model.Constant(bk.immutablevalue(main_exception_helper)) +## for graph in self.translator.graphs: +## self.transform_graph(graph) +## self.translator.annotator.complete() Added: pypy/dist/pypy/translator/transformer/test/__init__.py ============================================================================== Added: pypy/dist/pypy/translator/transformer/test/test_basictransform.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/transformer/test/test_basictransform.py Sat Sep 2 12:59:35 2006 @@ -0,0 +1,95 @@ + +""" test basic javascript transformation +""" + +from pypy.translator.translator import TranslationContext, graphof +from pypy.translator.transformer.basictransform import BasicTransformer +from pypy import conftest +from pypy.rpython import llinterp +from pypy.objspace.flow import model +from pypy.translator.unsimplify import copyvar + +def transform_function(transformerclass, fun, annotation=[], specialize=True, + type_system="ootype"): + t = TranslationContext() + annotator = t.buildannotator() + annotator.build_types(fun, annotation) + tran = transformerclass(t) + tran.transform_all() + + if conftest.option.view: + t.view() + + t.buildrtyper(type_system=type_system).specialize() + + if conftest.option.view: + t.view() + + return t + +def interp_fun(t, fun, args=[]): + graph = graphof(t, fun) + interp = llinterp.LLInterpreter(t.rtyper) + res = interp.eval_graph(graph, args) + return res + +class OpTransformer(BasicTransformer): + def transform_graph(self, graph): + block = graph.startblock + op, v = self.genop("add", [(1, True), (2, True)]) + block.operations.append(op) + self.add_block(graph, block) + block.exits[0].args = [v] + +def test_genop(): + def genop_fun(i1, i2): + return 1 + + t = transform_function(OpTransformer, genop_fun, [int, int]) + res = interp_fun(t, genop_fun, [3, 2]) + assert res == 3 + +class BlockTransformer(BasicTransformer): + def transform_graph(self, graph): + block = model.Block(graph.startblock.inputargs[:]) + + old_start_block = graph.startblock + graph.startblock = block + + block.isstartblock = True + old_start_block.isstartblock = False + op, v = self.genop("add", (block.inputargs[0], (1, True))) + block.operations.append(op) + block.closeblock(model.Link([v], old_start_block)) + + self.add_block(graph, block) + + old_start_block.renamevariables({block.inputargs[0]: + copyvar(self.annotator, block.inputargs[0])}) + +def test_change_startblock(): + def some_fun(i): + return i + + t = transform_function(BlockTransformer, some_fun, [int]) + res = interp_fun(t, some_fun, [1]) + assert res == 2 + +##def test_transform(): +## def fun(i): +## a = 3 + i +## b = a - 1 +## return b +## +## def wrapper(i): +## retval = fun(i) +## return retval, main_exception_helper.traceback() +## +## t = transform_function(wrapper, [int]) +## res = interp_fun(t, wrapper, [3]) +## retval = res._items['item0'] +## traceback = res._items['item1'] +## real_traceback = [i._str for i in traceback._list] +## assert retval == fun(3) +## assert len(real_traceback) == 3 +## # XXX: to be fixed as basic_transform continues to grow From fijal at codespeak.net Sat Sep 2 13:42:36 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 Sep 2006 13:42:36 +0200 (CEST) Subject: [pypy-svn] r31944 - in pypy/dist/pypy/translator/transformer: . test Message-ID: <20060902114236.5AF411006F@code0.codespeak.net> Author: fijal Date: Sat Sep 2 13:42:32 2006 New Revision: 31944 Modified: pypy/dist/pypy/translator/transformer/ (props changed) pypy/dist/pypy/translator/transformer/basictransform.py pypy/dist/pypy/translator/transformer/test/ (props changed) pypy/dist/pypy/translator/transformer/test/test_basictransform.py Log: Added additional test and helpers. Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Sat Sep 2 13:42:32 2006 @@ -2,9 +2,6 @@ """ basic transform - some play around graph transformations """ -# this is RPython code which handles proper base elements for -# stack tracing - from pypy.translator import unsimplify, simplify from pypy.translator.unsimplify import varoftype from pypy.annotation import model as annmodel @@ -66,80 +63,6 @@ self.transform_graph(graph) self.translator.annotator.complete() -##class Transformer(object): -## def __init__(self, translator): -## self.translator = translator -## self.register_helpers() -## -## def register_helpers(self): -## """ Flow necessary additional functions -## """ -## ann = self.translator.annotator -## bk = ann.bookkeeper -## -## for func_name, func_args in [("enter", [3]), ("leave", []), -## ("traceback", [])]: -## self.flow_exc_handler_method(func_name, func_args) -## self.excdef = bk.getuniqueclassdef(ExceptionHelper) -## -## def flow_exc_handler_method(self, func_name, args): -## ann = self.translator.annotator -## example_ann = ann.bookkeeper.annotation_from_example -## s_args = [example_ann(arg) for arg in args] -## graph = ann.annotate_helper_method(ExceptionHelper, func_name, s_args) -## graph.exception_handler_explicit = True -## -## def transform_graph(self, graph): -## # XXX: we do not want to flow low level helpers as well -## # but for now I do not see how to see them -## ann = self.translator.annotator -## if graph.name.startswith("ll_"): -## return -## if getattr(graph, 'exception_handler_explicit', False): -## return -## # for each graph block enter operation which calls apropriate functions -## old_start_block = graph.startblock -## new_start_block = model.Block(old_start_block.inputargs[:]) -## newoutputargs = [unsimplify.copyvar(ann, v) -## for v in old_start_block.inputargs] -## -## mapping = {} -## for old, new in zip(old_start_block.inputargs, newoutputargs): -## mapping[old] = new -## old_start_block.renamevariables(mapping) -## new_start_block.closeblock(model.Link( \ -## new_start_block.inputargs, old_start_block)) -## -## old_start_block.isstartblock = False -## new_start_block.isstartblock = True -## -## self.add_start_operations(graph, new_start_block) -## -## args_s = [ann.bindings[v] for v in new_start_block.inputargs] -## ann.addpendingblock(graph, new_start_block, args_s) -## graph.startblock = new_start_block -## -## #simplify.simplify_graph(graph, [simplify.eliminate_empty_blocks, -## # simplify.join_blocks, -## # simplify.transform_dead_op_vars]) -## -## #def add_same_as_operations(self, new_block, old_block, old_args, new_args): -## # mapping = {} -## # for old, new in zip(old_args, new_args): -## # new_block.operations.append(model.SpaceOperation("same_as", [old], new)) -## # mapping[old] = new -## # old_block.renamevariables(mapping) -## -## def add_start_operations(self, graph, block): -## assert len(block.operations) == 0 -## retval = model.Variable() -## bk = self.translator.annotator.bookkeeper -## arg = model.Constant(bk.immutablevalue("enter")) -## block.operations.append(model.SpaceOperation("getattr", [self.main_instance, arg], retval)) -## -## def transform_all(self): -## bk = self.translator.annotator.bookkeeper -## self.main_instance = model.Constant(bk.immutablevalue(main_exception_helper)) -## for graph in self.translator.graphs: -## self.transform_graph(graph) -## self.translator.annotator.complete() + def get_const(self, arg): + bk = self.bookkeeper + return model.Constant(arg, bk.immutablevalue(arg)) Modified: pypy/dist/pypy/translator/transformer/test/test_basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_basictransform.py Sat Sep 2 13:42:32 2006 @@ -75,6 +75,45 @@ res = interp_fun(t, some_fun, [1]) assert res == 2 +class ClassHelper(object): + def __init__(self): + self.i = 0 + + def method(self): + self.i = 8 + +helper_instance = ClassHelper() + +class HelperTransformer(BasicTransformer): + def __init__(self, translator): + BasicTransformer.__init__(self, translator) + self.flow_method(ClassHelper, 'method', []) + bk = self.bookkeeper + self.instance_const = model.Constant(helper_instance, \ + concretetype=bk.immutablevalue(helper_instance)) + + def transform_graph(self, graph): + if graph.name != 'helper_call_fun': + return + block = graph.startblock + c = self.get_const("method") + op, v = self.genop("getattr", [self.instance_const, c]) + block.operations.insert(0, op) + op, v2 = self.genop("simple_call", [v]) + block.operations.insert(1, op) + + self.add_block(graph, block) + +def test_method_helper(): + # XXX: retval of method is still wrong + def helper_call_fun(): + return helper_instance.i + + t = transform_function(HelperTransformer, helper_call_fun) + res = interp_fun(t, helper_call_fun) + assert res == 8 + + ##def test_transform(): ## def fun(i): ## a = 3 + i From arigo at codespeak.net Sat Sep 2 15:24:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 15:24:48 +0200 (CEST) Subject: [pypy-svn] r31945 - in pypy/dist/pypy/annotation: . test Message-ID: <20060902132448.504961006F@code0.codespeak.net> Author: arigo Date: Sat Sep 2 15:24:46 2006 New Revision: 31945 Modified: pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/annotation/test/test_annrpython.py Log: (arigo, pedronis) - coding (pedronis, arigo) - test A way to enforce general enough signatures during the annotation of functions. To be used mostly for low-level helpers, to get rid of problems mostly caused by non-neg integers that become possibly-negative later. Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Sat Sep 2 15:24:46 2006 @@ -250,6 +250,9 @@ tag = getattr(self.pyobj, '_annspecialcase_', None) policy = self.bookkeeper.annotator.policy self.specializer = policy.get_specializer(tag) + enforceargs = getattr(self.pyobj, '_annenforceargs_', None) + if enforceargs: + enforceargs(self, inputcells) # can modify inputcells in-place return self.specializer(self, inputcells) def pycall(self, schedule, args, s_previous_result): Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Sat Sep 2 15:24:46 2006 @@ -90,3 +90,30 @@ def override__ignore(pol, *args): bk = getbookkeeper() return bk.immutablevalue(None) + +# ____________________________________________________________ + +class Sig(object): + + def __init__(self, *argtypes): + self.argtypes = argtypes + + def __call__(self, funcdesc, inputcells): + args_s = [] + for argtype in self.argtypes: + if isinstance(argtype, annmodel.SomeObject): + args_s.append(argtype) + else: + args_s.append(funcdesc.bookkeeper.valueoftype(argtype)) + if len(inputcells) != len(args_s): + raise Exception("%r: expected %d args, got %d" % (funcdesc, + len(args_s), + len(inputcells))) + for i, (s_arg, s_input) in enumerate(zip(args_s, inputcells)): + if not s_arg.contains(s_input): + raise Exception("%r argument %d:\n" + "expected %s,\n" + " got %s" % (funcdesc, i+1, + s_arg, + s_input)) + inputcells[:] = args_s Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Sat Sep 2 15:24:46 2006 @@ -2308,6 +2308,18 @@ assert isinstance(s, annmodel.SomeInteger) assert s.nonneg + def test_sig(self): + def fun(x, y): + return x+y + s_nonneg = annmodel.SomeInteger(nonneg=True) + fun._annenforceargs_ = policy.Sig(int, s_nonneg) + + a = self.RPythonAnnotator() + s = a.build_types(fun, [s_nonneg, s_nonneg]) + assert isinstance(s, annmodel.SomeInteger) + assert not s.nonneg + py.test.raises(Exception, a.build_types, fun, [int, int]) + def g(n): return [0,1,2,n] From fijal at codespeak.net Sat Sep 2 17:01:26 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 Sep 2006 17:01:26 +0200 (CEST) Subject: [pypy-svn] r31948 - pypy/dist/pypy/rpython/test Message-ID: <20060902150126.F27F51006F@code0.codespeak.net> Author: fijal Date: Sat Sep 2 17:01:19 2006 New Revision: 31948 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py Log: Added failing test for exception raise/cacth. Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Sat Sep 2 17:01:19 2006 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.llinterp import LLInterpreter, LLException, log from pypy.rpython.rmodel import inputconst -from pypy.translator.translator import TranslationContext +from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.rint import signed_repr from pypy.rpython.lltypesystem import rstr from pypy.annotation import model as annmodel @@ -476,3 +476,23 @@ return i except ValueError: raise TypeError + +def test_llinterp_fail(): + py.test.skip("Fails") + def aa(i): + if i: + raise TypeError() + + def bb(i): + try: + aa(i) + except TypeError: + pass + + t = TranslationContext() + annotator = t.buildannotator() + annotator.build_types(bb, [int]) + t.buildrtyper(type_system="ootype").specialize() + graph = graphof(t, aa) + interp = LLInterpreter(t.rtyper) + res = interp.eval_graph(graph, [1]) From fijal at codespeak.net Sat Sep 2 17:05:03 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 2 Sep 2006 17:05:03 +0200 (CEST) Subject: [pypy-svn] r31949 - pypy/dist/pypy/jit Message-ID: <20060902150503.1213A1006F@code0.codespeak.net> Author: fijal Date: Sat Sep 2 17:05:01 2006 New Revision: 31949 Modified: pypy/dist/pypy/jit/conftest.py Log: Typo Modified: pypy/dist/pypy/jit/conftest.py ============================================================================== --- pypy/dist/pypy/jit/conftest.py (original) +++ pypy/dist/pypy/jit/conftest.py Sat Sep 2 17:05:01 2006 @@ -1,6 +1,6 @@ import py, time, os -# Usage: py.test --brenchmark +# Usage: py.test --benchmark # # This module provides an RPython class to use as follows: # From arigo at codespeak.net Sat Sep 2 17:41:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 17:41:49 +0200 (CEST) Subject: [pypy-svn] r31950 - in pypy/dist/pypy: annotation annotation/test rpython rpython/lltypesystem rpython/test Message-ID: <20060902154149.787401006F@code0.codespeak.net> Author: arigo Date: Sat Sep 2 17:41:45 2006 New Revision: 31950 Modified: pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: {arigo, pedronis} * Allow lambdas in Sig. * Started the concept of ADTInterface, which describes the signature of the ADT methods. This is used to ensure that the ADT methods are always annotated with the most general annotation. * In the middle of killing ListBuilder... Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Sat Sep 2 17:41:45 2006 @@ -6,6 +6,7 @@ # or we create a cycle. from pypy.annotation import model as annmodel from pypy.annotation.bookkeeper import getbookkeeper +import types class BasicAnnotatorPolicy(object): @@ -99,10 +100,23 @@ self.argtypes = argtypes def __call__(self, funcdesc, inputcells): + from pypy.rpython.lltypesystem import lltype args_s = [] - for argtype in self.argtypes: + for i, argtype in enumerate(self.argtypes): + if isinstance(argtype, (types.FunctionType, types.MethodType)): + argtype = argtype(*inputcells) if isinstance(argtype, annmodel.SomeObject): args_s.append(argtype) + elif isinstance(argtype, lltype.LowLevelType): + if argtype is lltype.Void: + # XXX the mapping between Void and annotation + # is not quite well defined + s_input = inputcells[i] + assert isinstance(s_input, annmodel.SomePBC) + assert s_input.is_constant() + args_s.append(s_input) + else: + args_s.append(annmodel.lltype_to_annotation(argtype)) else: args_s.append(funcdesc.bookkeeper.valueoftype(argtype)) if len(inputcells) != len(args_s): Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Sat Sep 2 17:41:45 2006 @@ -2320,6 +2320,20 @@ assert not s.nonneg py.test.raises(Exception, a.build_types, fun, [int, int]) + def test_sig_lambda(self): + def fun(x, y): + return y + s_nonneg = annmodel.SomeInteger(nonneg=True) + fun._annenforceargs_ = policy.Sig(lambda s1,s2: s1, lambda s1,s2: s1) + # means: the 2nd argument's annotation becomes the 1st argument's + # input annotation + + a = self.RPythonAnnotator() + s = a.build_types(fun, [int, s_nonneg]) + assert isinstance(s, annmodel.SomeInteger) + assert not s.nonneg + py.test.raises(Exception, a.build_types, fun, [s_nonneg, int]) + def g(n): return [0,1,2,n] Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Sat Sep 2 17:41:45 2006 @@ -5,7 +5,7 @@ import types from pypy.tool.sourcetools import valid_identifier from pypy.annotation import model as annmodel -from pypy.annotation.policy import AnnotatorPolicy +from pypy.annotation.policy import AnnotatorPolicy, Sig from pypy.rpython.lltypesystem import lltype from pypy.rpython import extfunctable, extregistry from pypy.objspace.flow.model import Constant @@ -330,5 +330,73 @@ def specialize_call(self, hop): return hop.args_r[1].get_unique_llfn() +# ____________________________________________________________ - +def placeholder_sigarg(s): + if s == "self": + def expand(s_self, *args_s): + assert isinstance(s_self, annmodel.SomePtr) + return s_self + elif s == "SELF": + raise NotImplementedError + else: + assert s.islower() + def expand(s_self, *args_s): + assert isinstance(s_self, annmodel.SomePtr) + return getattr(s_self.ll_ptrtype.TO, s.upper()) + return expand + +def typemeth_placeholder_sigarg(s): + if s == "SELF": + def expand(s_TYPE, *args_s): + assert isinstance(s_TYPE, annmodel.SomePBC) + assert s_TYPE.is_constant() + return s_TYPE + elif s == "self": + def expand(s_TYPE, *args_s): + assert isinstance(s_TYPE, annmodel.SomePBC) + assert s_TYPE.is_constant() + return lltype.Ptr(s_TYPE.const) + else: + assert s.islower() + def expand(s_TYPE, *args_s): + assert isinstance(s_TYPE, annmodel.SomePBC) + assert s_TYPE.is_constant() + return getattr(s_TYPE.const, s.upper()) + return expand + + +class ADTInterface(object): + + def __init__(self, base, sigtemplates): + self.sigtemplates = sigtemplates + self.base = base + sigs = {} + if base is not None: + sigs.update(base.sigs) + for name, template in sigtemplates.items(): + args, result = template + if args[0] == "self": + make_expand = placeholder_sigarg + elif args[0] == "SELF": + make_expand = typemeth_placeholder_sigarg + else: + assert False, ("ADTInterface signature should start with" + " 'SELF' or 'self'") + sigargs = [] + for arg in args: + if isinstance(arg, str): + arg = make_expand(arg) + sigargs.append(arg) + sigs[name] = Sig(*sigargs) + self.sigs = sigs + + def __call__(self, adtmeths): + for name, sig in self.sigs.items(): + meth = adtmeths[name] + prevsig = getattr(meth, '_annenforceargs_', None) + if prevsig: + assert prevsig is sig + else: + meth._annenforceargs_ = sig + return adtmeths Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sat Sep 2 17:41:45 2006 @@ -693,6 +693,14 @@ raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT)) +def erasedType(T): + while isinstance(T, Ptr) and isinstance(T.TO, Struct): + first, FIRSTTYPE = T.TO._first_struct() + if first is None: + break + T = Ptr(FIRSTTYPE) + return T + class InvalidCast(TypeError): pass Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Sat Sep 2 17:41:45 2006 @@ -5,7 +5,7 @@ from pypy.rpython.rmodel import externalvsinternal from pypy.rpython.rlist import AbstractBaseListRepr, AbstractListRepr, \ AbstractFixedSizeListRepr, AbstractListIteratorRepr, rtype_newlist, \ - rtype_alloc_and_set, ll_setitem_nonneg + rtype_alloc_and_set, ll_setitem_nonneg, ADTIList, ADTIFixedList from pypy.rpython.rlist import dum_nocheck, dum_checkidx from pypy.rpython.lltypesystem.rslice import SliceRepr from pypy.rpython.lltypesystem.rslice import startstop_slice_repr, startonly_slice_repr @@ -49,10 +49,10 @@ self.listitem = listitem self.list_cache = {} # setup() needs to be called to finish this initialization - self.list_builder = ListBuilder(self) +## self.list_builder = ListBuilder(self) - def _setup_repr_final(self): - self.list_builder.setup() +## def _setup_repr_final(self): +## self.list_builder.setup() def null_const(self): return nullptr(self.LIST) @@ -81,85 +81,85 @@ temp), rstr.list_str_close_bracket)) -class ListBuilder(object): - """Interface to allow lazy list building by the JIT.""" +##class ListBuilder(object): +## """Interface to allow lazy list building by the JIT.""" - def __init__(self, list_repr): - # This should not keep a reference to the RTyper, even indirectly via - # the list_repr. So tmp_list_repr is replaced by None in setup(). - self.tmp_list_repr = list_repr - - def setup(self): - # Precompute the c_newitem and c_setitem_nonneg function pointers, - # needed below. - list_repr = self.tmp_list_repr - if list_repr is None: - return # already set up - self.tmp_list_repr = None - if list_repr.rtyper is None: - return # only for test_rlist, which doesn't need this anyway +## def __init__(self, list_repr): +## # This should not keep a reference to the RTyper, even indirectly via +## # the list_repr. So tmp_list_repr is replaced by None in setup(). +## self.tmp_list_repr = list_repr + +## def setup(self): +## # Precompute the c_newitem and c_setitem_nonneg function pointers, +## # needed below. +## list_repr = self.tmp_list_repr +## if list_repr is None: +## return # already set up +## self.tmp_list_repr = None +## if list_repr.rtyper is None: +## return # only for test_rlist, which doesn't need this anyway - LIST = list_repr.LIST - LISTPTR = list_repr.lowleveltype - ITEM = list_repr.item_repr.lowleveltype - self.LIST = LIST - self.LISTPTR = LISTPTR - - argtypes = [Signed] - newlist_ptr = list_repr.rtyper.annotate_helper_fn(LIST.ll_newlist, - argtypes) - - bk = list_repr.rtyper.annotator.bookkeeper - argtypes = [bk.immutablevalue(dum_nocheck), LISTPTR, Signed, ITEM] - setitem_nonneg_ptr = list_repr.rtyper.annotate_helper_fn( - ll_setitem_nonneg, argtypes) - #self.c_dum_nocheck = inputconst(Void, dum_nocheck) - #self.c_LIST = inputconst(Void, self.LIST) - - def build_newlist(llops, length): - c_newlist = llops.genconst(newlist_ptr) - c_len = llops.genconst(length) - c_LIST = llops.genvoidconst(LIST) - return llops.genop('direct_call', - [c_newlist, c_LIST, c_len], - llops.constTYPE(LISTPTR)) - - def build_setitem(llops, v_list, index, v_item): - c_setitem_nonneg = llops.genconst(setitem_nonneg_ptr) - c_i = llops.genconst(index) - llops.genop('direct_call', [c_setitem_nonneg, - llops.genvoidconst(dum_nocheck), - v_list, c_i, v_item]) - - self.build_newlist = build_newlist - self.build_setitem = build_setitem - - def build(self, llops, items_v): - """Make the operations that would build a list containing the - provided items.""" - v_list = self.build_newlist(llops, len(items_v)) - for i, v in enumerate(items_v): - self.build_setitem(llops, v_list, i, v) - return v_list - - def getlistptr(self): - list_repr = self.tmp_list_repr - if list_repr is not None: - list_repr.setup() - return list_repr.lowleveltype - else: - return self.LISTPTR - - def __eq__(self, other): - if not isinstance(other, ListBuilder): - return False - return self.getlistptr() == other.getlistptr() +## LIST = list_repr.LIST +## LISTPTR = list_repr.lowleveltype +## ITEM = list_repr.item_repr.lowleveltype +## self.LIST = LIST +## self.LISTPTR = LISTPTR + +## argtypes = [Signed] +## newlist_ptr = list_repr.rtyper.annotate_helper_fn(LIST.ll_newlist, +## argtypes) + +## bk = list_repr.rtyper.annotator.bookkeeper +## argtypes = [bk.immutablevalue(dum_nocheck), LISTPTR, Signed, ITEM] +## setitem_nonneg_ptr = list_repr.rtyper.annotate_helper_fn( +## ll_setitem_nonneg, argtypes) +## #self.c_dum_nocheck = inputconst(Void, dum_nocheck) +## #self.c_LIST = inputconst(Void, self.LIST) + +## def build_newlist(llops, length): +## c_newlist = llops.genconst(newlist_ptr) +## c_len = llops.genconst(length) +## c_LIST = llops.genvoidconst(LIST) +## return llops.genop('direct_call', +## [c_newlist, c_LIST, c_len], +## llops.constTYPE(LISTPTR)) + +## def build_setitem(llops, v_list, index, v_item): +## c_setitem_nonneg = llops.genconst(setitem_nonneg_ptr) +## c_i = llops.genconst(index) +## llops.genop('direct_call', [c_setitem_nonneg, +## llops.genvoidconst(dum_nocheck), +## v_list, c_i, v_item]) + +## self.build_newlist = build_newlist +## self.build_setitem = build_setitem + +## def build(self, llops, items_v): +## """Make the operations that would build a list containing the +## provided items.""" +## v_list = self.build_newlist(llops, len(items_v)) +## for i, v in enumerate(items_v): +## self.build_setitem(llops, v_list, i, v) +## return v_list + +## def getlistptr(self): +## list_repr = self.tmp_list_repr +## if list_repr is not None: +## list_repr.setup() +## return list_repr.lowleveltype +## else: +## return self.LISTPTR + +## def __eq__(self, other): +## if not isinstance(other, ListBuilder): +## return False +## return self.getlistptr() == other.getlistptr() - def __ne__(self, other): - return not (self == other) +## def __ne__(self, other): +## return not (self == other) - def __hash__(self): - return 1 # bad but not used alone +## def __hash__(self): +## return 1 # bad but not used alone class __extend__(pairtype(BaseListRepr, BaseListRepr)): @@ -183,18 +183,18 @@ # XXX we might think of turning length stuff into Unsigned self.LIST.become(GcStruct("list", ("length", Signed), ("items", Ptr(ITEMARRAY)), - adtmeths = { + adtmeths = ADTIList({ "ll_newlist": ll_newlist, "ll_length": ll_length, "ll_items": ll_items, - "list_builder": self.list_builder, + ##"list_builder": self.list_builder, "ITEM": ITEM, "ll_getitem_fast": ll_getitem_fast, "ll_setitem_fast": ll_setitem_fast, "_ll_resize_ge": _ll_list_resize_ge, "_ll_resize_le": _ll_list_resize_le, "_ll_resize": _ll_list_resize, - }) + })) ) def compact_repr(self): @@ -215,15 +215,15 @@ if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype ITEMARRAY = GcArray(ITEM, - adtmeths = { + adtmeths = ADTIFixedList({ "ll_newlist": ll_fixed_newlist, "ll_length": ll_fixed_length, "ll_items": ll_fixed_items, - "list_builder": self.list_builder, + ##"list_builder": self.list_builder, "ITEM": ITEM, "ll_getitem_fast": ll_fixed_getitem_fast, "ll_setitem_fast": ll_fixed_setitem_fast, - }) + })) self.LIST.become(ITEMARRAY) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Sep 2 17:41:45 2006 @@ -7,6 +7,20 @@ from pypy.rpython.lltypesystem.lltype import nullptr, Char, UniChar from pypy.rpython import robject from pypy.rpython.objectmodel import malloc_zero_filled +from pypy.rpython.annlowlevel import ADTInterface + +ADTIFixedList = ADTInterface(None, { + 'll_newlist': (['SELF', Signed ], 'self'), + 'll_length': (['self' ], Signed), + 'll_getitem_fast': (['self', Signed ], 'item'), + 'll_setitem_fast': (['self', Signed, 'item'], Void), +}) +ADTIList = ADTInterface(ADTIFixedList, { + '_ll_resize_ge': (['self', Signed ], Void), + '_ll_resize_le': (['self', Signed ], Void), + '_ll_resize': (['self', Signed ], Void), +}) + def dum_checkidx(): pass def dum_nocheck(): pass Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Sat Sep 2 17:41:45 2006 @@ -186,44 +186,44 @@ def _freeze_(self): return True -def test_list_builder(): - def fixed_size_case(): - return [42] - def variable_size_case(): - lst = [] - lst.append(42) - return lst - - from pypy.rpython.rtyper import LowLevelOpList - - for fn in [fixed_size_case, variable_size_case]: - t = TranslationContext() - t.buildannotator().build_types(fn, []) - t.buildrtyper().specialize() - LIST = t.graphs[0].getreturnvar().concretetype.TO - llop = LowLevelOpList(None) - v0 = Constant(42) - v0.concretetype = Signed - v1 = Variable() - v1.concretetype = Signed - vr = LIST.list_builder.build(llop, [v0, v1]) - assert len(llop) == 3 - assert llop[0].opname == 'direct_call' - assert len(llop[0].args) == 3 - assert llop[0].args[1].concretetype == Void - assert llop[0].args[1].value == LIST - assert llop[0].args[2].concretetype == Signed - assert llop[0].args[2].value == 2 - assert llop[0].result is vr - for op, i, vi in [(llop[1], 0, v0), (llop[2], 1, v1)]: - assert op.opname == 'direct_call' - assert len(op.args) == 5 - assert op.args[1].value is dum_nocheck - assert op.args[2] is vr - assert op.args[3].concretetype == Signed - assert op.args[3].value == i - assert op.args[4] is vi - assert op.result.concretetype is Void +##def test_list_builder(): +## def fixed_size_case(): +## return [42] +## def variable_size_case(): +## lst = [] +## lst.append(42) +## return lst + +## from pypy.rpython.rtyper import LowLevelOpList + +## for fn in [fixed_size_case, variable_size_case]: +## t = TranslationContext() +## t.buildannotator().build_types(fn, []) +## t.buildrtyper().specialize() +## LIST = t.graphs[0].getreturnvar().concretetype.TO +## llop = LowLevelOpList(None) +## v0 = Constant(42) +## v0.concretetype = Signed +## v1 = Variable() +## v1.concretetype = Signed +## vr = LIST.list_builder.build(llop, [v0, v1]) +## assert len(llop) == 3 +## assert llop[0].opname == 'direct_call' +## assert len(llop[0].args) == 3 +## assert llop[0].args[1].concretetype == Void +## assert llop[0].args[1].value == LIST +## assert llop[0].args[2].concretetype == Signed +## assert llop[0].args[2].value == 2 +## assert llop[0].result is vr +## for op, i, vi in [(llop[1], 0, v0), (llop[2], 1, v1)]: +## assert op.opname == 'direct_call' +## assert len(op.args) == 5 +## assert op.args[1].value is dum_nocheck +## assert op.args[2] is vr +## assert op.args[3].concretetype == Signed +## assert op.args[3].value == i +## assert op.args[4] is vi +## assert op.result.concretetype is Void From arigo at codespeak.net Sat Sep 2 18:37:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 18:37:04 +0200 (CEST) Subject: [pypy-svn] r31952 - pypy/dist/pypy/tool Message-ID: <20060902163704.32E771006F@code0.codespeak.net> Author: arigo Date: Sat Sep 2 18:37:02 2006 New Revision: 31952 Modified: pypy/dist/pypy/tool/error.py Log: (pedronis, arigo) Tentative: a format for annotation error with an order and an amount of blank lines that seems to help. Very subjective, of course. Modified: pypy/dist/pypy/tool/error.py ============================================================================== --- pypy/dist/pypy/tool/error.py (original) +++ pypy/dist/pypy/tool/error.py Sat Sep 2 18:37:02 2006 @@ -50,12 +50,15 @@ else: linerange = (operline, operline) here = None - lines = ["Happened at file %s line %d" % (graph.filename, here or linerange[0])] + lines = ["Happened at file %s line %d" % (graph.filename, here or linerange[0]), ""] for n in range(max(0, linerange[0]-show_lines_of_code), \ min(linerange[1]+1+show_lines_of_code, len(graph_lines)+graph.startline)): - lines.append(graph_lines[n-graph.startline]) if n == here: - lines.append('^ HERE') + prefix = '==> ' + else: + prefix = ' ' + lines.append(prefix + graph_lines[n-graph.startline]) + lines.append("") return lines class FlowingError(Exception): @@ -65,7 +68,7 @@ pass def gather_error(annotator, block, graph): - msg = [] + msg = [""] msg.append('-+' * 30) from pypy.annotation import model if model.DEBUG: @@ -73,6 +76,11 @@ _, _, operindex = annotator.why_not_annotated[block][1].break_at oper = block.operations[operindex] msg.append(" " + str(oper)) + else: + msg.append("Blocked block") + operindex = None + msg += source_lines(graph, block, operindex, long=True) + if model.DEBUG: if SHOW_ANNOTATIONS: msg.append("Known variable annotations:") for arg in oper.args + [oper.result]: @@ -81,20 +89,15 @@ msg.append(" " + str(arg) + " = " + str(annotator.binding(arg))) except KeyError: pass - msg.append("") if SHOW_TRACEBACK: msg.extend(traceback.format_exception(*annotator.why_not_annotated[block])) - else: - msg.append("Blocked block") - operindex = None - msg += source_lines(graph, block, operindex, long=True) return "\n".join(msg) def format_blocked_annotation_error(annotator, blocked_blocks, graph): - text = "" + text = [] for block in blocked_blocks: - text += gather_error(annotator, block, graph) - return text + text.append(gather_error(annotator, block, graph)) + return '\n'.join(text) def format_someobject_error(annotator, position_key, what, s_value, called_from_graph): #block = getattr(annotator, 'flowin_block', None) or block From arigo at codespeak.net Sat Sep 2 19:13:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 19:13:55 +0200 (CEST) Subject: [pypy-svn] r31953 - in pypy/dist/pypy: annotation tool Message-ID: <20060902171355.3E2881005A@code0.codespeak.net> Author: arigo Date: Sat Sep 2 19:13:53 2006 New Revision: 31953 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/tool/error.py Log: (pedronis, arigo) Ooooooooups. In case of multiple annotation errors they where shown with the source code of *another* graph - at the bytecode position where they occurred in their true graph. Produces very nice nonsense. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Sat Sep 2 19:13:53 2006 @@ -38,6 +38,7 @@ self.links_followed = {} # set of links that have ever been followed self.notify = {} # {block: {positions-to-reflow-from-when-done}} self.fixed_graphs = {} # set of graphs not to annotate again + self.blocked_blocks = {} # set of {blocked_block: graph} # --- the following information is recorded for debugging only --- # --- and only if annotation.model.DEBUG is kept to True self.why_not_annotated = {} # {block: (exc_type, exc_value, traceback)} @@ -256,32 +257,14 @@ newgraphs = self.translator.graphs #all of them got_blocked_blocks = False in self.annotated.values() if got_blocked_blocks: - if annmodel.DEBUG: - for block in self.annotated: - if self.annotated[block] is False: - graph = self.why_not_annotated[block][1].break_at[0] - self.blocked_graphs[graph] = True -## import traceback -## blocked_err = [] -## blocked_err.append('-+' * 30 +'\n') -## blocked_err.append('BLOCKED block at :' + -## self.whereami(self.why_not_annotated[block][1].break_at) + -## '\n') -## blocked_err.append('because of:\n') -## blocked_err.extend(traceback.format_exception(*self.why_not_annotated[block])) -## from pypy.interpreter.pytraceback import offset2lineno -## -## offset = block.operations[self.why_not_annotated[block][1].break_at[2]].offset -## lineno = offset2lineno(graph.func.func_code, offset) -## blocked_err.append("Happened at file %s line %d\n" % (graph.filename, lineno)) -## blocked_err.append(graph.source.split("\n")[lineno-graph.startline] + "\n") -## blocked_err.append('-+' * 30 +'\n') -## log.ERROR(''.join(blocked_err)) + for graph in self.blocked_graphs.values(): + self.blocked_graphs[graph] = True blocked_blocks = [block for block, done in self.annotated.items() if done is False] + assert len(blocked_blocks) == len(self.blocked_blocks) - text = format_blocked_annotation_error(self, blocked_blocks, graph) + text = format_blocked_annotation_error(self, self.blocked_blocks) #raise SystemExit() raise AnnotatorError(text) for graph in newgraphs: @@ -486,10 +469,13 @@ self.reflowcounter.setdefault(block, 0) self.reflowcounter[block] += 1 self.annotated[block] = graph + if block in self.blocked_blocks: + del self.blocked_blocks[block] try: self.flowin(graph, block) except BlockedInference, e: self.annotated[block] = False # failed, hopefully temporarily + self.blocked_blocks[block] = graph except Exception, e: # hack for debug tools only if not hasattr(e, '__annotator_block'): @@ -508,6 +494,7 @@ self.pendingblocks[block] = graph assert block in self.annotated self.annotated[block] = False # must re-flow + self.blocked_blocks[block] = graph def bindinputargs(self, graph, block, inputcells, called_from_graph=None): # Create the initial bindings for the input args of a block. @@ -516,6 +503,7 @@ for a, cell in zip(block.inputargs, inputcells): self.setbinding(a, cell, called_from_graph, where=where) self.annotated[block] = False # must flowin. + self.blocked_blocks[block] = graph def mergeinputargs(self, graph, block, inputcells, called_from_graph=None): # Merge the new 'cells' with each of the block's existing input Modified: pypy/dist/pypy/tool/error.py ============================================================================== --- pypy/dist/pypy/tool/error.py (original) +++ pypy/dist/pypy/tool/error.py Sat Sep 2 19:13:53 2006 @@ -93,9 +93,9 @@ msg.extend(traceback.format_exception(*annotator.why_not_annotated[block])) return "\n".join(msg) -def format_blocked_annotation_error(annotator, blocked_blocks, graph): +def format_blocked_annotation_error(annotator, blocked_blocks): text = [] - for block in blocked_blocks: + for block, graph in blocked_blocks.items(): text.append(gather_error(annotator, block, graph)) return '\n'.join(text) From arigo at codespeak.net Sat Sep 2 20:30:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 20:30:43 +0200 (CEST) Subject: [pypy-svn] r31954 - in pypy/dist/pypy: jit/codegen/i386 jit/codegen/i386/test jit/codegen/llgraph jit/codegen/llgraph/test jit/llabstractinterp jit/llabstractinterp/test jit/timeshifter jit/timeshifter/test rpython/lltypesystem Message-ID: <20060902183043.731BD10053@code0.codespeak.net> Author: arigo Date: Sat Sep 2 20:30:29 2006 New Revision: 31954 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py pypy/dist/pypy/jit/codegen/llgraph/llimpl.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py pypy/dist/pypy/jit/llabstractinterp/llcontainer.py pypy/dist/pypy/jit/llabstractinterp/llvalue.py pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py pypy/dist/pypy/jit/llabstractinterp/vlist.py pypy/dist/pypy/jit/timeshifter/oop.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/vlist.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py Log: (pedronis, arigo) Improved the interface of RGenOp. Now it starts to make sense for real back-ends, and not to make sense any more for producing llgraphs. Good trade-off. Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Sat Sep 2 20:30:29 2006 @@ -30,11 +30,6 @@ return 'var@%d' % (self.stackpos,) -class TypeConst(GenConst): - - def __init__(self, kind): - self.kind = kind - ##class Const(GenConst): ## def revealconst(self, TYPE): @@ -124,31 +119,80 @@ self.fixedposition = True return self.startaddr - def geninputarg(self, gv_TYPE): + def geninputarg(self, kind): res = Var(self.argcount) self.argcount += 1 self.stackdepth += 1 return res @specialize.arg(1) - def genop(self, opname, args_gv, gv_RESTYPE=None): + def genop1(self, opname, gv_arg): genmethod = getattr(self, 'op_' + opname) - return genmethod(args_gv, gv_RESTYPE) + return genmethod(gv_arg) + + @specialize.arg(1) + def genop2(self, opname, gv_arg1, gv_arg2): + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg1, gv_arg2) def genop_getfield(self, offset, gv_ptr): - return self.emit_getfield(gv_ptr, offset) + # XXX only for int fields + self.mc.MOV(edx, gv_ptr.operand(self)) + return self.returnvar(mem(edx, offset)) def genop_setfield(self, offset, gv_ptr, gv_value): - return self.emit_setfield(gv_ptr, offset, gv_value) + # XXX only for ints for now. + self.mc.MOV(eax, gv_value.operand(self)) + self.mc.MOV(edx, gv_ptr.operand(self)) + self.mc.MOV(mem(edx, offset), eax) def genop_getsubstruct(self, offset, gv_ptr): - return self.emit_getsubstruct(gv_ptr, offset) + self.mc.MOV(edx, gv_ptr.operand(self)) + self.mc.LEA(eax, mem(edx, offset)) + return self.returnvar(eax) def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): - return self.emit_getarrayitem(gv_ptr, arraytoken, gv_index) + # XXX! only works for GcArray(Signed) for now!! + lengthoffset, startoffset, itemoffset = arraytoken + self.mc.MOV(edx, gv_ptr.operand(self)) + if isinstance(gv_index, IntConst): + startoffset += itemoffset * gv_index.value + op = mem(edx, startoffset) + elif itemoffset in SIZE2SHIFT: + self.mc.MOV(ecx, gv_index.operand(self)) + op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset) + else: + self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) + op = memSIB(edx, ecx, 0, startoffset) + return self.returnvar(op) + + def genop_getarraysize(self, arraytoken, gv_ptr): + lengthoffset, startoffset, itemoffset = arraytoken + self.mc.MOV(edx, gv_ptr.operand(self)) + return self.returnvar(mem(edx, lengthoffset)) def genop_malloc_fixedsize(self, size): - return self.emit_malloc_fixedsize(size) + # XXX boehm only, no atomic/non atomic distinction for now + self.push(imm(size)) + gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) + self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr))) + return self.returnvar(eax) + + def genop_call(self, sigtoken, gv_fnptr, args_gv): + for i in range(len(args_gv)-1, -1, -1): + gv_arg = args_gv[i] + if gv_arg is not None: + self.push(gv_arg.operand(self)) + target = gv_fnptr.revealconst(lltype.Signed) + self.mc.CALL(rel32(target)) + # XXX only for int return_kind + return self.returnvar(eax) + + def genop_same_as(self, kind, gv_x): + if gv_x.is_const: # must always return a var + return self.returnvar(gv_x.operand(self)) + else: + return gv_x def close1(self): return Link(self) @@ -161,6 +205,8 @@ self.mc.JE(rel32(false_block.getstartaddr())) return Link(false_block), Link(self) + # ____________________________________________________________ + def stack_access(self, stackpos): return mem(esp, WORD * (self.stackdepth-1 - stackpos)) @@ -173,172 +219,114 @@ self.push(op) return res - def op_int_is_true(self, (gv_x,), gv_RESTYPE): + def op_int_is_true(self, gv_x): return gv_x - def op_int_add(self, (gv_x, gv_y), gv_RESTYPE): - if isinstance(gv_x, IntConst) and isinstance(gv_y, IntConst): - # XXX do this for the other operations too - return IntConst(gv_x.value + gv_y.value) + def op_int_add(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.ADD(eax, gv_y.operand(self)) return self.returnvar(eax) - def op_int_sub(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_sub(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.SUB(eax, gv_y.operand(self)) return self.returnvar(eax) - def op_int_mul(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_mul(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.IMUL(eax, gv_y.operand(self)) return self.returnvar(eax) - def op_int_floordiv(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_floordiv(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CDQ() self.mc.MOV(ecx, gv_y.operand(self)) self.mc.IDIV(ecx) return self.returnvar(eax) - def op_int_and(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_and(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.AND(eax, gv_y.operand(self)) return self.returnvar(eax) - def op_int_or(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_or(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.OR(eax, gv_y.operand(self)) return self.returnvar(eax) - def op_int_xor(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_xor(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.XOR(eax, gv_y.operand(self)) return self.returnvar(eax) - def op_int_lt(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_lt(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CMP(eax, gv_y.operand(self)) self.mc.SETL(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_int_le(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_le(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CMP(eax, gv_y.operand(self)) self.mc.SETLE(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_int_eq(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_eq(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CMP(eax, gv_y.operand(self)) self.mc.SETE(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_int_ne(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_ne(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CMP(eax, gv_y.operand(self)) self.mc.SETNE(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_int_gt(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_gt(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CMP(eax, gv_y.operand(self)) self.mc.SETG(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_int_ge(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_ge(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CMP(eax, gv_y.operand(self)) self.mc.SETGE(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_int_neg(self, (gv_x,), gv_RESTYPE): + def op_int_neg(self, gv_x): self.mc.MOV(eax, gv_x.operand(self)) self.mc.NEG(eax) return self.returnvar(eax) - def op_int_lshift(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_lshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.MOV(ecx, gv_y.operand(self)) self.mc.SHL(eax, cl) return self.returnvar(eax) - def op_int_rshift(self, (gv_x, gv_y), gv_RESTYPE): + def op_int_rshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.MOV(ecx, gv_y.operand(self)) self.mc.SHR(eax, cl) return self.returnvar(eax) - def op_bool_not(self, (gv_x,), gv_RESTYPE): - if isinstance(gv_x, IntConst): - return IntConst(not gv_x.value) + def op_bool_not(self, gv_x): self.mc.CMP(gv_x.operand(self), imm8(0)) self.mc.SETE(al) self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_cast_pointer(self, (gv_x,), gv_RESTYPE): - return gv_x - - def op_same_as(self, (gv_x,), gv_RESTYPE): - if gv_x.is_const: # must always return a var - return self.returnvar(gv_x.operand(self)) - else: - return gv_x - - def emit_malloc_fixedsize(self, size): - # XXX boehm only, no atomic/non atomic distinction for now - self.push(imm(size)) - gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) - self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr))) - return self.returnvar(eax) - - def emit_getfield(self, gv_ptr, offset): - # XXX only for int fields - self.mc.MOV(edx, gv_ptr.operand(self)) - return self.returnvar(mem(edx, offset)) - - def emit_setfield(self, gv_ptr, offset, gv_value): - # XXX only for ints for now. - self.mc.MOV(eax, gv_value.operand(self)) - self.mc.MOV(edx, gv_ptr.operand(self)) - self.mc.MOV(mem(edx, offset), eax) - - def emit_getsubstruct(self, gv_ptr, offset): - self.mc.MOV(edx, gv_ptr.operand(self)) - self.mc.LEA(eax, mem(edx, offset)) - return self.returnvar(eax) - - def emit_getarrayitem(self, gv_ptr, arraytoken, gv_index): - # XXX! only works for GcArray(Signed) for now!! - lengthoffset, startoffset, itemoffset = arraytoken - self.mc.MOV(edx, gv_ptr.operand(self)) - if isinstance(gv_index, IntConst): - startoffset += itemoffset * gv_index.value - op = mem(edx, startoffset) - elif itemoffset in SIZE2SHIFT: - self.mc.MOV(ecx, gv_index.operand(self)) - op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset) - else: - self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - op = memSIB(edx, ecx, 0, startoffset) - return self.returnvar(op) - - def op_getarraysize(self, (gv_ptr,), gv_RESTYPE): - # XXX! only works for GcArray(Signed) for now!! - A = DUMMY_A - lengthoffset, startoffset, itemoffset = self.rgenop.arrayToken(A) - self.mc.MOV(edx, gv_ptr.operand(self)) - return self.returnvar(mem(edx, lengthoffset)) - def op_setarrayitem(self, (gv_ptr, gv_index, gv_value), gv_RESTYPE): # XXX! only works for GcArray(Signed) for now!! + XXX-fixme A = DUMMY_A lengthoffset, startoffset, itemoffset = self.rgenop.arrayToken(A) self.mc.MOV(eax, gv_value.operand(self)) @@ -354,17 +342,6 @@ op = memSIB(edx, ecx, 0, startoffset) self.mc.MOV(op, eax) - def op_direct_call(self, args_gv, result_kind): - for i in range(len(args_gv)-1, 0, -1): - gv_arg = args_gv[i] - if gv_arg is not None: - self.push(gv_arg.operand(self)) - gv_fnptr = args_gv[0] - target = gv_fnptr.revealconst(lltype.Signed) - self.mc.CALL(rel32(target)) - # XXX only for int return_kind - return self.returnvar(eax) - DUMMY_A = lltype.GcArray(lltype.Signed) SIZE2SHIFT = {1: 0, @@ -456,9 +433,6 @@ class RI386GenOp(AbstractRGenOp): from pypy.jit.codegen.i386.codebuf import MachineCodeBlock - - gv_IntWord = TypeConst('IntWord') - gv_Void = TypeConst('Void') def __init__(self): self.mcs = [] # machine code blocks where no-one is currently writing @@ -520,24 +494,18 @@ @staticmethod @specialize.memo() - def kindToken(T): # xxx simplify - if T is lltype.Void: - return RI386GenOp.gv_Void - else: - return RI386GenOp.gv_IntWord # XXX for now - - - constPrebuiltGlobal = genconst - - constTYPE = kindToken + def kindToken(T): + return None # for now @staticmethod @specialize.memo() - def constFieldName(T, name): - return IntConst(llmemory.offsetof(T, name)) + def sigToken(FUNCTYPE): + return None # for now + + constPrebuiltGlobal = genconst - def gencallableconst(self, name, block, gv_FUNCTYPE): + def gencallableconst(self, sigtoken, name, block): prologue = self.newblock() #prologue.mc.BREAKPOINT() # re-push the arguments so that they are after the return value Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py Sat Sep 2 20:30:29 2006 @@ -15,17 +15,15 @@ def make_adder(rgenop, n): # 'return x+n' - gv_SIGNED = rgenop.constTYPE(lltype.Signed) + signed_kind = rgenop.kindToken(lltype.Signed) block = rgenop.newblock() - gv_x = block.geninputarg(gv_SIGNED) - args_gv = [gv_x, - rgenop.genconst(n)] - gv_result = block.genop("int_add", args_gv, gv_SIGNED) + gv_x = block.geninputarg(signed_kind) + gv_result = block.genop2("int_add", gv_x, rgenop.genconst(n)) link = block.close1() link.closereturn(gv_result) - gv_FUNC = rgenop.constTYPE(FUNC) - gv_add_one = rgenop.gencallableconst("adder", block, gv_FUNC) + sigtoken = rgenop.sigToken(FUNC) + gv_add_one = rgenop.gencallableconst(sigtoken, "adder", block) return gv_add_one def runner(x, y): @@ -63,29 +61,26 @@ def make_dummy(rgenop): # 'return x - (y - (x-1))' - gv_SIGNED = rgenop.constTYPE(lltype.Signed) + signed_kind = rgenop.kindToken(lltype.Signed) block = rgenop.newblock() - gv_x = block.geninputarg(gv_SIGNED) - gv_y = block.geninputarg(gv_SIGNED) - args_gv = [gv_x, rgenop.genconst(1)] - gv_z = block.genop("int_sub", args_gv, gv_SIGNED) + gv_x = block.geninputarg(signed_kind) + gv_y = block.geninputarg(signed_kind) + gv_z = block.genop2("int_sub", gv_x, rgenop.genconst(1)) link = block.close1() block2 = rgenop.newblock() - gv_y2 = block2.geninputarg(gv_SIGNED) - gv_z2 = block2.geninputarg(gv_SIGNED) - gv_x2 = block2.geninputarg(gv_SIGNED) + gv_y2 = block2.geninputarg(signed_kind) + gv_z2 = block2.geninputarg(signed_kind) + gv_x2 = block2.geninputarg(signed_kind) link.close([gv_y, gv_z, gv_x], block2) - args_gv = [gv_y2, gv_z2] - gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED) - args_gv = [gv_x2, gv_s2] - gv_t2 = block2.genop("int_sub", args_gv, gv_SIGNED) + gv_s2 = block2.genop2("int_sub", gv_y2, gv_z2) + gv_t2 = block2.genop2("int_sub", gv_x2, gv_s2) link2 = block2.close1() link2.closereturn(gv_t2) - gv_FUNC2 = rgenop.constTYPE(FUNC2) - gv_dummyfn = rgenop.gencallableconst("dummy", block, gv_FUNC2) + sigtoken = rgenop.sigToken(FUNC2) + gv_dummyfn = rgenop.gencallableconst(sigtoken, "dummy", block) return gv_dummyfn def dummy_runner(x, y): @@ -122,30 +117,28 @@ def make_branching(rgenop): # 'if x > 5: return x-1 # else: return y' - gv_SIGNED = rgenop.constTYPE(lltype.Signed) - gv_BOOL = rgenop.constTYPE(lltype.Bool) + signed_kind = rgenop.kindToken(lltype.Signed) block = rgenop.newblock() - gv_x = block.geninputarg(gv_SIGNED) - gv_y = block.geninputarg(gv_SIGNED) - args_gv = [gv_x, rgenop.genconst(5)] - gv_cond = block.genop("int_gt", args_gv, gv_BOOL) + gv_x = block.geninputarg(signed_kind) + gv_y = block.geninputarg(signed_kind) + gv_cond = block.genop2("int_gt", gv_x, rgenop.genconst(5)) link_false, link_true = block.close2(gv_cond) block2 = rgenop.newblock() - gv_one = block2.geninputarg(gv_SIGNED) - gv_x2 = block2.geninputarg(gv_SIGNED) - gv_y2 = block2.geninputarg(gv_SIGNED) + gv_one = block2.geninputarg(signed_kind) + gv_x2 = block2.geninputarg(signed_kind) + gv_y2 = block2.geninputarg(signed_kind) link_true.close([rgenop.genconst(1), gv_x, gv_y], block2) - args_gv = [gv_x2, gv_one] - gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED) + gv_s2 = block2.genop2("int_sub", gv_x2, gv_one) link2 = block2.close1() link2.closereturn(gv_s2) link_false.closereturn(gv_y) - gv_FUNC2 = rgenop.constTYPE(FUNC2) - gv_branchingfn = rgenop.gencallableconst("branching", block, gv_FUNC2) + sigtoken = rgenop.sigToken(FUNC2) + gv_branchingfn = rgenop.gencallableconst(sigtoken, + "branching", block) return gv_branchingfn def branching_runner(x, y): Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Sat Sep 2 20:30:29 2006 @@ -13,6 +13,7 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.lltypesystem.rclass import fishllattr +from pypy.rpython.lltypesystem.lloperation import llop # for debugging, sanity checks in non-RPython code @@ -96,17 +97,34 @@ opname = LLSupport.from_rstr(opname) block = from_opaque_object(blockcontainer.obj) assert block.exits == [], "block already closed" - if isinstance(gv_RESULT_TYPE, lltype.LowLevelType): + opvars = _inputvars(vars_gv) + if gv_RESULT_TYPE is guess: + RESULT_TYPE = guess_result_type(opname, opvars) + elif isinstance(gv_RESULT_TYPE, lltype.LowLevelType): RESULT_TYPE = gv_RESULT_TYPE else: RESULT_TYPE = from_opaque_object(gv_RESULT_TYPE).value - opvars = _inputvars(vars_gv) v = flowmodel.Variable() v.concretetype = RESULT_TYPE op = flowmodel.SpaceOperation(opname, opvars, v) block.operations.append(op) return to_opaque_object(erasedvar(v, block)) +def guess_result_type(opname, opvars): + op = getattr(llop, opname) + need_result_type = getattr(op.fold, 'need_result_type', False) + assert not need_result_type, ("cannot guess the result type of %r" + % (opname,)) + examples = [] + for v in opvars: + example = v.concretetype._example() + if isinstance(v.concretetype, lltype.Primitive): + if example == 0: + example = type(example)(1) # to avoid ZeroDivisionError + examples.append(example) + result = op.fold(*examples) + return lltype.typeOf(result) + def gencallableconst(name, targetcontainer, gv_FUNCTYPE): # 'name' is just a way to track things if not isinstance(name, str): @@ -327,7 +345,8 @@ nulllink = lltype.nullptr(LINK.TO) gv_Void = constTYPE(lltype.Void) -dummy_placeholder = placeholder("dummy") +dummy_placeholder = placeholder(None) +guess = placeholder('guess') # helpers @@ -384,4 +403,4 @@ # XXX(for now) void constant constructors setannotation(constFieldName, s_ConstOrVar, specialize_as_constant=True) setannotation(constTYPE, s_ConstOrVar, specialize_as_constant=True) -setannotation(placeholder, s_ConstOrVar, specialize_as_constant=True) +#setannotation(placeholder, s_ConstOrVar, specialize_as_constant=True) Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Sat Sep 2 20:30:29 2006 @@ -26,6 +26,7 @@ return repr(RGenOp.reveal(self)) gv_Void = LLConst(llimpl.constTYPE(lltype.Void)) +gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder) class LLBlock(CodeGenBlock): @@ -35,10 +36,29 @@ def geninputarg(self, gv_TYPE): return LLVar(llimpl.geninputarg(self.b, gv_TYPE.v)) +## @specialize.arg(1) +## def genop(self, opname, vars_gv, gv_RESULT_TYPE=None): +## return LLVar(llimpl.genop(self.b, opname, vars_gv, +## (gv_RESULT_TYPE or gv_Void).v)) + + @specialize.arg(1) + def genop1(self, opname, gv_arg): + return LLVar(llimpl.genop(self.b, opname, [gv_arg], llimpl.guess)) + @specialize.arg(1) - def genop(self, opname, vars_gv, gv_RESULT_TYPE=None): - return LLVar(llimpl.genop(self.b, opname, vars_gv, - (gv_RESULT_TYPE or gv_Void).v)) + def genop2(self, opname, gv_arg1, gv_arg2): + return LLVar(llimpl.genop(self.b, opname, [gv_arg1, gv_arg2], + llimpl.guess)) + + def genop_call(self, (ARGS_gv, gv_RESULT, _), gv_callable, args_gv): + vars_gv = [gv_callable] + for i in range(len(ARGS_gv)): + gv_arg = args_gv[i] + if gv_arg is not None: + gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, gv_arg.v)) + vars_gv.append(gv_arg) + # XXX indirect_call later + return LLVar(llimpl.genop(self.b, 'direct_call', vars_gv, gv_RESULT.v)) def genop_getfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr): vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v] @@ -63,11 +83,23 @@ return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv, gv_ITEMTYPE.v)) + def genop_getarraysize(self, gv_ITEMTYPE, gv_ptr): + return LLVar(llimpl.genop(self.b, 'getarraysize', [gv_ptr.v], + llimpl.constTYPE(lltype.Signed))) + def genop_malloc_fixedsize(self, (gv_TYPE, gv_PTRTYPE)): vars_gv = [gv_TYPE.v] return LLVar(llimpl.genop(self.b, 'malloc', vars_gv, gv_PTRTYPE.v)) - + + def genop_malloc_varsize(self, (gv_TYPE, gv_PTRTYPE), gv_length): + vars_gv = [gv_TYPE.v, gv_length.v] + return LLVar(llimpl.genop(self.b, 'malloc_varsize', vars_gv, + gv_PTRTYPE.v)) + + def genop_same_as(self, gv_TYPE, gv_value): + return LLVar(gv_value.v) + def close1(self): return LLLink(llimpl.closeblock1(self.b)) @@ -84,7 +116,8 @@ llimpl.closelink(self.l, vars_gv, targetblock.b) def closereturn(self, gv_returnvar): - llimpl.closereturnlink(self.l, gv_returnvar.v) + llimpl.closereturnlink(self.l, + (gv_returnvar or gv_dummy_placeholder).v) class RGenOp(AbstractRGenOp): @@ -94,7 +127,8 @@ return LLBlock(llimpl.newblock()) # XXX what kind of type/kind information does this need? - def gencallableconst(self, name, targetblock, gv_FUNCTYPE): + def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, + targetblock): return LLConst(llimpl.gencallableconst(name, targetblock.b, gv_FUNCTYPE.v)) @@ -130,22 +164,12 @@ def arrayToken(A): return LLConst(llimpl.constTYPE(A.OF)) - @staticmethod @specialize.memo() - def constTYPE(T): - return LLConst(llimpl.constTYPE(T)) - - @staticmethod - @specialize.arg(0) - def placeholder(dummy): - return LLConst(llimpl.placeholder(dummy)) - - @staticmethod - @specialize.memo() - def constFieldName(T, name): - assert name in T._flds - return LLConst(llimpl.constFieldName(name)) + def sigToken(FUNCTYPE): + return ([LLConst(llimpl.constTYPE(A)) for A in FUNCTYPE.ARGS], + LLConst(llimpl.constTYPE(FUNCTYPE.RESULT)), + LLConst(llimpl.constTYPE(FUNCTYPE))) constPrebuiltGlobal = genconst Modified: pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py Sat Sep 2 20:30:29 2006 @@ -135,14 +135,6 @@ assert c.concretetype == lltype.Void assert c.value == lltype.Signed - def dummy(): - return placeholder(None) - res = interpret(dummy, []) - c = from_opaque_object(res) - assert isinstance(c, flowmodel.Constant) - assert c.concretetype == lltype.Void - assert c.value == None - def test_rtype_revealcosnt(): def hide_and_reveal(v): gv = genconst(v) Modified: pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py Sat Sep 2 20:30:29 2006 @@ -160,7 +160,8 @@ class LLAbstractInterp(object): - def __init__(self, policy=best_policy): + def __init__(self, rtyper, policy=best_policy): + self.rtyper = rtyper self.graphs = [] self.graphstates = {} # {origgraph: {BlockState: GraphState}} self.blocks = {} # {BlockState.key(): list-of-LLBlockStates} @@ -276,8 +277,11 @@ assert isinstance(v2, (AVariable, AConstant)) if isinstance(v2, AConstant): # sanity check violating encapsulation - v1 = rgenop.reveal(v1) - assert v1.value == v2.value + if v2.concretetype is lltype.Void: + assert v1 is None + else: + v1 = rgenop.reveal(v1) + assert v1.value == v2.value else: args.append(v1) self.link.close(args, block) @@ -541,18 +545,36 @@ ls.link = cases[ls.exitcase] return b - def genop(self, opname, args, RESULT_TYPE=lltype.Void): - return self.newblock.genop(opname, args, - rgenop.constTYPE(RESULT_TYPE)) +## def genop(self, opname, args, RESULT_TYPE=lltype.Void): +## return self.newblock.genop(opname, args, +## rgenop.constTYPE(RESULT_TYPE)) - def genconst(self, llvalue): - return rgenop.genconst(llvalue) + def genop1(self, opname, arg): + return self.newblock.genop1(opname, arg) + + def genop2(self, opname, arg1, arg2): + return self.newblock.genop2(opname, arg1, arg2) + + def genop_call(self, sigtoken, v_callable, args_v): + return self.newblock.genop_call(sigtoken, v_callable, args_v) + + def genop_malloc_fixedsize(self, alloctoken): + return self.newblock.genop_malloc_fixedsize(alloctoken) - def genvoidconst(self, placeholder): - return rgenop.placeholder(placeholder) + def genop_malloc_varsize(self, alloctoken, v_length): + return self.newblock.genop_malloc_varsize(alloctoken, v_length) - def constTYPE(self, T): - return T + def genop_getfield(self, fieldtoken, v_ptr): + return self.newblock.genop_getfield(fieldtoken, v_ptr) + + def genop_setfield(self, fieldtoken, v_ptr, v_value): + return self.newblock.genop_setfield(fieldtoken, v_ptr, v_value) + + def genop_getsubstruct(self, fieldtoken, v_ptr): + return self.newblock.genop_getsubstruct(fieldtoken, v_ptr) + + def genconst(self, llvalue): + return rgenop.genconst(llvalue) def binding(self, v): assert isinstance(v, (Constant, Variable)) @@ -595,20 +617,27 @@ return a_result def residual(self, op, args_a): - T= op.result.concretetype - retvar = self.genop(op.opname, - [a.forcegenvarorconst(self) for a in args_a], - T) + T = op.result.concretetype + args_v = [a.forcegenvarorconst(self) for a in args_a] + if op.opname == 'direct_call': + sigtoken = rgenop.sigToken(args_a[0].getconcretetype().TO) + retvar = self.genop_call(sigtoken, args_v[0], args_v[1:]) + elif op.opname == 'getfield': + fieldtoken = rgenop.fieldToken(args_a[0].getconcretetype().TO, + op.args[1].value) + retvar = self.genop_getfield(fieldtoken, args_v[0]) + else: + # generic version + genopmeth = getattr(self, 'genop%d' % len(args_a)) + retvar = genopmeth(op.opname, *args_v) return LLAbstractValue(AVariable(T, genvar=retvar)) def residual_direct_call(self, FUNCTYPE, name, target, args_a): T = FUNCTYPE.RESULT - gen_fn_const = rgenop.gencallableconst(name, - target, - rgenop.constTYPE(FUNCTYPE)) - retvar = self.genop('direct_call', [gen_fn_const] + - [a.forcegenvarorconst(self) for a in args_a], - T) + sigtoken = rgenop.sigToken(FUNCTYPE) + gen_fn_const = rgenop.gencallableconst(sigtoken, name, target) + retvar = self.genop_call(sigtoken, gen_fn_const, + [a.forcegenvarorconst(self) for a in args_a]) return LLAbstractValue(AVariable(T, genvar=retvar)) Modified: pypy/dist/pypy/jit/llabstractinterp/llcontainer.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/llcontainer.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/llcontainer.py Sat Sep 2 20:30:29 2006 @@ -52,19 +52,16 @@ RESULT_TYPE = lltype.Ptr(self.T) if self.a_parent is not None: PARENT_TYPE = self.a_parent.getconcretetype().TO - parentindex = rgenop.constFieldName(PARENT_TYPE, self.parentindex) + fieldtoken = rgenop.fieldToken(PARENT_TYPE, self.parentindex) v_parent = self.a_parent.forcegenvarorconst(builder) - v_result = builder.genop('getsubstruct', - [v_parent, parentindex], RESULT_TYPE) + v_result = builder.genop_getsubstruct(fieldtoken, v_parent) else: - t = rgenop.constTYPE(self.T) + t = rgenop.allocToken(self.T) if self.T._is_varsize(): - v_result = builder.genop('malloc_varsize', - [t, - builder.genconst(self.length)], - RESULT_TYPE) + c_length = builder.genconst(self.length) + v_result = builder.genop_malloc_varsize(t, c_length) else: - v_result = builder.genop('malloc', [t], RESULT_TYPE) + v_result = builder.genop_malloc_fixedsize(t) self.buildcontent(builder, v_result) return v_result @@ -76,10 +73,8 @@ T = self.fieldtype(name) if isinstance(T, lltype.ContainerType): # initialize the substructure/subarray - c_name = rgenop.constFieldName(self.T, name) - v_subptr = builder.genop('getsubstruct', - [v_target, c_name], - lltype.Ptr(T)) + fieldtoken = rgenop.fieldToken(self.T, name) + v_subptr = builder.genop_getsubstruct(fieldtoken, v_target) assert isinstance(a_value.content, LLVirtualContainer) a_value.content.buildcontent(builder, v_subptr) else: @@ -167,9 +162,8 @@ return getattr(self.T, name) def setop(self, builder, v_target, name, v_value): - c_name = rgenop.constFieldName(self.T, name) - builder.genop('setfield', [v_target, c_name, v_value], - lltype.Void) + fieldtoken = rgenop.fieldToken(self.T, name) + builder.genop_setfield(fieldtoken, v_target, v_value) class LLVirtualArray(LLVirtualContainer): Modified: pypy/dist/pypy/jit/llabstractinterp/llvalue.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/llvalue.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/llvalue.py Sat Sep 2 20:30:29 2006 @@ -16,11 +16,9 @@ Hashable.__init__(self, value) self.concretetype = T or lltype.typeOf(value) self.genvar = genvar - if T is lltype.Void and self.genvar is None: - self.genvar = rgenop.placeholder(value) - + def getgenvar(self, builder): - if self.genvar is None: + if self.genvar is None and self.concretetype is not lltype.Void: self.genvar = builder.genconst(self.value) return self.genvar @@ -202,7 +200,7 @@ assert c.concretetype == self.concretetype result = LLAbstractValue(c) else: - gen_v = block.geninputarg(rgenop.constTYPE(self.concretetype)) + gen_v = block.geninputarg(rgenop.kindToken(self.concretetype)) result = LLAbstractValue(AVariable(self.concretetype, genvar=gen_v)) result.origin.append(self) return result Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py Sat Sep 2 20:30:29 2006 @@ -17,11 +17,12 @@ #inline.auto_inlining(t, 0.3) mod.graph1 = t.graphs[0] + mod.rtyper = rtyper mod.llinterp = LLInterpreter(rtyper) def jit_tl(code): - interp = LLAbstractInterp() + interp = LLAbstractInterp(rtyper) hints = {0: string_repr.convert_const(code), 1: 0} graph2 = interp.eval(graph1, hints) Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py Sat Sep 2 20:30:29 2006 @@ -15,7 +15,7 @@ rtyper = t.buildrtyper() rtyper.specialize() - interp = LLAbstractInterp() + interp = LLAbstractInterp(rtyper) hints = {0: string_repr.convert_const(tlr.SQUARE)} graph2 = interp.eval(t.graphs[0], hints) #graph2.show() Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py Sat Sep 2 20:30:29 2006 @@ -34,7 +34,7 @@ rtyper = t.buildrtyper() rtyper.specialize() # build the residual ll graphs by propagating the hints - interp = LLAbstractInterp(policy) + interp = LLAbstractInterp(rtyper, policy) hints = {} for hint in arghints: hints[hint] = argvalues[hint] Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py Sat Sep 2 20:30:29 2006 @@ -16,7 +16,7 @@ rtyper.specialize() graph1 = t.graphs[0] - interp = LLAbstractInterp(policy) + interp = LLAbstractInterp(rtyper, policy) hints = {} llvalues = [] for i, value in enumerate(argvalues): Modified: pypy/dist/pypy/jit/llabstractinterp/vlist.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/vlist.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/vlist.py Sat Sep 2 20:30:29 2006 @@ -3,6 +3,7 @@ from pypy.jit.llabstractinterp.llvalue import LLAbstractValue, AConstant from pypy.jit.llabstractinterp.llvalue import ll_dummy_value from pypy.jit.llabstractinterp.llcontainer import LLAbstractContainer +from pypy.jit.codegen.llgraph.rgenop import rgenop class LLVirtualList(LLAbstractContainer): @@ -40,9 +41,29 @@ return LLVirtualList(self.T, items_a) def build_runtime_container(self, builder): + rtyper = builder.interp.rtyper + LIST = self.T + + argtypes = [lltype.Signed] + ll_newlist_ptr = rtyper.annotate_helper_fn(LIST.ll_newlist, + argtypes) + c_ll_newlist = rgenop.constPrebuiltGlobal(ll_newlist_ptr) + ll_newlist_sig = rgenop.sigToken(lltype.typeOf(ll_newlist_ptr).TO) + + argtypes = [lltype.Ptr(LIST), lltype.Signed, LIST.ITEM] + ll_setitem_ptr = rtyper.annotate_helper_fn(LIST.ll_setitem_fast, + argtypes) + c_ll_setitem = rgenop.constPrebuiltGlobal(ll_setitem_ptr) + ll_setitem_sig = rgenop.sigToken(lltype.typeOf(ll_setitem_ptr).TO) + items_v = [a.forcegenvarorconst(builder) for a in self.items_a] - v_result = self.T.list_builder.build(builder, items_v) - return v_result + v_list = builder.genop_call(ll_newlist_sig, c_ll_newlist, + [None, builder.genconst(len(items_v))]) + + for i in range(len(items_v)): + builder.genop_call(ll_setitem_sig, c_ll_setitem, + [v_list, builder.genconst(i), items_v[i]]) + return v_list # ____________________________________________________________ # High-level operations Modified: pypy/dist/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/oop.py (original) +++ pypy/dist/pypy/jit/timeshifter/oop.py Sat Sep 2 20:30:29 2006 @@ -28,19 +28,20 @@ self.argpositions = [] for i, obj in enumerate(self.argtuple): if isinstance(obj, Index): - self.argpositions.append(obj.n + 1) + self.argpositions.append(obj.n) else: - self.argpositions.append(0) + self.argpositions.append(-1) for i in range(nb_args): ARGTYPE = FUNCTYPE.ARGS[i] - assert ((i+1) in self.argpositions) == (ARGTYPE is not lltype.Void) + assert (i in self.argpositions) == (ARGTYPE is not lltype.Void) RGenOp = hrtyper.RGenOp self.args_gv = [None] * nb_args - self.args_gv.insert(0, RGenOp.constPrebuiltGlobal(fnobj._as_ptr())) + self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnobj._as_ptr()) self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT) self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT) + self.sigtoken = RGenOp.sigToken(FUNCTYPE) if operation_name == 'newlist': from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist @@ -58,10 +59,8 @@ argpositions = self.argpositions for i in range(len(argpositions)): pos = argpositions[i] - if pos > 0: + if pos >= 0: gv_arg = argboxes[i].getgenvar(builder) args_gv[pos] = gv_arg - gv_result = builder.genop('direct_call', - args_gv, - self.result_kind) + gv_result = builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv) return self.redboxbuilder(self.result_kind, gv_result) Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Sat Sep 2 20:30:29 2006 @@ -123,6 +123,7 @@ assert isinstance(PTRTYPE.TO, lltype.Array) FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF) self.arraytoken = RGenOp.arrayToken(PTRTYPE.TO) + self.indexkind = RGenOp.kindToken(lltype.Signed) # ____________________________________________________________ Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Sat Sep 2 20:30:29 2006 @@ -61,9 +61,8 @@ arg = rvalue.ll_getvalue(argbox, ARG0) res = opdesc.llop(RESULT, arg) return rvalue.ll_fromvalue(jitstate, res) - op_args = [argbox.getgenvar(jitstate.curbuilder)] - genvar = jitstate.curbuilder.genop(opdesc.opname, op_args, - opdesc.result_kind) + gv_arg = argbox.getgenvar(jitstate.curbuilder) + genvar = jitstate.curbuilder.genop1(opdesc.opname, gv_arg) return opdesc.redboxcls(opdesc.result_kind, genvar) def ll_generate_operation2(opdesc, jitstate, argbox0, argbox1): @@ -77,10 +76,9 @@ arg1 = rvalue.ll_getvalue(argbox1, ARG1) res = opdesc.llop(RESULT, arg0, arg1) return rvalue.ll_fromvalue(jitstate, res) - op_args = [argbox0.getgenvar(jitstate.curbuilder), - argbox1.getgenvar(jitstate.curbuilder)] - genvar = jitstate.curbuilder.genop(opdesc.opname, op_args, - opdesc.result_kind) + gv_arg0 = argbox0.getgenvar(jitstate.curbuilder) + gv_arg1 = argbox1.getgenvar(jitstate.curbuilder) + genvar = jitstate.curbuilder.genop2(opdesc.opname, gv_arg0, gv_arg1) return opdesc.redboxcls(opdesc.result_kind, genvar) def ll_generate_getfield(jitstate, fielddesc, argbox): @@ -128,6 +126,16 @@ return fielddesc.redboxcls(fielddesc.kind, genvar) +def ll_generate_getarraysize(jitstate, fielddesc, argbox): + if argbox.is_constant(): + array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE) + res = len(array) + return rvalue.ll_fromvalue(jitstate, res) + genvar = jitstate.curbuilder.genop_getarraysize( + fielddesc.arraytoken, + argbox.getgenvar(jitstate.curbuilder)) + return rvalue.IntRedBox(fielddesc.indexkind, genvar) + # ____________________________________________________________ # other jitstate/graph level operations @@ -299,9 +307,20 @@ ## return self.rgenop.placeholder(dummy) ## genvoidconst._annspecialcase_ = 'specialize:arg(1)' - def genop(self, opname, args_gv, result_kind=None): - return self.block.genop(opname, args_gv, result_kind) - genop._annspecialcase_ = 'specialize:arg(1)' +## def genop(self, opname, args_gv, result_kind=None): +## return self.block.genop(opname, args_gv, result_kind) +## genop._annspecialcase_ = 'specialize:arg(1)' + + def genop1(self, opname, gv_arg): + return self.block.genop1(opname, gv_arg) + genop1._annspecialcase_ = 'specialize:arg(1)' + + def genop2(self, opname, gv_arg1, gv_arg2): + return self.block.genop2(opname, gv_arg1, gv_arg2) + genop2._annspecialcase_ = 'specialize:arg(1)' + + def genop_call(self, sigtoken, gv_callable, args_gv): + return self.block.genop_call(sigtoken, gv_callable, args_gv) def genop_getfield(self, fieldtoken, gv_ptr): return self.block.genop_getfield(fieldtoken, gv_ptr) @@ -314,10 +333,16 @@ def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): return self.block.genop_getarrayitem(arraytoken, gv_ptr, gv_index) + + def genop_getarraysize(self, arraytoken, gv_ptr): + return self.block.genop_getarraysize(arraytoken, gv_ptr) def genop_malloc_fixedsize(self, alloctoken): return self.block.genop_malloc_fixedsize(alloctoken) + def genop_same_as(self, kind, gv_value): + return self.block.genop_same_as(kind, gv_value) + def constTYPE(self, T): return self.rgenop.constTYPE(T) constTYPE._annspecialcase_ = 'specialize:arg(1)' Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sat Sep 2 20:30:29 2006 @@ -151,11 +151,32 @@ c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() - return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getarrayitem, + return hop.llops.genmixlevelhelpercall( + rtimeshift.ll_generate_getarrayitem, [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox], [v_jitstate, c_fielddesc, v_argbox, v_index ], ts.s_RedBox) + def translate_op_getarraysize(self, hop): + res = self.generic_translate_operation(hop, force=True) + if res is not None: + return res + + PTRTYPE = originalconcretetype(hop.args_s[0]) + ts = self.timeshifter + [v_argbox] = hop.inputargs(self.getredrepr(PTRTYPE)) + + fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE) + c_fielddesc = inputconst(lltype.Void, fielddesc) + s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall( + rtimeshift.ll_generate_getarraysize, + [ts.s_JITState, s_fielddesc, ts.s_RedBox], + [v_jitstate, c_fielddesc, v_argbox ], + ts.s_RedBox) + + def translate_op_setfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_setfield(hop) Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Sat Sep 2 20:30:29 2006 @@ -49,7 +49,7 @@ if self.is_constant(): # cannot mutate constant boxes in-place box = self.copy(memo) - box.genvar = builder.genop("same_as", [self.genvar], self.kind) + box.genvar = builder.genop_same_as(self.kind, self.genvar) return box else: # force virtual containers Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Sat Sep 2 20:30:29 2006 @@ -151,22 +151,22 @@ llvalue = args[1] args = args[2:] TYPE = lltype.typeOf(llvalue) - gv_type = rgenop.constTYPE(TYPE) + kind = rgenop.kindToken(TYPE) boxcls = rvalue.ll_redboxcls(TYPE) - gv_arg = rtimeshift.ll_geninputarg(builder, gv_type) + gv_arg = rtimeshift.ll_geninputarg(builder, kind) if is_constant: # ignore the gv_arg above, which is still present # to give the residual graph a uniform signature gv_arg = rgenop.genconst(llvalue) - box = boxcls(gv_type, gv_arg) + box = boxcls(kind, gv_arg) timeshifted_entrypoint_args += (box,) startblock = rtimeshift.ll_end_setup_builder(builder) endbuilder = timeshifted_entrypoint(builder, None, *timeshifted_entrypoint_args) endbuilder.finish_and_return() - gv_functype = rgenop.constTYPE(FUNC) - gv_generated = rgenop.gencallableconst("generated", startblock, - gv_functype) + sigtoken = rgenop.sigToken(FUNC) + gv_generated = rgenop.gencallableconst(sigtoken, "generated", + startblock) generated = gv_generated.revealconst(lltype.Ptr(FUNC)) return generated Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Sat Sep 2 20:30:29 2006 @@ -17,11 +17,14 @@ ll_newlist_ptr = rtyper.annotate_helper_fn(LIST.ll_newlist, argtypes) self.gv_ll_newlist = RGenOp.constPrebuiltGlobal(ll_newlist_ptr) + self.tok_ll_newlist = RGenOp.sigToken(lltype.typeOf(ll_newlist_ptr).TO) argtypes = [self.LISTPTR, lltype.Signed, LIST.ITEM] ll_setitem_fast = rtyper.annotate_helper_fn(LIST.ll_setitem_fast, argtypes) self.gv_ll_setitem_fast = RGenOp.constPrebuiltGlobal(ll_setitem_fast) + self.tok_ll_setitem_fast = RGenOp.sigToken( + lltype.typeOf(ll_setitem_fast).TO) def factory(self, length, itembox): vlist = VirtualList(self, length, itembox) @@ -84,15 +87,18 @@ boxes = self.item_boxes self.item_boxes = None - args_gv = [typedesc.gv_ll_newlist, None, builder.genconst(len(boxes))] - gv_list = builder.genop('direct_call', args_gv, typedesc.ptrkind) + args_gv = [None, builder.genconst(len(boxes))] + gv_list = builder.genop_call(typedesc.tok_ll_newlist, + typedesc.gv_ll_newlist, + args_gv) self.ownbox.genvar = gv_list self.ownbox.content = None for i in range(len(boxes)): gv_item = boxes[i].getgenvar(builder) - args_gv = [typedesc.gv_ll_setitem_fast, gv_list, - builder.genconst(i), gv_item] - builder.genop('direct_call', args_gv) + args_gv = [gv_list, builder.genconst(i), gv_item] + builder.genop_call(typedesc.tok_ll_setitem_fast, + typedesc.gv_ll_setitem_fast, + args_gv) def freeze(self, memo): contmemo = memo.containers Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat Sep 2 20:30:29 2006 @@ -3,6 +3,7 @@ """ from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.objspace.flow.model import roproperty class LLOp(object): @@ -54,7 +55,7 @@ val = lltype.enforce(RESULTTYPE, val) return val - def fold(self, RESULTTYPE, *args): + def get_fold_impl(self): global lltype # <- lazy import hack, worth an XXX from pypy.rpython.lltypesystem import lltype if self.canfold or self.opname in ('getfield', 'getarrayitem'): @@ -67,8 +68,8 @@ raise error # cache the implementation function into 'self' self.fold = op_impl - return self(RESULTTYPE, *args) - fold.need_result_type = True + return op_impl + fold = roproperty(get_fold_impl) def enum_ops_without_sideeffects(raising_is_ok=False): From arigo at codespeak.net Sat Sep 2 21:47:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Sep 2006 21:47:41 +0200 (CEST) Subject: [pypy-svn] r31960 - pypy/dist/pypy/rpython/test Message-ID: <20060902194741.0E5561006E@code0.codespeak.net> Author: arigo Date: Sat Sep 2 21:47:39 2006 New Revision: 31960 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py Log: This test passes if we spot the typo in it :-) Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Sat Sep 2 21:47:39 2006 @@ -478,7 +478,6 @@ raise TypeError def test_llinterp_fail(): - py.test.skip("Fails") def aa(i): if i: raise TypeError() @@ -493,6 +492,6 @@ annotator = t.buildannotator() annotator.build_types(bb, [int]) t.buildrtyper(type_system="ootype").specialize() - graph = graphof(t, aa) + graph = graphof(t, bb) interp = LLInterpreter(t.rtyper) res = interp.eval_graph(graph, [1]) From arigo at codespeak.net Sun Sep 3 13:43:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 13:43:08 +0200 (CEST) Subject: [pypy-svn] r31963 - in pypy/dist/pypy/translator: . test Message-ID: <20060903114308.CD5DC10063@code0.codespeak.net> Author: arigo Date: Sun Sep 3 13:43:06 2006 New Revision: 31963 Modified: pypy/dist/pypy/translator/simplify.py pypy/dist/pypy/translator/test/test_simplify.py pypy/dist/pypy/translator/translator.py Log: Experimental: in the flow graphs, detect the patterns made by list comprehension before annotation, and insert different operations that should allow more precise annotations and more efficient implementation in the rtyper. Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Sun Sep 3 13:43:06 2006 @@ -706,7 +706,318 @@ newtgts = has_is_true_exitpath(cand) if newtgts: candidates.append((cand, newtgts)) - + +# ____________________________________________________________ + +def detect_list_comprehension(graph): + """Look for the pattern: Replace it with marker operations: + + v1 = newlist() v0 = newlistbuilder(length) + loop start loop start + ... ... + exactly one append per loop v0.append(..) + and nothing else done with v1 + ... ... + loop end v1 = listbuilder_done(v0) + """ + # NB. this assumes RPythonicity: we can only iterate over something + # that has a len(), and this len() cannot change as long as we are + # using the iterator. + from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder + builder = DataFlowFamilyBuilder(graph) + variable_families = builder.get_variable_families() + c_append = Constant('append') + newlist_v = {} + iter_v = {} + append_v = [] + loopnextblocks = [] + + # collect relevant operations based on the family of their result + for block in graph.iterblocks(): + if (len(block.operations) == 1 and + block.operations[0].opname == 'next' and + block.exitswitch == c_last_exception and + len(block.exits) == 2 and + block.exits[1].exitcase is StopIteration and + block.exits[0].exitcase is None): + # it's a straightforward loop start block + loopnextblocks.append((block, block.operations[0].args[0])) + continue + for op in block.operations: + if op.opname == 'newlist' and not op.args: + vlist = variable_families.find_rep(op.result) + newlist_v[vlist] = block + if op.opname == 'iter': + viter = variable_families.find_rep(op.result) + iter_v[viter] = block + loops = [] + for block, viter in loopnextblocks: + viterfamily = variable_families.find_rep(viter) + if viterfamily in iter_v: + # we have a next(viter) operation where viter comes from a + # single known iter() operation. Check that the iter() + # operation is in the block just before. + iterblock = iter_v[viterfamily] + if (len(iterblock.exits) == 1 and iterblock.exitswitch is None + and iterblock.exits[0].target is block): + # yes - simple case. + loops.append((block, iterblock, viterfamily)) + if not newlist_v or not loops: + return + + # XXX works with Python 2.4 only: find calls to append encoded as + # getattr/simple_call pairs + for block in graph.iterblocks(): + for i in range(len(block.operations)-1): + op = block.operations[i] + if op.opname == 'getattr' and op.args[1] == c_append: + vlist = variable_families.find_rep(op.args[0]) + if vlist in newlist_v: + op2 = block.operations[i+1] + if (op2.opname == 'simple_call' and len(op2.args) == 2 + and op2.args[0] is op.result): + append_v.append((op.args[0], op.result, block)) + if not append_v: + return + detector = ListComprehensionDetector(graph, loops, newlist_v, + variable_families) + for location in append_v: + try: + detector.run(*location) + except DetectorFailed: + pass + + +class DetectorFailed(Exception): + pass + +class ListComprehensionDetector(object): + + def __init__(self, graph, loops, newlist_v, variable_families): + self.graph = graph + self.loops = loops + self.newlist_v = newlist_v + self.variable_families = variable_families + + def enum_blocks_from(self, fromblock, avoid): + found = {avoid: True} + pending = [fromblock] + while pending: + block = pending.pop() + if block in found: + continue + yield block + found[block] = True + for exit in block.exits: + pending.append(exit.target) + + def enum_reachable_blocks(self, fromblock, stop_at): + if fromblock is stop_at: + return + found = {stop_at: True} + pending = [fromblock] + while pending: + block = pending.pop() + if block in found: + continue + found[block] = True + for exit in block.exits: + yield exit.target + pending.append(exit.target) + + def reachable(self, fromblock, toblock, avoid): + if toblock is avoid: + return False + for block in self.enum_reachable_blocks(fromblock, avoid): + if block is toblock: + return True + return False + + def vlist_alive(self, block): + # check if 'block' is in the "cone" of blocks where + # the vlistfamily lives + try: + return self.vlistcone[block] + except KeyError: + result = bool(self.contains_vlist(block.inputargs)) + self.vlistcone[block] = result + return result + + def vlist_escapes(self, block): + # check if the vlist "escapes" to uncontrolled places in that block + try: + return self.escapes[block] + except KeyError: + for op in block.operations: + if op.result is self.vmeth: + continue # the single getattr(vlist, 'append') is ok + if op.opname == 'getitem': + continue # why not allow getitem(vlist, index) too + if self.contains_vlist(op.args): + result = True + break + else: + result = False + self.escapes[block] = result + return result + + def contains_vlist(self, args): + for arg in args: + if self.variable_families.find_rep(arg) is self.vlistfamily: + return arg + else: + return None + + def remove_vlist(self, args): + removed = 0 + for i in range(len(args)-1, -1, -1): + arg = self.variable_families.find_rep(args[i]) + if arg is self.vlistfamily: + del args[i] + removed += 1 + assert removed == 1 + + def run(self, vlist, vmeth, appendblock): + # first check that the 'append' method object doesn't escape + for op in appendblock.operations: + if op.opname == 'simple_call' and op.args[0] is vmeth: + pass + elif vmeth in op.args: + raise DetectorFailed # used in another operation + for link in appendblock.exits: + if vmeth in link.args: + raise DetectorFailed # escapes to a next block + + self.vmeth = vmeth + self.vlistfamily = self.variable_families.find_rep(vlist) + newlistblock = self.newlist_v[self.vlistfamily] + self.vlistcone = {newlistblock: True} + self.escapes = {self.graph.returnblock: True, + self.graph.exceptblock: True} + + # in which loop are we? + for loopnextblock, iterblock, viterfamily in self.loops: + # check that the vlist is alive across the loop head block, + # which ensures that we have a whole loop where the vlist + # doesn't change + if not self.vlist_alive(loopnextblock): + continue # no - unrelated loop + + # check that we cannot go from 'newlist' to 'append' without + # going through the 'iter' of our loop (and the following 'next'). + # This ensures that the lifetime of vlist is cleanly divided in + # "before" and "after" the loop... + if self.reachable(newlistblock, appendblock, avoid=iterblock): + continue + + # ... with the possible exception of links from the loop + # body jumping back to the loop prologue, between 'newlist' and + # 'iter', which we must forbid too: + if self.reachable(loopnextblock, iterblock, avoid=newlistblock): + continue + + # there must not be a larger number of calls to 'append' than + # the number of elements that 'next' returns, so we must ensure + # that we cannot go from 'append' to 'append' again without + # passing 'next'... + if self.reachable(appendblock, appendblock, avoid=loopnextblock): + continue + + # ... and when the iterator is exhausted, we should no longer + # reach 'append' at all. + assert loopnextblock.exits[1].exitcase is StopIteration + stopblock = loopnextblock.exits[1].target + if self.reachable(stopblock, appendblock, avoid=newlistblock): + continue + + # now explicitly find the "loop body" blocks: they are the ones + # from which we can reach 'append' without going through 'iter'. + # (XXX inefficient) + loopbody = {} + for block in self.graph.iterblocks(): + if (self.vlist_alive(block) and + self.reachable(block, appendblock, iterblock)): + loopbody[block] = True + + # if the 'append' is actually after a 'break' or on a path that + # can only end up in a 'break', then it won't be recorded as part + # of the loop body at all. This is a strange case where we have + # basically proved that the list will be of length 1... too + # uncommon to worry about, I suspect + if appendblock not in loopbody: + continue + + # This candidate loop is acceptable if the list is not escaping + # too early, i.e. in the loop header or in the loop body. + loopheader = list(self.enum_blocks_from(newlistblock, + avoid=loopnextblock)) + escapes = False + for block in loopheader + loopbody.keys(): + assert self.vlist_alive(block) + if self.vlist_escapes(block): + escapes = True + break + + if not escapes: + break # accept this loop! + + else: + raise DetectorFailed # no suitable loop + + # Found a suitable loop, let's patch the graph: + + # - remove newlist() + for op in newlistblock.operations: + if op.opname == 'newlist': + res = self.variable_families.find_rep(op.result) + if res is self.vlistfamily: + newlistblock.operations.remove(op) + break + else: + raise AssertionError("bad newlistblock") + + # - remove the vlist variable from all blocks of the loop header, + # up to the iterblock + for block in loopheader: + if block is not newlistblock: + self.remove_vlist(block.inputargs) + if block is not iterblock: + for link in block.exits: + self.remove_vlist(link.args) + + # - add a newlistbuilder() in the iterblock, where we can compute + # the known maximum length + vlist = self.contains_vlist(iterblock.exits[0].args) + assert vlist + for op in iterblock.operations: + res = self.variable_families.find_rep(op.result) + if res is viterfamily: + break + else: + raise AssertionError("lost 'iter' operation") + vlength = Variable('maxlength') + iterblock.operations += [ + SpaceOperation('len', [op.args[0]], vlength), + SpaceOperation('newlistbuilder', [vlength], vlist)] + + # - wherever the list exits the loop body, add a 'listbuilder_done' + from pypy.translator.unsimplify import insert_empty_block + for block in loopbody: + for link in block.exits: + if link.target not in loopbody: + vlist = self.contains_vlist(link.args) + if vlist is None: + continue # list not passed along this link anyway + newblock = insert_empty_block(None, link) + index = link.args.index(vlist) + vlist2 = newblock.inputargs[index] + vlist3 = Variable('listbuilder') + newblock.inputargs[index] = vlist3 + newblock.operations.append( + SpaceOperation('listbuilder_done', [vlist3], vlist2)) + # done! + + # ____ all passes & simplify_graph all_passes = [ Modified: pypy/dist/pypy/translator/test/test_simplify.py ============================================================================== --- pypy/dist/pypy/translator/test/test_simplify.py (original) +++ pypy/dist/pypy/translator/test/test_simplify.py Sun Sep 3 13:43:06 2006 @@ -3,6 +3,7 @@ from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.simplify import get_graph, transform_dead_op_vars from pypy.objspace.flow.model import traverse, Block +from pypy import conftest def translate(func, argtypes, backend_optimize=True): t = TranslationContext() @@ -187,3 +188,26 @@ interp = LLInterpreter(t.rtyper) e = py.test.raises(LLException, 'interp.eval_graph(graph, [])') assert 'ValueError' in str(e) + +def test_detect_list_comprehension(): + def f1(l): + return [x*17 for x in l] + + t = TranslationContext(list_comprehension_operations=True) + graph = t.buildflowgraph(f1) + if conftest.option.view: + graph.show() + insns = {} + for block in graph.iterblocks(): + for op in block.operations: + insns[op.opname] = insns.get(op.opname, 0) + 1 + assert insns == { + 'iter': 1, + 'len': 1, + 'newlistbuilder': 1, + 'next': 1, + 'mul': 1, + 'getattr': 1, + 'simple_call': 1, + 'listbuilder_done': 1, + } Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Sun Sep 3 13:43:06 2006 @@ -7,7 +7,7 @@ import autopath, os, sys, types, copy from pypy.objspace.flow.model import * -from pypy.translator.simplify import simplify_graph +from pypy.translator import simplify from pypy.objspace.flow import FlowObjSpace from pypy.tool.ansi_print import ansi_log from pypy.tool.sourcetools import nice_repr_for_func @@ -21,6 +21,7 @@ 'simplifying': True, 'do_imports_immediately': True, 'builtins_can_raise_exceptions': False, + 'list_comprehension_operations': False, } def __init__(self, **flowing_flags): @@ -53,7 +54,9 @@ self.annotator.policy._adjust_space_config(space) graph = space.build_flow(func) if self.flags.get('simplifying'): - simplify_graph(graph) + simplify.simplify_graph(graph) + if self.flags.get('list_comprehension_operations'): + simplify.detect_list_comprehension(graph) if self.flags.get('verbose'): log.done(func.__name__) self.graphs.append(graph) # store the graph in our list From fijal at codespeak.net Sun Sep 3 14:07:37 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 Sep 2006 14:07:37 +0200 (CEST) Subject: [pypy-svn] r31964 - in pypy/dist/pypy/translator/transformer: . test Message-ID: <20060903120737.18B581006C@code0.codespeak.net> Author: fijal Date: Sun Sep 3 14:07:16 2006 New Revision: 31964 Added: pypy/dist/pypy/translator/transformer/debug.py (contents, props changed) pypy/dist/pypy/translator/transformer/test/test_debug.py (contents, props changed) Modified: pypy/dist/pypy/translator/transformer/basictransform.py pypy/dist/pypy/translator/transformer/test/test_basictransform.py Log: Added simple debug transform. With a little effort it could be used to handle debug stuff (some annotation problems still exists). Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Sun Sep 3 14:07:16 2006 @@ -32,7 +32,10 @@ if isinstance(arg, (model.Constant, model.Variable)): real_args.append(arg) else: - arg_example, is_constant = arg + if isinstance(arg, tuple): + arg_example, is_constant = arg + else: + arg_example, is_constant = arg, True if is_constant: real_args.append(model.Constant(arg_example, concretetype=bk.immutablevalue(arg_example))) else: Added: pypy/dist/pypy/translator/transformer/debug.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/transformer/debug.py Sun Sep 3 14:07:16 2006 @@ -0,0 +1,94 @@ + +""" Debug transformer - attach source info to tracebacks generated +out of RPython code +""" + +from pypy.translator import unsimplify, simplify +from pypy.translator.unsimplify import varoftype +from pypy.annotation import model as annmodel +from pypy.objspace.flow import model +from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem import rclass +from pypy.translator.transformer.basictransform import BasicTransformer + +from types import FunctionType, MethodType + +# this is RPython code which handles proper base elements for +# stack tracing +class TracebackHandler(object): + def __init__(self): + self.tb = [] + + def enter(self, tb_str, data): + self.tb.append((tb_str, data)) + + def leave(self, tb_str): + num = len(self.tb) - 1 + while num >= 0: + if self.tb[num][0] == tb_str: + self.tb = self.tb[:num] + num -= 1 + + def traceback(self): + # cut of everything which is from entrypoint + return self.tb + +traceback_handler = TracebackHandler() + +class DebugTransformer(BasicTransformer): + def __init__(self, translator): + BasicTransformer.__init__(self, translator) + bk = self.bookkeeper + self.register_helpers() + self.instance_const = model.Constant(traceback_handler, \ + concretetype=bk.immutablevalue(traceback_handler)) + + def register_helpers(self): + return None + for func_name, func_args in [("traceback", []), + ("enter", ["aa", "aa"]), ("leave", ["aa"])]: + graph = self.flow_method(TracebackHandler, func_name, func_args) + graph.explicit_traceback = True + + def transform_block(self, graph, block): + next = [] + changed = False + for op in block.operations: + # XXX: We need to support indirect calls as well, but + # just need to do it somehow differently + if op.opname == 'simple_call' and \ + isinstance(op.args[0], model.Constant) and \ + isinstance(op.args[0].value, (FunctionType, MethodType)): + # XXX or any other call + opg, v1 = self.genop("getattr", [self.instance_const, 'enter']) + fun_name = op.args[0].value.func_name + data = self.get_info(block, graph, op) + opc, v2 = self.genop("simple_call", [v1, fun_name, data]) + opgl, v3 = self.genop("getattr", [self.instance_const, 'leave']) + oplc, v4 = self.genop("simple_call", [v3, fun_name]) + next += [opg, opc, op, opgl, oplc] + changed = True + #next.append(op) + else: + next.append(op) + block.operations = next + if changed: + self.add_block(graph, block) + + def get_info(self, block, graph, op): + """ Returns as much data as we can from our position + """ + arglist = [] + for arg in op.args[1:]: + if isinstance(arg, model.Constant): + arglist.append(str(arg.value)) + else: + arglist.append(str(arg)) + return "(%s)" % ", ".join(arglist) + + def transform_graph(self, graph): + if getattr(graph, 'explicit_traceback', None): + return + + for block in graph.iterblocks(): + self.transform_block(graph, block) Modified: pypy/dist/pypy/translator/transformer/test/test_basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_basictransform.py Sun Sep 3 14:07:16 2006 @@ -14,12 +14,14 @@ t = TranslationContext() annotator = t.buildannotator() annotator.build_types(fun, annotation) - tran = transformerclass(t) - tran.transform_all() if conftest.option.view: t.view() - + + tran = transformerclass(t) + tran.transform_all() + annotator.simplify() + t.buildrtyper(type_system=type_system).specialize() if conftest.option.view: @@ -77,10 +79,10 @@ class ClassHelper(object): def __init__(self): - self.i = 0 + self.i = 3 def method(self): - self.i = 8 + self.i += 8 helper_instance = ClassHelper() @@ -111,7 +113,7 @@ t = transform_function(HelperTransformer, helper_call_fun) res = interp_fun(t, helper_call_fun) - assert res == 8 + assert res == 11 ##def test_transform(): Added: pypy/dist/pypy/translator/transformer/test/test_debug.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/transformer/test/test_debug.py Sun Sep 3 14:07:16 2006 @@ -0,0 +1,83 @@ + +""" test debug generation transformation +""" + +from pypy.translator.transformer.test.test_basictransform import \ + transform_function, interp_fun +from pypy.translator.transformer.debug import DebugTransformer, traceback_handler + +from pypy.translator.translator import TranslationContext, graphof +from pypy.translator.transformer.basictransform import BasicTransformer +from pypy import conftest +from pypy.rpython import llinterp +from pypy.objspace.flow import model +from pypy.translator.unsimplify import copyvar + +import py +py.test.skip("llinterp does not like my transformations") + +def g(): + pass + +def test_basic_debug(): + def f(): + g() + + def wrapper(): + f() + return traceback_handler.tb + + t = transform_function(DebugTransformer, wrapper, []) + res = interp_fun(t, wrapper) + real_res = [s._items['item0']._str for s in res._list] + assert len(real_res) == 0 + +def test_debug_raising(): + #py.test.skip("llinterp does some strange things with operations order") + def a(): + raise ValueError() + + def b(): + a() + + def c(): + b() + + def wrapper(): + try: + c() + except: + pass + return traceback_handler.tb + + t = transform_function(DebugTransformer, wrapper) + res = interp_fun(t, wrapper) + real_res = [s._items['item0']._str for s in res._list] + assert len(real_res) == 3 + +def test_debug_double_raising(): + py.test.skip("strange llinterp stuff") + def aaa(i): + if i: + raise TypeError() + + def zzz(i): + aaa(i) + + def bbb(i): + try: + zzz(i) + except TypeError: + pass + + def ccc(i): + bbb(i) + + def wrapper(i): + ccc(i) + return traceback_handler.tb + + t = transform_function(DebugTransformer, wrapper, [int]) + res = interp_fun(t, wrapper, [3]) + real_res = [s._items['item0']._str for s in res._list] + assert len(real_res) == 3 From fijal at codespeak.net Sun Sep 3 14:16:43 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 Sep 2006 14:16:43 +0200 (CEST) Subject: [pypy-svn] r31965 - in pypy/dist/pypy/translator/js: . demo/jsdemo modules/test test tools Message-ID: <20060903121643.B158F1005A@code0.codespeak.net> Author: fijal Date: Sun Sep 3 14:16:09 2006 New Revision: 31965 Added: pypy/dist/pypy/translator/js/modules/test/__init__.py (contents, props changed) pypy/dist/pypy/translator/js/test/test_transformer.py (contents, props changed) Modified: pypy/dist/pypy/translator/js/demo/jsdemo/consserv.py pypy/dist/pypy/translator/js/js.py pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/js/modules/test/test_dom.py pypy/dist/pypy/translator/js/test/runtest.py pypy/dist/pypy/translator/js/test/test_seq.py pypy/dist/pypy/translator/js/tools/console.py Log: Added basic support for debug transform, some minor fixes as well. Need to write wrapper around it next. Modified: pypy/dist/pypy/translator/js/demo/jsdemo/consserv.py ============================================================================== --- pypy/dist/pypy/translator/js/demo/jsdemo/consserv.py (original) +++ pypy/dist/pypy/translator/js/demo/jsdemo/consserv.py Sun Sep 3 14:16:09 2006 @@ -36,12 +36,11 @@ def run_command(self, str_to_eval = "aa"): # we need what has changed # we try to run it... - lines = str_to_eval.split("
") for num, line in enumerate(lines): if not line.startswith(" "): lines[num] = " " + line - all_text = "\n".join(["def f():"] + lines[:-1]) + all_text = "\n".join(["def f():"] + lines) print all_text try: exec(all_text) Modified: pypy/dist/pypy/translator/js/js.py ============================================================================== --- pypy/dist/pypy/translator/js/js.py (original) +++ pypy/dist/pypy/translator/js/js.py Sun Sep 3 14:16:09 2006 @@ -34,7 +34,8 @@ return path class JS(GenOO): - def __init__(self, translator, functions=[], stackless=False, compress=False, logging=False): + def __init__(self, translator, functions=[], stackless=False, compress=False, \ + logging=False, use_debug=False): backend_mapping = { 'type_system_class' : JTS, 'opcode_dict' : opcodes, @@ -49,6 +50,7 @@ translator.annotator.bookkeeper.getdesc(f).cachedgraph(None) for f in functions ]) self.translator = translator self.db.translator = translator + self.use_debug = use_debug def gen_pendings(self): while self.db._pending_nodes: Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Sun Sep 3 14:16:09 2006 @@ -5,7 +5,7 @@ #from pypy.translator.js.test.runtest import compile_function #from pypy.translator.translator import TranslationContext -from pypy.translator.driver import TranslationDriver +from pypy.translator.driver import TranslationDriver, _default_options from pypy.translator.js.js import JS from pypy.tool.error import AnnotatorError, FlowingError, debug from pypy.rpython.nonconst import NonConstant @@ -38,7 +38,7 @@ mod = __import__(module_name, None, None, ["Module"]) return rpython2javascript(mod, function_names) -def rpython2javascript(mod, function_names): +def rpython2javascript(mod, function_names, use_debug=True): module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: function_names.append('main') @@ -50,11 +50,12 @@ raise BadSignature("Function %s does not have default arguments" % func_name) source_ssf = "\n".join(["import %s" % module_name, "def some_strange_function_which_will_never_be_called():"] + [" "+\ module_name+"."+fun_name+get_args(mod.__dict__[fun_name]) for fun_name in function_names]) - print source_ssf exec(source_ssf) in globals() #fn = compile_function([mod.__dict__[f_name] for f_name in function_names], [[] for i in function_names]) # now we gonna just cut off not needed function - driver = TranslationDriver() + options = _default_options.copy() + options.debug_transform = use_debug + driver = TranslationDriver(options=options) try: driver.setup(some_strange_function_which_will_never_be_called, [], policy = JsPolicy()) driver.proceed(["compile_js"]) Added: pypy/dist/pypy/translator/js/modules/test/__init__.py ============================================================================== Modified: pypy/dist/pypy/translator/js/modules/test/test_dom.py ============================================================================== --- pypy/dist/pypy/translator/js/modules/test/test_dom.py (original) +++ pypy/dist/pypy/translator/js/modules/test/test_dom.py Sun Sep 3 14:16:09 2006 @@ -9,20 +9,6 @@ from pypy.translator.js import conftest #from pypy.rpython.rjs import jseval -import time - -if not conftest.option.browser: - py.test.skip("Works only in browser (right now?)") - -def test_document_base(): - def f(): - return get_document().getElementById("dupa") - #document.getElementById("dupa").setInnerHTML("

Fire!

") - #return document.getElementById("dupa") - - fn = compile_function(f, [], html = 'html/test.html') - assert fn() == '[object HTMLHeadingElement]' - class Mover(object): def __init__(self, elem): self.x = 0 @@ -54,37 +40,51 @@ def move_it(): movers[0].move_it() #movers[1].move_it() - -def test_anim_f(): - def anim_fun(): - obj = get_document().createElement('img') - obj.id = 'anim_img' - obj.setAttribute('style', 'position:absolute; top:0; left:0;') - obj.src = '/static/gfx/BubBob.gif' - get_document().body.appendChild(obj) - #obj2 = get_document().getElementById("anim_img2") - #obj2.setAttribute('style', 'position: absolute; top: 50; left: 0;') - move_it() - setTimeout(move_it, 10) - return get_document().getElementById("anim_img").style.left - fn = compile_function(anim_fun, [], html = 'html/anim.html') - assert fn() == '3px' - -xml = XMLHttpRequest() - -def t_xml_fun(): - if xml.readyState == 4: - alert('Wow!') +class TestReal(object): + def setup_class(self): + if not conftest.option.browser: + py.test.skip("Works only in browser (right now?)") + + def test_document_base(self): + def f(): + return get_document().getElementById("dupa") + #document.getElementById("dupa").setInnerHTML("

Fire!

") + #return document.getElementById("dupa") + + fn = compile_function(f, [], html = 'html/test.html') + assert fn() == '[object HTMLHeadingElement]' + + def test_anim_f(self): + def anim_fun(): + obj = get_document().createElement('img') + obj.id = 'anim_img' + obj.setAttribute('style', 'position:absolute; top:0; left:0;') + obj.src = '/static/gfx/BubBob.gif' + get_document().body.appendChild(obj) + #obj2 = get_document().getElementById("anim_img2") + #obj2.setAttribute('style', 'position: absolute; top: 50; left: 0;') + move_it() + setTimeout(move_it, 10) + return get_document().getElementById("anim_img").style.left -def test_xmlhttp(): - """ Low level XMLHttpRequest test - """ - def xml_fun(): - xml.open('GET', '/get_some_info?info=dupa', True) - xml.onreadystatechange = t_xml_fun - #return xml.readyState - xml.send(None) + fn = compile_function(anim_fun, [], html = 'html/anim.html') + assert fn() == '3px' + + xml = XMLHttpRequest() - fn = compile_function(xml_fun, []) - fn() + def t_xml_fun(self): + if xml.readyState == 4: + alert('Wow!') + + def test_xmlhttp(self): + """ Low level XMLHttpRequest test + """ + def xml_fun(): + xml.open('GET', '/get_some_info?info=dupa', True) + xml.onreadystatechange = t_xml_fun + #return xml.readyState + xml.send(None) + + fn = compile_function(xml_fun, []) + fn() Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Sun Sep 3 14:16:09 2006 @@ -12,6 +12,7 @@ from pypy.translator.js.log import log from pypy.conftest import option from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin +from pypy.translator.transformer.debug import DebugTransformer log = log.runtest use_browsertest = conftest.option.browser @@ -27,16 +28,18 @@ return True class compile_function(object): - def __init__(self, functions, annotations, stackless=False, view=False, html=None, is_interactive=False, root = None, run_browser = True): + def __init__(self, functions, annotations, stackless=False, view=False, html=None, is_interactive=False, root = None, run_browser = True, debug_transform = False): if not use_browsertest and not _CLI_is_on_path(): py.test.skip('Javascript CLI (js) not found') self.html = html self.is_interactive = is_interactive t = TranslationContext() - t.buildannotator().build_types(functions, annotations) + ann = t.buildannotator() + ann.build_types(functions, annotations) + if debug_transform: + DebugTransformer(t).transform_all() t.buildrtyper(type_system="ootype").specialize() - #print t.rtyper #backend_optimizations(t, raisingop2direct_call_all=True, inline_threshold=0, mallocs=False) #backend_optimizations(t) Modified: pypy/dist/pypy/translator/js/test/test_seq.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_seq.py (original) +++ pypy/dist/pypy/translator/js/test/test_seq.py Sun Sep 3 14:16:09 2006 @@ -76,6 +76,17 @@ for y in c2.keys(): assert fn(x, y) == soph_const(x, y) + def test_dict_iterator(self): + c = {'aa':1, 'bb':2, 'cc':3, 'dd':4} + def dict_iter(): + sum = 0 + for i in c: + sum += c[i] + return sum + + fn = compile_function(dict_iter, []) + assert fn() == dict_iter() + class TestTuple(object): def test_f1(self): f = compile_function(llvmsnippet.tuple_f1, [int]) Added: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Sun Sep 3 14:16:09 2006 @@ -0,0 +1,42 @@ + +""" some javascript transform test examples +""" + +from pypy.translator.js.main import rpython2javascript +from pypy.translator.js.test.runtest import compile_function +from pypy.translator.transformer.debug import traceback_handler + +def test_simple_tansform(): + def g(): + raise ValueError() + + def f(): + g() + + def wrapper(): + try: + # XXX: this is needed to make annotator happy + traceback_handler.enter("entrypoint", "data") + f() + except: + return "|".join([i + ": " + j for i, j in traceback_handler.tb]) + return "" + + fn = compile_function(wrapper, [], debug_transform = True) + retval = fn() + lst = retval.split('|') + assert len(lst) == 3 + assert lst[1] == 'f: ()' + assert lst[2] == 'g: ()' + +def test_simple_seq(): + def fun(i): + if i: + a = [("ab", "cd"), ("ef", "xy")] + else: + a = [("xz", "pr"), ("as", "fg")] + return ",".join(["%s : %s" % (i, j) for i,j in a]) + + fn = compile_function(fun, [int]) + assert fn(0) == fun(0) + assert fn(1) == fun(1) Modified: pypy/dist/pypy/translator/js/tools/console.py ============================================================================== --- pypy/dist/pypy/translator/js/tools/console.py (original) +++ pypy/dist/pypy/translator/js/tools/console.py Sun Sep 3 14:16:09 2006 @@ -45,7 +45,7 @@ console = Console() def comeback(msg): - pass + jseval(msg['source'] + "\nf()") def onchange(key): kc = key.keyCode From arigo at codespeak.net Sun Sep 3 17:47:15 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 17:47:15 +0200 (CEST) Subject: [pypy-svn] r31966 - in pypy/dist/pypy: annotation rpython Message-ID: <20060903154715.CEBF51006C@code0.codespeak.net> Author: arigo Date: Sun Sep 3 17:47:12 2006 New Revision: 31966 Modified: pypy/dist/pypy/annotation/listdef.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rlist.py Log: (pedronis, arigo) Obscure results could be obtained by using mix-level annotators that marked previously-fixed-size lists as variable-sized. The Repr for these lists is of course not updated. Confusion. Instead, fail cleanly. Modified: pypy/dist/pypy/annotation/listdef.py ============================================================================== --- pypy/dist/pypy/annotation/listdef.py (original) +++ pypy/dist/pypy/annotation/listdef.py Sun Sep 3 17:47:12 2006 @@ -3,10 +3,14 @@ from pypy.annotation.model import unionof, TLS, UnionError, isdegenerated +class TooLateForChange(Exception): + pass + class ListItem: mutated = False # True for lists mutated after creation resized = False # True for lists resized after creation range_step = None # the step -- only for lists only created by a range() + dont_change_any_more = False # set to True when too late for changes # what to do if range_step is different in merge. # - if one is a list (range_step is None), unify to a list. @@ -23,15 +27,44 @@ self.itemof = {} # set of all ListDefs using this ListItem self.read_locations = {} + def mutate(self): + if not self.mutated: + if self.dont_change_any_more: + raise TooLateForChange + self.mutated = True + + def resize(self): + if not self.resized: + if self.dont_change_any_more: + raise TooLateForChange + self.resized = True + + def setrangestep(self, step): + if step != self.range_step: + if self.dont_change_any_more: + raise TooLateForChange + self.range_step = step + def merge(self, other): if self is not other: if getattr(TLS, 'no_side_effects_in_union', 0): raise UnionError("merging list/dict items") - self.mutated |= other.mutated - self.resized |= other.resized + + if other.dont_change_any_more: + if self.dont_change_any_more: + raise TooLateForChange + else: + # lists using 'other' don't expect it to change any more, + # so we try merging into 'other', which will give + # TooLateForChange if it actually tries to make + # things more general + self, other = other, self + + if other.mutated: self.mutate() + if other.resized: self.resize() if other.range_step != self.range_step: - self.range_step = self._step_map[type(self.range_step), - type(other.range_step)] + self.setrangestep(self._step_map[type(self.range_step), + type(other.range_step)]) self.itemof.update(other.itemof) read_locations = self.read_locations.copy() other_read_locations = other.read_locations.copy() @@ -43,6 +76,8 @@ if isdegenerated(s_new_value) and self.bookkeeper: self.bookkeeper.ondegenerated(self, s_new_value) if s_new_value != s_value: + if self.dont_change_any_more: + raise TooLateForChange self.s_value = s_new_value # reflow from reading points for position_key in read_locations: @@ -62,6 +97,8 @@ self.bookkeeper.ondegenerated(self, s_new_value) updated = s_new_value != self.s_value if updated: + if self.dont_change_any_more: + raise TooLateForChange self.s_value = s_new_value # reflow from all reading points for position_key in self.read_locations: @@ -128,11 +165,11 @@ return '<[%r]>' % (self.listitem.s_value,) def mutate(self): - self.listitem.mutated = True + self.listitem.mutate() def resize(self): - self.listitem.mutated = True - self.listitem.resized = True + self.listitem.mutate() + self.listitem.resize() MOST_GENERAL_LISTDEF = ListDef(None, SomeObject()) Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sun Sep 3 17:47:12 2006 @@ -39,6 +39,8 @@ custom_eq_hash) def rtyper_makekey(self): + self.dictdef.dictkey .dont_change_any_more = True + self.dictdef.dictvalue.dont_change_any_more = True return (self.__class__, self.dictdef.dictkey, self.dictdef.dictvalue) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Sep 3 17:47:12 2006 @@ -46,6 +46,7 @@ lambda: rtyper.getrepr(listitem.s_value), listitem) def rtyper_makekey(self): + self.listdef.listitem.dont_change_any_more = True return self.__class__, self.listdef.listitem From arigo at codespeak.net Sun Sep 3 20:45:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 20:45:55 +0200 (CEST) Subject: [pypy-svn] r31967 - pypy/dist/pypy/translator/js Message-ID: <20060903184555.0DB641006C@code0.codespeak.net> Author: arigo Date: Sun Sep 3 20:45:54 2006 New Revision: 31967 Modified: pypy/dist/pypy/translator/js/main.py Log: (pedronis, arigo) Uh? That couldn't possibly have worked. Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Sun Sep 3 20:45:54 2006 @@ -5,11 +5,12 @@ #from pypy.translator.js.test.runtest import compile_function #from pypy.translator.translator import TranslationContext -from pypy.translator.driver import TranslationDriver, _default_options +from pypy.translator.driver import TranslationDriver, DEFAULT_OPTIONS from pypy.translator.js.js import JS from pypy.tool.error import AnnotatorError, FlowingError, debug from pypy.rpython.nonconst import NonConstant from pypy.annotation.policy import AnnotatorPolicy +import optparse class FunctionNotFound(Exception): pass @@ -53,7 +54,7 @@ exec(source_ssf) in globals() #fn = compile_function([mod.__dict__[f_name] for f_name in function_names], [[] for i in function_names]) # now we gonna just cut off not needed function - options = _default_options.copy() + options = optparse.Values(defaults=DEFAULT_OPTIONS) options.debug_transform = use_debug driver = TranslationDriver(options=options) try: From arigo at codespeak.net Sun Sep 3 20:49:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 20:49:20 +0200 (CEST) Subject: [pypy-svn] r31968 - pypy/dist/pypy/annotation Message-ID: <20060903184920.E0EEF1006E@code0.codespeak.net> Author: arigo Date: Sun Sep 3 20:49:19 2006 New Revision: 31968 Modified: pypy/dist/pypy/annotation/listdef.py Log: (pedronis, arigo) More on dont_change flags: ListItems with None as a bookkeeper are automatically 'dont_change'. Added keyword args to specify ListDefs that are initialized already in a mutated/resized state. Modified: pypy/dist/pypy/annotation/listdef.py ============================================================================== --- pypy/dist/pypy/annotation/listdef.py (original) +++ pypy/dist/pypy/annotation/listdef.py Sun Sep 3 20:49:19 2006 @@ -26,6 +26,8 @@ self.bookkeeper = bookkeeper self.itemof = {} # set of all ListDefs using this ListItem self.read_locations = {} + if bookkeeper is None: + self.dont_change_any_more = True def mutate(self): if not self.mutated: @@ -73,8 +75,11 @@ s_value = self.s_value s_other_value = other.s_value s_new_value = unionof(s_value, s_other_value) - if isdegenerated(s_new_value) and self.bookkeeper: - self.bookkeeper.ondegenerated(self, s_new_value) + if isdegenerated(s_new_value): + if self.bookkeeper: + self.bookkeeper.ondegenerated(self, s_new_value) + elif other.bookkeeper: + other.bookkeeper.ondegenerated(other, s_new_value) if s_new_value != s_value: if self.dont_change_any_more: raise TooLateForChange @@ -85,7 +90,7 @@ if s_new_value != s_other_value: # reflow from reading points for position_key in other_read_locations: - self.bookkeeper.annotator.reflowfromposition(position_key) + other.bookkeeper.annotator.reflowfromposition(position_key) def patch(self): for listdef in self.itemof: @@ -111,8 +116,11 @@ list have to be. Every list creation makes a new ListDef, and the union of two lists merges the ListItems that each ListDef stores.""" - def __init__(self, bookkeeper, s_item=s_ImpossibleValue): + def __init__(self, bookkeeper, s_item=s_ImpossibleValue, + mutated=False, resized=False): self.listitem = ListItem(bookkeeper, s_item) + self.listitem.mutated = mutated | resized + self.listitem.resized = resized self.listitem.itemof[self] = True self.bookkeeper = bookkeeper @@ -174,5 +182,4 @@ MOST_GENERAL_LISTDEF = ListDef(None, SomeObject()) -s_list_of_strings = SomeList(ListDef(None, SomeString())) -s_list_of_strings.listdef.resize() +s_list_of_strings = SomeList(ListDef(None, SomeString(), resized = True)) From arigo at codespeak.net Sun Sep 3 20:49:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 20:49:57 +0200 (CEST) Subject: [pypy-svn] r31969 - pypy/dist/pypy/translator/test Message-ID: <20060903184957.13F031006E@code0.codespeak.net> Author: arigo Date: Sun Sep 3 20:49:56 2006 New Revision: 31969 Modified: pypy/dist/pypy/translator/test/test_simplify.py Log: Being recalled by pedronis of objspace.flow.model.summary(). Modified: pypy/dist/pypy/translator/test/test_simplify.py ============================================================================== --- pypy/dist/pypy/translator/test/test_simplify.py (original) +++ pypy/dist/pypy/translator/test/test_simplify.py Sun Sep 3 20:49:56 2006 @@ -2,7 +2,7 @@ from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.simplify import get_graph, transform_dead_op_vars -from pypy.objspace.flow.model import traverse, Block +from pypy.objspace.flow.model import traverse, Block, summary from pypy import conftest def translate(func, argtypes, backend_optimize=True): @@ -197,11 +197,7 @@ graph = t.buildflowgraph(f1) if conftest.option.view: graph.show() - insns = {} - for block in graph.iterblocks(): - for op in block.operations: - insns[op.opname] = insns.get(op.opname, 0) + 1 - assert insns == { + assert summary(graph) == { 'iter': 1, 'len': 1, 'newlistbuilder': 1, From arigo at codespeak.net Sun Sep 3 20:50:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 20:50:36 +0200 (CEST) Subject: [pypy-svn] r31970 - pypy/dist/pypy/jit/llabstractinterp/test Message-ID: <20060903185036.735D81006E@code0.codespeak.net> Author: arigo Date: Sun Sep 3 20:50:35 2006 New Revision: 31970 Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py Log: (pedronis, arigo) One day maybe, we'll restore the llabstractinterpreter... Currently it's really not very useful any more. Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py ============================================================================== --- pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py (original) +++ pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py Sun Sep 3 20:50:35 2006 @@ -9,6 +9,9 @@ from pypy.objspace.flow import model as flowmodel from pypy.rpython import objectmodel +# one day maybe +py.test.skip("XXX need to be ported to the newer rgenop interface") + def annotation(a, x): T = lltype.typeOf(x) if T == lltype.Ptr(rstr.STR): From arigo at codespeak.net Sun Sep 3 20:51:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 20:51:10 +0200 (CEST) Subject: [pypy-svn] r31971 - pypy/dist/pypy/jit Message-ID: <20060903185110.2A0471006C@code0.codespeak.net> Author: arigo Date: Sun Sep 3 20:51:07 2006 New Revision: 31971 Modified: pypy/dist/pypy/jit/conftest.py Log: More readable outputs for the --benchmark option to py.test. Modified: pypy/dist/pypy/jit/conftest.py ============================================================================== --- pypy/dist/pypy/jit/conftest.py (original) +++ pypy/dist/pypy/jit/conftest.py Sun Sep 3 20:51:07 2006 @@ -60,5 +60,13 @@ prefix = self.name if prefix: prefix += ': ' - os.write(1, '{%s%f iterations/second}\n' % (prefix, - iterations / elapsed)) + result = iterations / elapsed + if result <= 1000: + s = '%f' % result + else: + s = '%d' % int(result) + i = len(s)-3 + while i > 0: + s = s[:i] + "'" + s[i:] + i -= 3 + os.write(1, '{%s%s iterations/second}\n' % (prefix, s)) From arigo at codespeak.net Sun Sep 3 20:59:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Sep 2006 20:59:51 +0200 (CEST) Subject: [pypy-svn] r31972 - in pypy/dist/pypy/jit: codegen codegen/i386 codegen/i386/test codegen/llgraph timeshifter timeshifter/test Message-ID: <20060903185951.1E00A1006C@code0.codespeak.net> Author: arigo Date: Sun Sep 3 20:59:48 2006 New Revision: 31972 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py pypy/dist/pypy/jit/codegen/llgraph/llimpl.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/model.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/jit/timeshifter/vlist.py Log: (pedronis, arigo) Big Diff Of The Day. The rgenop interface is getting in a nice shape: no more links, and no more geninputarg(). Back-end friendly. ri386genop produces code that is a bit more reasonable now (e.g. it's no longer 95% moves)... Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Sun Sep 3 20:59:48 2006 @@ -1,7 +1,7 @@ from pypy.rpython.objectmodel import specialize from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.i386.ri386 import * -from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink +from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator from pypy.jit.codegen.model import GenVar, GenConst from pypy.rpython import objectmodel from pypy.rpython.annlowlevel import llhelper @@ -12,19 +12,22 @@ class Var(GenVar): def __init__(self, stackpos): - # 'stackpos' is an index relative to the pushed arguments: - # 0 = 1st arg, - # 1 = 2nd arg, - # ... - # return address, - # local var, ... + # 'stackpos' is an index relative to the pushed arguments + # (where N is the number of arguments of the function): + # + # 0 = last arg + # = ... + # N-1 = 1st arg + # N = return address + # N+1 = local var + # N+2 = ... # ... <--- esp+4 # local var <--- esp # self.stackpos = stackpos - def operand(self, block): - return block.stack_access(self.stackpos) + def operand(self, builder): + return builder.stack_access(self.stackpos) def __repr__(self): return 'var@%d' % (self.stackpos,) @@ -60,7 +63,7 @@ def __init__(self, value): self.value = value - def operand(self, block): + def operand(self, builder): return imm(self.value) @specialize.arg(1) @@ -88,7 +91,7 @@ def __init__(self, addr): self.addr = addr - def operand(self, block): + def operand(self, builder): return imm(llmemory.cast_adr_to_int(self.addr)) @specialize.arg(1) @@ -107,23 +110,31 @@ class Block(CodeGenBlock): - def __init__(self, rgenop, mc): + + def __init__(self, startaddr, arg_positions, stackdepth): + self.startaddr = startaddr + self.arg_positions = arg_positions + self.stackdepth = stackdepth + + +class Builder(CodeGenerator): + + def __init__(self, rgenop, mc, stackdepth): self.rgenop = rgenop - self.argcount = 0 - self.stackdepth = 0 + self.stackdepth = stackdepth self.mc = mc - self.startaddr = mc.tell() - self.fixedposition = False - def getstartaddr(self): - self.fixedposition = True - return self.startaddr - - def geninputarg(self, kind): - res = Var(self.argcount) - self.argcount += 1 - self.stackdepth += 1 - return res + def _write_prologue(self, sigtoken): + numargs = sigtoken # for now + #self.mc.BREAKPOINT() + return [Var(pos) for pos in range(numargs-1, -1, -1)] + + def _close(self): + self.rgenop.close_mc(self.mc) + self.mc = None + + def _fork(self): + return self.rgenop.openbuilder(self.stackdepth) @specialize.arg(1) def genop1(self, opname, gv_arg): @@ -194,16 +205,44 @@ else: return gv_x - def close1(self): - return Link(self) + def enter_next_block(self, kinds, args_gv): + arg_positions = [] + seen = {} + for i in range(len(args_gv)): + gv = args_gv[i] + # turn constants into variables; also make copies of vars that + # are duplicate in args_gv + if not isinstance(gv, Var) or gv.stackpos in seen: + gv = args_gv[i] = self.returnvar(gv.operand(self)) + # remember the var's position in the stack + arg_positions.append(gv.stackpos) + seen[gv.stackpos] = None + return Block(self.mc.tell(), arg_positions, self.stackdepth) + + def jump_if_false(self, gv_condition): + targetbuilder = self._fork() + self.mc.CMP(gv_condition.operand(self), imm8(0)) + self.mc.JE(rel32(targetbuilder.mc.tell())) + return targetbuilder - def close2(self, gv_condition): - false_block = self.rgenop.newblock() - false_block.stackdepth = self.stackdepth - # XXX what if gv_condition is a Const? + def jump_if_true(self, gv_condition): + targetbuilder = self._fork() self.mc.CMP(gv_condition.operand(self), imm8(0)) - self.mc.JE(rel32(false_block.getstartaddr())) - return Link(false_block), Link(self) + self.mc.JNE(rel32(targetbuilder.mc.tell())) + return targetbuilder + + def finish_and_return(self, sigtoken, gv_returnvar): + numargs = sigtoken # for now + initialstackdepth = numargs + 1 + self.mc.MOV(eax, gv_returnvar.operand(self)) + self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) + self.mc.RET() + self._close() + + def finish_and_goto(self, outputargs_gv, targetblock): + remap_stack_layout(self, outputargs_gv, targetblock) + self.mc.JMP(rel32(targetblock.startaddr)) + self._close() # ____________________________________________________________ @@ -357,78 +396,74 @@ # ____________________________________________________________ -class Link(CodeGenLink): - - def __init__(self, prevblock): - self.prevblock = prevblock - - def closereturn(self, gv_result): - block = self.prevblock - block.mc.MOV(eax, gv_result.operand(block)) - block.mc.ADD(esp, imm(WORD * block.stackdepth)) - block.mc.RET() - block.rgenop.close_mc(block.mc) - - def close(self, outputargs_gv, targetblock): - block = self.prevblock - N = len(outputargs_gv) - if block.stackdepth < N: - block.mc.SUB(esp, imm(WORD * (N - block.stackdepth))) - block.stackdepth = N +def remap_stack_layout(builder, outputargs_gv, targetblock): + N = targetblock.stackdepth + if builder.stackdepth < N: + builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth))) + builder.stackdepth = N + + M = len(outputargs_gv) + arg_positions = targetblock.arg_positions + assert M == len(arg_positions) + targetlayout = [None] * N + srccount = [-N] * N + for i in range(M): + pos = arg_positions[i] + gv = outputargs_gv[i] + assert targetlayout[pos] is None + targetlayout[pos] = gv + srccount[pos] = 0 + pending_dests = M + for i in range(M): + gv = outputargs_gv[i] + if isinstance(gv, Var): + p = gv.stackpos + if 0 <= p < N: + if p == i: + srccount[p] = -N # ignore 'v=v' + pending_dests -= 1 + else: + srccount[p] += 1 - pending_dests = N - srccount = [0] * N + while pending_dests: + progress = False for i in range(N): - gv = outputargs_gv[i] - if isinstance(gv, Var): - p = gv.stackpos - if 0 <= p < N: - if p == i: - srccount[p] = -N # ignore 'v=v' - pending_dests -= 1 - else: - srccount[p] += 1 - - while pending_dests: - progress = False + if srccount[i] == 0: + srccount[i] = -1 + pending_dests -= 1 + gv_src = targetlayout[i] + if isinstance(gv_src, Var): + p = gv_src.stackpos + if 0 <= p < N: + srccount[p] -= 1 + builder.mc.MOV(eax, gv_src.operand(builder)) + builder.mc.MOV(builder.stack_access(i), eax) + progress = True + if not progress: + # we are left with only pure disjoint cycles; break them for i in range(N): - if srccount[i] == 0: - srccount[i] = -1 - pending_dests -= 1 - gv_src = outputargs_gv[i] - if isinstance(gv_src, Var): - p = gv_src.stackpos - if 0 <= p < N: - srccount[p] -= 1 - block.mc.MOV(eax, gv_src.operand(block)) - block.mc.MOV(block.stack_access(i), eax) - progress = True - if not progress: - # we are left with only pure disjoint cycles; break them - for i in range(N): - if srccount[i] >= 0: - dst = i - block.mc.MOV(edx, block.stack_access(dst)) - while True: - assert srccount[dst] == 1 - srccount[dst] = -1 - pending_dests -= 1 - gv_src = outputargs_gv[dst] - assert isinstance(gv_src, Var) - src = gv_src.stackpos - assert 0 <= src < N - if src == i: - break - block.mc.MOV(eax, block.stack_access(src)) - block.mc.MOV(block.stack_access(dst), eax) - dst = src - block.mc.MOV(block.stack_access(dst), edx) - assert pending_dests == 0 - - if block.stackdepth > N: - block.mc.ADD(esp, imm(WORD * (block.stackdepth - N))) - block.stackdepth = N - block.rgenop.close_mc_and_jump(block.mc, targetblock) + if srccount[i] >= 0: + dst = i + builder.mc.MOV(edx, builder.stack_access(dst)) + while True: + assert srccount[dst] == 1 + srccount[dst] = -1 + pending_dests -= 1 + gv_src = targetlayout[dst] + assert isinstance(gv_src, Var) + src = gv_src.stackpos + assert 0 <= src < N + if src == i: + break + builder.mc.MOV(eax, builder.stack_access(src)) + builder.mc.MOV(builder.stack_access(dst), eax) + dst = src + builder.mc.MOV(builder.stack_access(dst), edx) + assert pending_dests == 0 + + if builder.stackdepth > N: + builder.mc.ADD(esp, imm(WORD * (builder.stackdepth - N))) + builder.stackdepth = N class RI386GenOp(AbstractRGenOp): @@ -447,20 +482,16 @@ def close_mc(self, mc): self.mcs.append(mc) - def close_mc_and_jump(self, mc, targetblock): - if (targetblock.fixedposition - or targetblock.mc.tell() != targetblock.startaddr): - mc.JMP(rel32(targetblock.getstartaddr())) - self.close_mc(mc) - else: - # bring the targetblock here, instead of jumping to it - self.close_mc(targetblock.mc) - targetblock.mc = mc - targetblock.startaddr = mc.tell() - targetblock.fixedposition = True + def openbuilder(self, stackdepth): + return Builder(self, self.open_mc(), stackdepth) - def newblock(self): - return Block(self, self.open_mc()) + def newgraph(self, sigtoken): + numargs = sigtoken # for now + initialstackdepth = numargs+1 + builder = self.openbuilder(initialstackdepth) + entrypoint = builder.mc.tell() + inputargs_gv = builder._write_prologue(sigtoken) + return builder, entrypoint, inputargs_gv @staticmethod @specialize.genconst(0) @@ -500,18 +531,10 @@ @staticmethod @specialize.memo() def sigToken(FUNCTYPE): - return None # for now + return len(FUNCTYPE.ARGS) # for now constPrebuiltGlobal = genconst - def gencallableconst(self, sigtoken, name, block): - prologue = self.newblock() - #prologue.mc.BREAKPOINT() - # re-push the arguments so that they are after the return value - # and in the correct order - for i in range(block.argcount): - operand = mem(esp, WORD * (2*i+1)) - prologue.mc.PUSH(operand) - self.close_mc_and_jump(prologue.mc, block) - return IntConst(prologue.getstartaddr()) + def gencallableconst(self, sigtoken, name, entrypointaddr): + return IntConst(entrypointaddr) Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py Sun Sep 3 20:59:48 2006 @@ -15,15 +15,11 @@ def make_adder(rgenop, n): # 'return x+n' - signed_kind = rgenop.kindToken(lltype.Signed) - block = rgenop.newblock() - gv_x = block.geninputarg(signed_kind) - gv_result = block.genop2("int_add", gv_x, rgenop.genconst(n)) - link = block.close1() - link.closereturn(gv_result) - sigtoken = rgenop.sigToken(FUNC) - gv_add_one = rgenop.gencallableconst(sigtoken, "adder", block) + builder, entrypoint, [gv_x] = rgenop.newgraph(sigtoken) + gv_result = builder.genop2("int_add", gv_x, rgenop.genconst(n)) + builder.finish_and_return(sigtoken, gv_result) + gv_add_one = rgenop.gencallableconst(sigtoken, "adder", entrypoint) return gv_add_one def runner(x, y): @@ -62,25 +58,19 @@ def make_dummy(rgenop): # 'return x - (y - (x-1))' signed_kind = rgenop.kindToken(lltype.Signed) - block = rgenop.newblock() - gv_x = block.geninputarg(signed_kind) - gv_y = block.geninputarg(signed_kind) - gv_z = block.genop2("int_sub", gv_x, rgenop.genconst(1)) - link = block.close1() - - block2 = rgenop.newblock() - gv_y2 = block2.geninputarg(signed_kind) - gv_z2 = block2.geninputarg(signed_kind) - gv_x2 = block2.geninputarg(signed_kind) - link.close([gv_y, gv_z, gv_x], block2) - - gv_s2 = block2.genop2("int_sub", gv_y2, gv_z2) - gv_t2 = block2.genop2("int_sub", gv_x2, gv_s2) - link2 = block2.close1() - - link2.closereturn(gv_t2) sigtoken = rgenop.sigToken(FUNC2) - gv_dummyfn = rgenop.gencallableconst(sigtoken, "dummy", block) + builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken) + gv_z = builder.genop2("int_sub", gv_x, rgenop.genconst(1)) + + args_gv = [gv_y, gv_z, gv_x] + builder.enter_next_block([signed_kind, signed_kind, signed_kind], args_gv) + [gv_y2, gv_z2, gv_x2] = args_gv + + gv_s2 = builder.genop2("int_sub", gv_y2, gv_z2) + gv_t2 = builder.genop2("int_sub", gv_x2, gv_s2) + builder.finish_and_return(sigtoken, gv_t2) + + gv_dummyfn = rgenop.gencallableconst(sigtoken, "dummy", entrypoint) return gv_dummyfn def dummy_runner(x, y): @@ -118,27 +108,25 @@ # 'if x > 5: return x-1 # else: return y' signed_kind = rgenop.kindToken(lltype.Signed) - block = rgenop.newblock() - gv_x = block.geninputarg(signed_kind) - gv_y = block.geninputarg(signed_kind) - gv_cond = block.genop2("int_gt", gv_x, rgenop.genconst(5)) - link_false, link_true = block.close2(gv_cond) - - block2 = rgenop.newblock() - gv_one = block2.geninputarg(signed_kind) - gv_x2 = block2.geninputarg(signed_kind) - gv_y2 = block2.geninputarg(signed_kind) - link_true.close([rgenop.genconst(1), gv_x, gv_y], block2) - - gv_s2 = block2.genop2("int_sub", gv_x2, gv_one) - link2 = block2.close1() - link2.closereturn(gv_s2) + sigtoken = rgenop.sigToken(FUNC2) + builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken) + gv_cond = builder.genop2("int_gt", gv_x, rgenop.genconst(5)) + false_builder = builder.jump_if_false(gv_cond) + + # true path + args_gv = [rgenop.genconst(1), gv_x, gv_y] + builder.enter_next_block([signed_kind, signed_kind, signed_kind], args_gv) + [gv_one, gv_x2, gv_y2] = args_gv - link_false.closereturn(gv_y) + gv_s2 = builder.genop2("int_sub", gv_x2, gv_one) + builder.finish_and_return(sigtoken, gv_s2) - sigtoken = rgenop.sigToken(FUNC2) + # false path + false_builder.finish_and_return(sigtoken, gv_y) + + # done gv_branchingfn = rgenop.gencallableconst(sigtoken, - "branching", block) + "branching", entrypoint) return gv_branchingfn def branching_runner(x, y): @@ -175,3 +163,71 @@ assert res == 29 res = fn(3, 17) assert res == 17 + +# ____________________________________________________________ + +def make_goto(rgenop): + # while x > 0: + # y += x + # x -= 1 + # return y + signed_kind = rgenop.kindToken(lltype.Signed) + sigtoken = rgenop.sigToken(FUNC2) + builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken) + + # loop start block + args_gv = [gv_x, gv_y] + loopblock = builder.enter_next_block([signed_kind, signed_kind], args_gv) + [gv_x, gv_y] = args_gv + + gv_cond = builder.genop2("int_gt", gv_x, rgenop.genconst(0)) + bodybuilder = builder.jump_if_true(gv_cond) + builder.finish_and_return(sigtoken, gv_y) + + # loop body + args_gv = [gv_y, gv_x] + bodybuilder.enter_next_block([signed_kind, signed_kind], args_gv) + [gv_y, gv_x] = args_gv + + gv_y2 = bodybuilder.genop2("int_add", gv_x, gv_y) + gv_x2 = bodybuilder.genop2("int_sub", gv_x, rgenop.genconst(1)) + bodybuilder.finish_and_goto([gv_x2, gv_y2], loopblock) + + # done + gv_gotofn = rgenop.gencallableconst(sigtoken, "goto", entrypoint) + return gv_gotofn + +def goto_runner(x, y): + rgenop = RI386GenOp() + gv_gotofn = make_goto(rgenop) + gotofn = gv_gotofn.revealconst(lltype.Ptr(FUNC2)) + res = gotofn(x, y) + keepalive_until_here(rgenop) # to keep the code blocks alive + return res + +def test_goto_interpret(): + from pypy.jit.codegen.llgraph.rgenop import rgenop + gv_gotofn = make_goto(rgenop) + gotofn = gv_gotofn.revealconst(lltype.Ptr(FUNC2)) + llinterp = LLInterpreter(None) + res = llinterp.eval_graph(gotofn._obj.graph, [30, 17]) + assert res == 31 * 15 + 17 + res = llinterp.eval_graph(gotofn._obj.graph, [3, 17]) + assert res == 23 + +def test_goto_direct(): + rgenop = RI386GenOp() + gv_gotofn = make_goto(rgenop) + print gv_gotofn.value + fnptr = cast(c_void_p(gv_gotofn.value), CFUNCTYPE(c_int, c_int, c_int)) + res = fnptr(30, 17) # <== the segfault is here + assert res == 31 * 15 + 17 + res = fnptr(3, 17) # <== or here + assert res == 23 + +def test_goto_compile(): + fn = compile(goto_runner, [int, int], annotatorpolicy=GENOP_POLICY) + res = fn(30, 17) + assert res == 31 * 15 + 17 + res = fn(3, 17) + assert res == 23 Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Sun Sep 3 20:59:48 2006 @@ -215,6 +215,7 @@ def _closelink(link, vars, targetblock): if isinstance(link, flowmodel.Link): + assert link.target is None # link already closed blockvars = dict.fromkeys(link.prevblock.getvariables()) for v in vars: if isinstance(v, flowmodel.Variable): Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Sun Sep 3 20:59:48 2006 @@ -1,6 +1,6 @@ from pypy.rpython.objectmodel import specialize from pypy.rpython.lltypesystem import lltype -from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink +from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator from pypy.jit.codegen.model import GenVar, GenConst from pypy.jit.codegen.llgraph import llimpl from pypy.rpython.lltypesystem.rclass import fishllattr @@ -33,13 +33,11 @@ def __init__(self, b): self.b = b - def geninputarg(self, gv_TYPE): - return LLVar(llimpl.geninputarg(self.b, gv_TYPE.v)) +class LLBuilder(CodeGenerator): + lnk = llimpl.nulllink -## @specialize.arg(1) -## def genop(self, opname, vars_gv, gv_RESULT_TYPE=None): -## return LLVar(llimpl.genop(self.b, opname, vars_gv, -## (gv_RESULT_TYPE or gv_Void).v)) + def __init__(self): + self.rgenop = rgenop @specialize.arg(1) def genop1(self, opname, gv_arg): @@ -100,36 +98,59 @@ def genop_same_as(self, gv_TYPE, gv_value): return LLVar(gv_value.v) - def close1(self): - return LLLink(llimpl.closeblock1(self.b)) - - def close2(self, gv_exitswitch): - l1, l2 = llimpl.closeblock2(self.b, gv_exitswitch.v) - return LLLink(l1), LLLink(l2) - - -class LLLink(CodeGenLink): - def __init__(self, l): - self.l = l - - def close(self, vars_gv, targetblock): - llimpl.closelink(self.l, vars_gv, targetblock.b) - - def closereturn(self, gv_returnvar): - llimpl.closereturnlink(self.l, + def _newblock(self, kinds): + self.b = newb = llimpl.newblock() + return [LLVar(llimpl.geninputarg(newb, kind.v)) for kind in kinds] + + def enter_next_block(self, kinds, args_gv): + lnk = self.lnk or llimpl.closeblock1(self.b) + self.lnk = llimpl.nulllink + newb_args_gv = self._newblock(kinds) + llimpl.closelink(lnk, args_gv, self.b) + for i in range(len(args_gv)): + args_gv[i] = newb_args_gv[i] + return LLBlock(self.b) + + def finish_and_goto(self, args_gv, targetblock): + lnk = self.lnk or llimpl.closeblock1(self.b) + self.lnk = llimpl.nulllink + llimpl.closelink(lnk, args_gv, targetblock.b) + + def finish_and_return(self, sigtoken, gv_returnvar): + lnk = self.lnk or llimpl.closeblock1(self.b) + self.lnk = llimpl.nulllink + llimpl.closereturnlink(lnk, (gv_returnvar or gv_dummy_placeholder).v) + def jump_if_true(self, gv_cond): + l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) + self.b = llimpl.nullblock + later_builder = LLBuilder() + later_builder.lnk = l_true + self.lnk = l_false + return later_builder + + def jump_if_false(self, gv_cond): + l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) + self.b = llimpl.nullblock + later_builder = LLBuilder() + later_builder.lnk = l_false + self.lnk = l_true + return later_builder + class RGenOp(AbstractRGenOp): gv_Void = gv_Void - def newblock(self): - return LLBlock(llimpl.newblock()) - # XXX what kind of type/kind information does this need? + def newgraph(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE)): + builder = LLBuilder() + inputargs_gv = builder._newblock(ARGS_gv) + return builder, LLBlock(builder.b), inputargs_gv + def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, - targetblock): - return LLConst(llimpl.gencallableconst(name, targetblock.b, + entrypoint): + return LLConst(llimpl.gencallableconst(name, entrypoint.b, gv_FUNCTYPE.v)) @staticmethod Modified: pypy/dist/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/dist/pypy/jit/codegen/model.py Sun Sep 3 20:59:48 2006 @@ -10,10 +10,10 @@ is_const = True -class CodeGenBlock(object): +class CodeGenerator(object): pass -class CodeGenLink(object): +class CodeGenBlock(object): pass Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Sun Sep 3 20:59:48 2006 @@ -170,12 +170,12 @@ for desc in typedesc.fielddescs] #self.ownbox = ... set in ll_factory() - def enter_block(self, newblock, incoming, memo): + def enter_block(self, incoming, memo): contmemo = memo.containers if self not in contmemo: contmemo[self] = None for box in self.content_boxes: - box.enter_block(newblock, incoming, memo) + box.enter_block(incoming, memo) def force_runtime_container(self, builder): typedesc = self.typedesc Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Sun Sep 3 20:59:48 2006 @@ -139,11 +139,10 @@ # ____________________________________________________________ # other jitstate/graph level operations -def enter_graph(builder, backstate=None): - return builder.build_jitstate(backstate) +def enter_graph(backstate): + return JITState(backstate.curbuilder, backstate) def start_new_block(states_dic, jitstate, key, redboxes): - rgenop = jitstate.rgenop memo = rvalue.freeze_memo() frozens = [redbox.freeze(memo) for redbox in redboxes] memo = rvalue.exactmatch_memo() @@ -151,13 +150,16 @@ for i in range(len(redboxes)): res = frozens[i].exactmatch(redboxes[i], outgoingvarboxes, memo) assert res, "exactmatch() failed" - newblock = rgenop.newblock() linkargs = [] - for box in outgoingvarboxes: - linkargs.append(box.getgenvar(None)) - box.genvar = newblock.geninputarg(box.kind) - jitstate.curbuilder.enter_block(linkargs, newblock) + kinds = [] + for box in outgoingvarboxes: # all variables + linkargs.append(box.genvar) + kinds.append(box.kind) + newblock = jitstate.curbuilder.enter_next_block(kinds, linkargs) states_dic[key] = frozens, newblock + for i in range(len(outgoingvarboxes)): + box = outgoingvarboxes[i] + box.genvar = linkargs[i] return jitstate start_new_block._annspecialcase_ = "specialize:arglltype(2)" @@ -178,18 +180,15 @@ exactmatch = False if exactmatch: - jitstate = dyn_enter_block(jitstate, outgoingvarboxes) linkargs = [] for box in outgoingvarboxes: linkargs.append(box.getgenvar(jitstate.curbuilder)) - jitstate.curbuilder.leave_block() jitstate.curbuilder.finish_and_goto(linkargs, oldblock) return None # We need a more general block. Do it by generalizing all the # redboxes from outgoingvarboxes, by making them variables. # Then we make a new block based on this new state. - jitstate = dyn_enter_block(jitstate, outgoingvarboxes) replace_memo = rvalue.copy_memo() for box in outgoingvarboxes: box = box.forcevar(jitstate.curbuilder, replace_memo) @@ -197,54 +196,45 @@ for i in range(len(mylocalredboxes)): newbox = redboxes[i].replace(replace_memo) mylocalredboxes[i] = redboxes[i] = newbox - jitstate.curbuilder.leave_block() return start_new_block(states_dic, jitstate, key, redboxes) retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)" def enter_block(jitstate, redboxes): # 'redboxes' is a fixed-size list (s_box_list) of the current red boxes - rgenop = jitstate.rgenop - newblock = rgenop.newblock() - incoming = [] - memo = rvalue.enter_block_memo() - for redbox in redboxes: - redbox.enter_block(newblock, incoming, memo) - js = jitstate.backstate - while js is not None: - lrb = js.localredboxes - assert lrb is not None - for redbox in lrb: - redbox.enter_block(newblock, incoming, memo) - js = js.backstate - jitstate.curbuilder.enter_block(incoming, newblock) - return jitstate - -def dyn_enter_block(jitstate, redboxes): - # 'redboxes' is a var-sized list (s_box_accum) of *all* the boxes - # including the ones from the callers' locals - rgenop = jitstate.rgenop - newblock = rgenop.newblock() incoming = [] memo = rvalue.enter_block_memo() for redbox in redboxes: - redbox.enter_block(newblock, incoming, memo) - jitstate.curbuilder.enter_block(incoming, newblock) - return jitstate - -def leave_block(jitstate): - jitstate.curbuilder.leave_block() - return jitstate + redbox.enter_block(incoming, memo) +## XXX +## js = jitstate.backstate +## while js is not None: +## lrb = js.localredboxes +## assert lrb is not None +## for redbox in lrb: +## redbox.enter_block(incoming, memo) +## js = js.backstate + linkargs = [] + kinds = [] + for redbox in incoming: # all variables + linkargs.append(redbox.genvar) + kinds.append(redbox.kind) + jitstate.curbuilder.enter_next_block(kinds, linkargs) + for i in range(len(incoming)): + incoming[i].genvar = linkargs[i] -def leave_block_split(jitstate, switchredbox, exitindex, redboxes): +def leave_block_split(jitstate, switchredbox, exitindex, + redboxes_true, redboxes_false): if switchredbox.is_constant(): - jitstate.curbuilder.leave_block() return rvalue.ll_getvalue(switchredbox, lltype.Bool) else: exitgvar = switchredbox.getgenvar(jitstate.curbuilder) - later_builder = jitstate.curbuilder.leave_block_split(exitgvar) + later_builder = jitstate.curbuilder.jump_if_false(exitgvar) memo = rvalue.copy_memo() - redboxcopies = [redbox.copy(memo) for redbox in redboxes] + redboxcopies = [None] * len(redboxes_false) + for i in range(len(redboxes_false)): + redboxcopies[i] = redboxes_false[i].copy(memo) jitstate.split_queue.append((exitindex, later_builder, redboxcopies)) + enter_block(jitstate, redboxes_true) return True def dispatch_next(jitstate, outredboxes): @@ -252,6 +242,7 @@ if split_queue: exitindex, later_builder, redboxes = split_queue.pop() jitstate.curbuilder = later_builder + enter_block(jitstate, redboxes) for box in redboxes: outredboxes.append(box) return exitindex @@ -263,15 +254,13 @@ def prepare_return(jitstate, cache, return_type): for builder, retbox in jitstate.return_queue[:-1]: - builder.leave_block() jitstate.curbuilder = builder - retrieve_jitstate_for_merge(cache, jitstate, (), [retbox]) + res = retrieve_jitstate_for_merge(cache, jitstate, (), [retbox]) + assert res is None frozens, block = cache[()] - _, returnbox = jitstate.return_queue[-1] - rgenop = jitstate.rgenop - builder = ResidualGraphBuilder(rgenop, block) - builder.valuebox = returnbox - return builder + builder, returnbox = jitstate.return_queue[-1] + jitstate.backstate.curbuilder = builder + return returnbox def ll_gvar_from_redbox(jitstate, redbox): return redbox.getgenvar(jitstate.curbuilder) @@ -282,125 +271,11 @@ def save_locals(jitstate, redboxes): jitstate.localredboxes = redboxes -def before_call(jitstate): - leave_block(jitstate) - return jitstate.curbuilder - -def after_call(jitstate, newbuilder): - jitstate.curbuilder = newbuilder - return newbuilder.valuebox - # ____________________________________________________________ -class ResidualGraphBuilder(object): - def __init__(self, rgenop, block=None, link=None): - self.rgenop = rgenop - self.block = block - self.outgoinglink = link - self.valuebox = None - - def genconst(self, llvalue): - return self.rgenop.genconst(llvalue) - genconst._annspecialcase_ = 'specialize:genconst(1)' - -## def genvoidconst(self, dummy): -## return self.rgenop.placeholder(dummy) -## genvoidconst._annspecialcase_ = 'specialize:arg(1)' - -## def genop(self, opname, args_gv, result_kind=None): -## return self.block.genop(opname, args_gv, result_kind) -## genop._annspecialcase_ = 'specialize:arg(1)' - - def genop1(self, opname, gv_arg): - return self.block.genop1(opname, gv_arg) - genop1._annspecialcase_ = 'specialize:arg(1)' - - def genop2(self, opname, gv_arg1, gv_arg2): - return self.block.genop2(opname, gv_arg1, gv_arg2) - genop2._annspecialcase_ = 'specialize:arg(1)' - - def genop_call(self, sigtoken, gv_callable, args_gv): - return self.block.genop_call(sigtoken, gv_callable, args_gv) - - def genop_getfield(self, fieldtoken, gv_ptr): - return self.block.genop_getfield(fieldtoken, gv_ptr) - - def genop_setfield(self, fieldtoken, gv_ptr, gv_value): - return self.block.genop_setfield(fieldtoken, gv_ptr, gv_value) - - def genop_getsubstruct(self, fieldtoken, gv_ptr): - return self.block.genop_getsubstruct(fieldtoken, gv_ptr) - - def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): - return self.block.genop_getarrayitem(arraytoken, gv_ptr, gv_index) - - def genop_getarraysize(self, arraytoken, gv_ptr): - return self.block.genop_getarraysize(arraytoken, gv_ptr) - - def genop_malloc_fixedsize(self, alloctoken): - return self.block.genop_malloc_fixedsize(alloctoken) - - def genop_same_as(self, kind, gv_value): - return self.block.genop_same_as(kind, gv_value) - - def constTYPE(self, T): - return self.rgenop.constTYPE(T) - constTYPE._annspecialcase_ = 'specialize:arg(1)' - - def build_jitstate(self, backstate=None): - return JITState(self, backstate) - - def enter_block(self, linkargs, newblock): - self.outgoinglink.close(linkargs, newblock) - self.block = newblock - self.outgoinglink = None - - def leave_block(self): - self.outgoinglink = self.block.close1() - - def leave_block_split(self, exitgvar): - false_link, true_link = self.block.close2(exitgvar) - later_builder = ResidualGraphBuilder(self.rgenop, link=false_link) - self.outgoinglink = true_link - return later_builder - - def finish_and_goto(self, linkargs, targetblock): - self.outgoinglink.close(linkargs, targetblock) - self.outgoinglink = None - - def finish_and_return(self): - gv_retval = self.valuebox.getgenvar(self) - returnlink = self.block.close1() - returnlink.closereturn(gv_retval) - -def make_builder(rgenop): - return ResidualGraphBuilder(rgenop, rgenop.newblock()) - -def ll_int_box(kind, gv): - return rvalue.IntRedBox(kind, gv) - -def ll_double_box(kind, gv): - return rvalue.DoubleRedBox(kind, gv) - -def ll_addr_box(kind, gv): - return rvalue.PtrRedBox(kind, gv) - -def ll_geninputarg(builder, kind): - return builder.block.geninputarg(kind) - -def ll_end_setup_builder(builder): - builder.leave_block() - return builder.block - -def ll_close_builder(builder): - builder.finish_and_return() - -def ll_gencallableconst(builder, name, startblock, gv_functype): - return builder.rgenop.gencallableconst(name, startblock, gv_functype) - class JITState(object): # XXX obscure interface - localredboxes = None + localredboxes = [] def __init__(self, builder, backstate=None): self.split_queue = [] Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sun Sep 3 20:59:48 2006 @@ -242,34 +242,24 @@ return v else: bk = self.annotator.bookkeeper - # first close the current block ts = self.timeshifter v_jitstate = hop.llops.getjitstate() - v_builder = hop.llops.genmixlevelhelpercall(rtimeshift.before_call, - [ts.s_JITState], - [v_jitstate], - ts.s_ResidualGraphBuilder) hop.r_s_popfirstarg() args_hs = hop.args_s[:] # fixed is always false here graph = bk.get_graph_for_call(fnobj.graph, False, args_hs) args_r = [self.getrepr(hs) for hs in args_hs] args_v = hop.inputargs(*args_r) - ARGS = [ts.r_ResidualGraphBuilder.lowleveltype, - ts.r_JITState.lowleveltype] + ARGS = [ts.r_JITState.lowleveltype] ARGS += [r.lowleveltype for r in args_r] - RESULT = ts.r_ResidualGraphBuilder.lowleveltype + RESULT = ts.r_RedBox.lowleveltype fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), graph.name, graph=graph, _callable = graph.func) self.timeshifter.schedule_graph(graph) - args_v[:0] = [hop.llops.genconst(fnptr), v_builder, v_jitstate] - v_newbuilder = hop.genop('direct_call', args_v, RESULT) - return hop.llops.genmixlevelhelpercall(rtimeshift.after_call, - [ts.s_JITState, ts.s_ResidualGraphBuilder], - [v_jitstate, v_newbuilder], - ts.s_RedBox) + args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate] + return hop.genop('direct_call', args_v, RESULT) def translate_op_save_locals(self, hop): ts = self.timeshifter Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Sun Sep 3 20:59:48 2006 @@ -38,12 +38,11 @@ def getgenvar(self, builder): return self.genvar - def enter_block(self, newblock, incoming, memo): + def enter_block(self, incoming, memo): memo = memo.boxes if not self.is_constant() and self not in memo: - incoming.append(self.genvar) + incoming.append(self) memo[self] = None - self.genvar = newblock.geninputarg(self.kind) def forcevar(self, builder, memo): if self.is_constant(): @@ -212,11 +211,11 @@ assert self.genvar return self.genvar - def enter_block(self, newblock, incoming, memo): + def enter_block(self, incoming, memo): if self.content: - self.content.enter_block(newblock, incoming, memo) + self.content.enter_block(incoming, memo) else: - RedBox.enter_block(self, newblock, incoming, memo) + RedBox.enter_block(self, incoming, memo) # ____________________________________________________________ Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Sun Sep 3 20:59:48 2006 @@ -5,9 +5,8 @@ from pypy.jit.hintannotator.model import * from pypy.jit.timeshifter.timeshift import HintTimeshift from pypy.jit.timeshifter import rtimeshift, rvalue, rtyper as hintrtyper -from pypy.jit.llabstractinterp.test.test_llabstractinterp import annotation -from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.objspace.flow.model import summary +from pypy.rpython.lltypesystem import lltype, llmemory, rstr from pypy.rpython.objectmodel import hint, keepalive_until_here from pypy.rpython.unroll import unrolling_iterable from pypy.rpython.annlowlevel import PseudoHighLevelCallable @@ -26,6 +25,14 @@ def getargtypes(annotator, values): return [annotation(annotator, x) for x in values] +def annotation(a, x): + T = lltype.typeOf(x) + if T == lltype.Ptr(rstr.STR): + t = str + else: + t = annmodel.lltype_to_annotation(T) + return a.typeannotation(t) + def hannotate(func, values, policy=None, inline=None): # build the normal ll graphs for ll_function t = TranslationContext() @@ -103,8 +110,8 @@ # (True=constant, False=variable) and a value # graph1 = ha.translator.graphs[0] # the timeshifted entry point - assert len(graph1.getargs()) == 2 + len(values) - graph1varargs = graph1.getargs()[2:] + assert len(graph1.getargs()) == 1 + len(values) + graph1varargs = graph1.getargs()[1:] timeshifted_entrypoint_args_s = [] residual_argtypes = [] argcolors = [] @@ -131,16 +138,19 @@ graph1) timeshifted_entrypoint = PseudoHighLevelCallable( timeshifted_entrypoint_fnptr, - [htshift.s_ResidualGraphBuilder, htshift.s_JITState] + [htshift.s_JITState] + timeshifted_entrypoint_args_s, - htshift.s_ResidualGraphBuilder) + htshift.s_RedBox) FUNC = lltype.FuncType(residual_argtypes, RESTYPE) argcolors = unrolling_iterable(argcolors) self.argcolors = argcolors def ml_generate_code(rgenop, *args): timeshifted_entrypoint_args = () - builder = rtimeshift.make_builder(rgenop) + + sigtoken = rgenop.sigToken(FUNC) + builder, entrypoint, inputargs_gv = rgenop.newgraph(sigtoken) + i = 0 for color in argcolors: if color == "green": llvalue = args[0] @@ -153,20 +163,24 @@ TYPE = lltype.typeOf(llvalue) kind = rgenop.kindToken(TYPE) boxcls = rvalue.ll_redboxcls(TYPE) - gv_arg = rtimeshift.ll_geninputarg(builder, kind) if is_constant: - # ignore the gv_arg above, which is still present + # ignore the inputargs_gv[i], which is still present # to give the residual graph a uniform signature gv_arg = rgenop.genconst(llvalue) + else: + gv_arg = inputargs_gv[i] box = boxcls(kind, gv_arg) + i += 1 timeshifted_entrypoint_args += (box,) - startblock = rtimeshift.ll_end_setup_builder(builder) - endbuilder = timeshifted_entrypoint(builder, None, + + top_jitstate = rtimeshift.JITState(builder) + returnbox = timeshifted_entrypoint(top_jitstate, *timeshifted_entrypoint_args) - endbuilder.finish_and_return() - sigtoken = rgenop.sigToken(FUNC) + gv_ret = returnbox.getgenvar(top_jitstate.curbuilder) + top_jitstate.curbuilder.finish_and_return(sigtoken, gv_ret) + gv_generated = rgenop.gencallableconst(sigtoken, "generated", - startblock) + entrypoint) generated = gv_generated.revealconst(lltype.Ptr(FUNC)) return generated Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Sun Sep 3 20:59:48 2006 @@ -4,7 +4,7 @@ from pypy.annotation import model as annmodel from pypy.annotation import listdef, dictdef from pypy.jit.timeshifter import rvalue, oop -from pypy.jit.timeshifter.rtimeshift import JITState, ResidualGraphBuilder +from pypy.jit.timeshifter.rtimeshift import JITState from pypy.rpython import rmodel, annlowlevel from pypy.rpython.lltypesystem import rtuple, rlist, rdict from pypy.jit.timeshifter import rtimeshift @@ -26,7 +26,8 @@ self.latestexitindex = -1 self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper) - self.s_ResidualGraphBuilder, self.r_ResidualGraphBuilder = self.s_r_instanceof(ResidualGraphBuilder) + self.s_CodeGenerator, self.r_CodeGenerator = self.s_r_instanceof( + cgmodel.CodeGenerator) self.s_JITState, self.r_JITState = self.s_r_instanceof(JITState) self.s_RedBox, self.r_RedBox = self.s_r_instanceof(rvalue.RedBox) self.s_OopSpecDesc, self.r_OopSpecDesc = self.s_r_instanceof( @@ -38,63 +39,16 @@ getrepr = self.rtyper.getrepr bk = rtyper.annotator.bookkeeper - box_list_def = listdef.ListDef(None, self.s_RedBox) - box_list_def.mutate() + box_list_def = listdef.ListDef(None, self.s_RedBox, mutated = True) self.s_box_list = annmodel.SomeList(box_list_def) self.r_box_list = getrepr(self.s_box_list) self.r_box_list.setup() - box_accum_def = listdef.ListDef(None, self.s_RedBox) - box_accum_def.mutate() - box_accum_def.resize() + box_accum_def = listdef.ListDef(None, self.s_RedBox, resized = True) self.s_box_accum = annmodel.SomeList(box_accum_def) self.r_box_accum = getrepr(self.s_box_accum) self.r_box_accum.setup() -## def ll_make_builder(): -## rgenop = RGenOp() -## return rtimeshift.make_builder(rgenop) - -## # XXX find a different way to enforce the interface types -## self.ll_make_builder_graph = self.annhelper.getgraph( -## ll_make_builder, -## [], self.s_ResidualGraphBuilder) -## self.ll_int_box_graph = self.annhelper.getgraph( -## rtimeshift.ll_int_box, -## [self.s_ConstOrVar, self.s_ConstOrVar], -## self.s_RedBox) -## self.ll_addr_box_graph = self.annhelper.getgraph( -## rtimeshift.ll_addr_box, -## [self.s_ConstOrVar, self.s_ConstOrVar], -## self.s_RedBox) -## self.ll_double_box_graph = self.annhelper.getgraph( -## rtimeshift.ll_int_box, -## [self.s_ConstOrVar, self.s_ConstOrVar], -## self.s_RedBox) -## self.ll_geninputarg_graph = self.annhelper.getgraph( -## rtimeshift.ll_geninputarg, -## [self.s_ResidualGraphBuilder, self.s_ConstOrVar], -## self.s_ConstOrVar) -## self.ll_end_setup_builder_graph = self.annhelper.getgraph( -## rtimeshift.ll_end_setup_builder, -## [self.s_ResidualGraphBuilder], -## self.s_Block) - -#### self.ll_close_jitstate_graph = self.annhelper.getgraph( -#### rtimeshift.ll_close_jitstate, -#### [self.s_JITState], -#### annmodel.s_None) - -## self.ll_close_builder_graph = self.annhelper.getgraph( -## rtimeshift.ll_close_builder, -## [self.s_ResidualGraphBuilder], -## annmodel.s_None) -## self.annhelper.getgraph( -## rtimeshift.ll_gencallableconst, -## [self.s_ResidualGraphBuilder, annmodel.SomeString(), -## self.s_Block, self.s_ConstOrVar], -## self.s_ConstOrVar) - def s_r_instanceof(self, cls, can_be_None=True): # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) @@ -110,7 +64,7 @@ # # then passes the variables to the target of link # - def getexitindex(self, link, inputargs, args_r, entering_links): + def getexitindex(self, link, entering_links): self.latestexitindex += 1 v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') v_boxes = varoftype(self.r_box_accum.lowleveltype, 'boxes') @@ -120,13 +74,14 @@ llops = HintLowLevelOpList(self, None) reenter_vars = [v_jitstate] + i = 0 for var in link.args[1:]: if isinstance(var, flowmodel.Constant): reenter_vars.append(var) continue - i = inputargs.index(var) - r = args_r[i] + r = self.hrtyper.bindingrepr(var) v_box = self.read_out_box(llops, v_boxes, i) + i += 1 if isinstance(r, RedRepr): reenter_vars.append(v_box) else: @@ -184,6 +139,10 @@ self.timeshift_block(timeshifted_blocks, entering_links, block) originalblocks = timeshifted_blocks + inputlinkcounters = {} + for block in originalblocks: + inputlinkcounters[block] = len(entering_links[block]) + returnblock = graph.returnblock self.r_returnvalue = self.hrtyper.bindingrepr(returnblock.inputargs[0]) returnblock.operations = [] @@ -205,7 +164,7 @@ before_block = self.insert_before_block(block, block_entering_links) self.insert_bookkeeping_enter(block, before_block, - len(block_entering_links)) + inputlinkcounters[block]) self.insert_bookkeeping_leave_block(block, entering_links) #self.hrtyper.insert_link_conversions(before_returnblock) @@ -235,16 +194,15 @@ def insert_start_setup(self): newstartblock = self.insert_before_block(self.graph.startblock, None, closeblock=True) - v_builder = varoftype(self.r_ResidualGraphBuilder.lowleveltype, 'builder') v_backstate = varoftype(self.r_JITState.lowleveltype, 'backstate') v_jitstate = newstartblock.inputargs[0] - newstartblock.inputargs[:1] = [v_builder, v_backstate] + newstartblock.inputargs[:1] = [v_backstate] llops = HintLowLevelOpList(self, None) llops.genop('direct_call', [self.c_ll_clearcaches_ptr]) v_jitstate1 = llops.genmixlevelhelpercall(rtimeshift.enter_graph, - [self.s_ResidualGraphBuilder, self.s_JITState], - [v_builder, v_backstate], + [self.s_JITState], + [v_backstate], self.s_JITState) llops.append(flowmodel.SpaceOperation('same_as', [v_jitstate1], v_jitstate)) newstartblock.operations = list(llops) @@ -260,7 +218,7 @@ #elif len(link.args) == 1: # assert False, "the return block should not be seen" - def insert_before_block(self, block, entering_links, closeblock=True): + def insert_before_block(self, block, block_entering_links, closeblock=True): newinputargs = [copyvar(self.hannotator, var) for var in block.inputargs] newblock = flowmodel.Block(newinputargs) @@ -269,7 +227,7 @@ newblock.isstartblock = True self.graph.startblock = newblock else: - for link in entering_links: + for link in block_entering_links: link.settarget(newblock) if closeblock: @@ -353,26 +311,9 @@ v_boxes = rlist.newlist(llops, self.r_box_list, type_erased_v) return v_boxes - # insert before non-join blocks a block with: - # - # newjitstate = rtimeshift.enter_block(jitstate, boxes) - # where boxes = [current-redboxes] - # - # then pass the newjitstate (XXX modified?) and boxes - # to the block original; boxes are modified in place - # + def bookkeeping_enter_simple(self, args_r, newinputargs, before_block, llops, v_boxes, is_returnblock=False): - v_newjitstate = llops.genmixlevelhelpercall(rtimeshift.enter_block, - [self.s_JITState, self.s_box_list], - [newinputargs[0], v_boxes], - self.s_JITState) - - bridge = before_block.exits[0] - # not used any more: v_boxes is not modified by enter_block() nowadays - #self.insert_read_out_boxes(bridge, llops, v_newjitstate, v_boxes, args_r, newinputargs) - before_block.operations[:] = llops - return None # insert before join blocks a block with: @@ -492,126 +433,100 @@ return cache - # insert after blocks the following logic: - # if the original block is the returnblock: + # insert at the end of blocks the following logic: + # if the block is the returnblock: # # go to dispatch_block(jitstate) # - # if the original block has just one exit or the exitswitch is green: + # if the block has just one exit or the exitswitch is green: # - # newjitstate = rtimeshift.leave_block(jitstate) + # # - # if the original block has more than one exit (split case): + # if the block has more than one exit (split case): # - # res = rtimeshift.leave_block_split(jitstate, exitswitchredbox, exitindex, boxes) + # res = rtimeshift.leave_block_split(jitstate, + # exitswitchredbox, exitindex, + # true_case_boxes, + # false_case_boxes) # where - # boxes =[boxes-for-all-current-red-and-green-values] + # true_case_boxes = [redboxes going into the true case link] + # false_case_boxes = [redbox going into the false case link + # + green values going into it wrapped into redboxes, + # all to be saved for later dispatch] # exitindex = number identifying the false branch of the switch # if res then go to true_exit_block # else go to false_exit_block # # exitindex is computed by getexitindex, see comment for that method # - # leave_block_split if the exitswitchredbox is constant just returns its value as res - # otherwise returns True and schedule the false case + # leave_block_split if the exitswitchredbox is constant just + # returns its value as res otherwise returns True + # and schedule the false case # def insert_bookkeeping_leave_block(self, block, entering_links): - # XXX wrong with exceptions as much else - - renamemap = {} - rename = lambda v: renamemap.get(v, v) - inargs = [] - - def introduce(v): - if isinstance(v, flowmodel.Variable): - if v not in renamemap: - vprime = renamemap[v] = copyvar(self.hannotator, v) - inargs.append(v) - - orig_v_jitstate = block.inputargs[0] - introduce(orig_v_jitstate) - - newlinks = [] - - v_newjitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') - self.hannotator.bindings[v_newjitstate] = self.s_JITState - - def rename_on_link(v): - if v is orig_v_jitstate: - return v_newjitstate - else: - return rename(v) + exits = block.exits + exitswitch = block.exitswitch - for link in block.exits: - for v in link.args: - introduce(v) - newlink = link.copy(rename_on_link) - newlink.llexitcase = newlink.exitcase # sanitize the link llexitcase - newlinks.append(newlink) - target = link.target - # update entering_links as necessary - if target in entering_links: - target_entering_links = entering_links[target] - target_entering_links.remove(link) - target_entering_links.append(newlink) - introduce(block.exitswitch) - - inputargs = [rename(v) for v in inargs] - newblock = flowmodel.Block(inputargs) - newblock.closeblock(*newlinks) - - inlink = flowmodel.Link(inargs, newblock) - oldexitswitch = block.exitswitch - block.exitswitch = None - block.recloseblock(inlink) - - llops = HintLowLevelOpList(self, None) - if len(newblock.exits) == 0: # this is the original returnblock - newblock.recloseblock(flowmodel.Link(newblock.inputargs, self.dispatchblock)) - elif len(newblock.exits) == 1 or isinstance(self.hrtyper.bindingrepr(oldexitswitch), GreenRepr): - newblock.exitswitch = rename(oldexitswitch) - v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block, - [self.s_JITState], - [rename(orig_v_jitstate)], - self.s_JITState) - - llops.append(flowmodel.SpaceOperation('same_as', - [v_res], - v_newjitstate)) + if len(exits) == 0: # this is the original returnblock + block.recloseblock(flowmodel.Link(block.inputargs[:1], + self.dispatchblock)) + elif (len(exits) == 1 or + isinstance(self.hrtyper.bindingrepr(exitswitch), GreenRepr)): + pass # nothing to do else: - v_jitstate = rename(orig_v_jitstate) - args_r = [] - boxes_v = [] - for var in inputargs[1:]: - r = self.hrtyper.bindingrepr(var) - args_r.append(r) - if isinstance(r, RedRepr): - boxes_v.append(var) - elif isinstance(r, GreenRepr): - v_box = self.make_const_box(llops, r, var, v_jitstate) - boxes_v.append(v_box) - else: - raise RuntimeError('Unsupported boxtype') - - v_boxes = self.build_box_list(llops, boxes_v) - false_exit = [exit for exit in newblock.exits if exit.exitcase is False][0] - exitindex = self.getexitindex(false_exit, inputargs[1:], args_r, entering_links) + llops = HintLowLevelOpList(self, None) + v_jitstate = self.getjitstate(block) + assert len(exits) == 2 + false_exit, true_exit = exits + if true_exit.exitcase is False: + true_exit, false_exit = false_exit, true_exit + assert true_exit.exitcase is True + assert false_exit.exitcase is False + # sanitize llexitcase + true_exit.llexitcase = True + false_exit.llexitcase = False + v_boxes_true = self.pack_state_into_boxes(llops, + true_exit.args[1:], + v_jitstate, + pack_greens_too=False) + v_boxes_false = self.pack_state_into_boxes(llops, + false_exit.args[1:], + v_jitstate, + pack_greens_too=True) + exitindex = self.getexitindex(false_exit, entering_links) c_exitindex = rmodel.inputconst(lltype.Signed, exitindex) v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split, [self.s_JITState, self.s_RedBox, annmodel.SomeInteger(), + self.s_box_list, self.s_box_list], [v_jitstate, - rename(oldexitswitch), + exitswitch, c_exitindex, - v_boxes], + v_boxes_true, + v_boxes_false], annmodel.SomeBool()) - llops.append(flowmodel.SpaceOperation('same_as', - [inputargs[0]], - v_newjitstate)) - newblock.exitswitch = v_res - newblock.operations[:] = llops + block.exitswitch = v_res + block.operations.extend(llops) + + + def pack_state_into_boxes(self, llops, statevars, v_jitstate, + pack_greens_too): + boxes_v = [] + for var in statevars: + if isinstance(var, flowmodel.Constant): + continue # it's correspondingly skipped in getexitindex() + r = self.hrtyper.bindingrepr(var) + if isinstance(r, RedRepr): + boxes_v.append(var) + elif isinstance(r, GreenRepr): + if pack_greens_too: + v_box = self.make_const_box(llops, r, var, v_jitstate) + boxes_v.append(v_box) + else: + raise RuntimeError('Unsupported boxtype') + return self.build_box_list(llops, boxes_v) # put the following logic in the dispatch block: # @@ -626,13 +541,13 @@ # # the prepare_return_block does: # - # builder = prepare_return(jitstate) + # returnbox = prepare_return(jitstate) # where # prepare_return = (lambda jitstate: # rtimeshift.prepare_return(jitstate, return_cache, # None))) # XXX return type info # where return_cache is a predefined cache - # return builder + # return returnbox # def insert_dispatch_logic(self): dispatchblock = self.dispatchblock @@ -640,8 +555,8 @@ llops = HintLowLevelOpList(self, None) - v_returnbuilder = varoftype(self.r_ResidualGraphBuilder.lowleveltype, 'builder') - returnblock = flowmodel.Block([v_returnbuilder]) + v_returnbox = varoftype(self.r_RedBox.lowleveltype, 'returnbox') + returnblock = flowmodel.Block([v_returnbox]) returnblock.operations = () self.graph.returnblock = returnblock @@ -685,7 +600,7 @@ llops = HintLowLevelOpList(self, None) v_return_builder = llops.genmixlevelhelpercall(prepare_return, [self.s_JITState], [v_jitstate2], - self.s_ResidualGraphBuilder) + self.s_RedBox) prepare_return_block.operations = list(llops) finishedlink = flowmodel.Link([v_return_builder], returnblock) Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Sun Sep 3 20:59:48 2006 @@ -75,19 +75,19 @@ self.item_boxes = [itembox] * length # self.ownbox = ... set in factory() - def enter_block(self, newblock, incoming, memo): + def enter_block(self, incoming, memo): contmemo = memo.containers if self not in contmemo: contmemo[self] = None for box in self.item_boxes: - box.enter_block(newblock, incoming, memo) + box.enter_block(incoming, memo) def force_runtime_container(self, builder): typedesc = self.typedesc boxes = self.item_boxes self.item_boxes = None - args_gv = [None, builder.genconst(len(boxes))] + args_gv = [None, builder.rgenop.genconst(len(boxes))] gv_list = builder.genop_call(typedesc.tok_ll_newlist, typedesc.gv_ll_newlist, args_gv) @@ -95,7 +95,7 @@ self.ownbox.content = None for i in range(len(boxes)): gv_item = boxes[i].getgenvar(builder) - args_gv = [gv_list, builder.genconst(i), gv_item] + args_gv = [gv_list, builder.rgenop.genconst(i), gv_item] builder.genop_call(typedesc.tok_ll_setitem_fast, typedesc.gv_ll_setitem_fast, args_gv) From fijal at codespeak.net Mon Sep 4 08:56:41 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 4 Sep 2006 08:56:41 +0200 (CEST) Subject: [pypy-svn] r31975 - in pypy/dist/pypy/translator: js/test transformer Message-ID: <20060904065641.A15B51006C@code0.codespeak.net> Author: fijal Date: Mon Sep 4 08:56:18 2006 New Revision: 31975 Modified: pypy/dist/pypy/translator/js/test/runtest.py pypy/dist/pypy/translator/js/test/test_seq.py pypy/dist/pypy/translator/js/test/test_transformer.py pypy/dist/pypy/translator/transformer/debug.py Log: Added some tests for transformation. Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Mon Sep 4 08:56:18 2006 @@ -28,7 +28,7 @@ return True class compile_function(object): - def __init__(self, functions, annotations, stackless=False, view=False, html=None, is_interactive=False, root = None, run_browser = True, debug_transform = False): + def __init__(self, function, annotations, stackless=False, view=False, html=None, is_interactive=False, root = None, run_browser = True, debug_transform = False): if not use_browsertest and not _CLI_is_on_path(): py.test.skip('Javascript CLI (js) not found') @@ -36,7 +36,7 @@ self.is_interactive = is_interactive t = TranslationContext() ann = t.buildannotator() - ann.build_types(functions, annotations) + ann.build_types(function, annotations) if debug_transform: DebugTransformer(t).transform_all() t.buildrtyper(type_system="ootype").specialize() @@ -46,7 +46,7 @@ if view or option.view: t.view() #self.js = JS(t, [function, callback_function], stackless) - self.js = JS(t, functions, stackless) + self.js = JS(t, function, stackless) self.js.write_source() if root is None and use_tg: from pypy.translator.js.demo.jsdemo.controllers import Root Modified: pypy/dist/pypy/translator/js/test/test_seq.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_seq.py (original) +++ pypy/dist/pypy/translator/js/test/test_seq.py Mon Sep 4 08:56:18 2006 @@ -112,3 +112,15 @@ fn = compile_function(upperlower, []) assert fn() == "ABAFabaf" + +def test_simple_seq(): + def fun(i): + if i: + a = [("ab", "cd"), ("ef", "xy")] + else: + a = [("xz", "pr"), ("as", "fg")] + return ",".join(["%s : %s" % (i, j) for i,j in a]) + + fn = compile_function(fun, [int]) + assert fn(0) == fun(0) + assert fn(1) == fun(1) Modified: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_transformer.py (original) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Mon Sep 4 08:56:18 2006 @@ -6,6 +6,15 @@ from pypy.translator.js.test.runtest import compile_function from pypy.translator.transformer.debug import traceback_handler +def check_tb(tb_entry_str, callname, args, func, relline): + tb_entry = tb_entry_str.split(":") + funname, callargs, filename, lineno = tb_entry + assert funname == callname + if args is not None: + assert callargs.startswith(args) + assert filename == __file__ or filename == __file__[:-1] + assert int(lineno) == func.func_code.co_firstlineno + relline + def test_simple_tansform(): def g(): raise ValueError() @@ -16,27 +25,64 @@ def wrapper(): try: # XXX: this is needed to make annotator happy - traceback_handler.enter("entrypoint", "data") + traceback_handler.enter("entrypoint", "()", "", 0) f() except: - return "|".join([i + ": " + j for i, j in traceback_handler.tb]) + return "|".join(["%s:%s:%s:%s" % k for k in traceback_handler.tb]) return "" fn = compile_function(wrapper, [], debug_transform = True) retval = fn() lst = retval.split('|') assert len(lst) == 3 - assert lst[1] == 'f: ()' - assert lst[2] == 'g: ()' + check_tb(lst[1], 'f', '()', wrapper, 4) + check_tb(lst[2], 'g', '()', f, 1) -def test_simple_seq(): - def fun(i): - if i: - a = [("ab", "cd"), ("ef", "xy")] - else: - a = [("xz", "pr"), ("as", "fg")] - return ",".join(["%s : %s" % (i, j) for i,j in a]) - - fn = compile_function(fun, [int]) - assert fn(0) == fun(0) - assert fn(1) == fun(1) +def test_sophisticated_transform(): + def g(): + raise ValueError() + + def f(): + try: + g() + except: + pass + + def z(): + f() + raise TypeError() + + def wrapper(): + try: + traceback_handler.enter("entrypoint", "()", "", 0) + z() + except: + return "|".join(["%s:%s:%s:%s" % k for k in traceback_handler.tb]) + return "" + + fn = compile_function(wrapper, [], debug_transform = True) + retval = fn() + lst = retval.split("|") + assert len(lst) == 2 + check_tb(lst[1], 'z', '()', wrapper, 3) + +def test_args(): + def f(a, b, c): + raise TypeError() + + def g(): + f(3, "dupa", [1,2,3]) + + def wrapper(): + try: + traceback_handler.enter("entrypoint", "()", "", 0) + g() + except: + return "|".join(["%s:%s:%s:%s" % k for k in traceback_handler.tb]) + return "" + + fn = compile_function(wrapper, [], debug_transform = True) + retval = fn() + lst = retval.split("|") + check_tb(lst[1], "g", "()", wrapper, 3) + check_tb(lst[2], "f", "(3, 'dupa'", g, 1) Modified: pypy/dist/pypy/translator/transformer/debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/debug.py (original) +++ pypy/dist/pypy/translator/transformer/debug.py Mon Sep 4 08:56:18 2006 @@ -10,6 +10,7 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.ootypesystem import rclass from pypy.translator.transformer.basictransform import BasicTransformer +from pypy.interpreter.pytraceback import offset2lineno from types import FunctionType, MethodType @@ -19,8 +20,8 @@ def __init__(self): self.tb = [] - def enter(self, tb_str, data): - self.tb.append((tb_str, data)) + def enter(self, tb_str, data, filename, lineno): + self.tb.append((tb_str, data, filename, lineno)) def leave(self, tb_str): num = len(self.tb) - 1 @@ -46,7 +47,7 @@ def register_helpers(self): return None for func_name, func_args in [("traceback", []), - ("enter", ["aa", "aa"]), ("leave", ["aa"])]: + ("enter", ["aa", "aa", "aa", 3]), ("leave", ["aa"])]: graph = self.flow_method(TracebackHandler, func_name, func_args) graph.explicit_traceback = True @@ -62,8 +63,9 @@ # XXX or any other call opg, v1 = self.genop("getattr", [self.instance_const, 'enter']) fun_name = op.args[0].value.func_name - data = self.get_info(block, graph, op) - opc, v2 = self.genop("simple_call", [v1, fun_name, data]) + data, filename, lineno = self.get_info(block, graph, op) + opc, v2 = self.genop("simple_call", [v1, fun_name, data, \ + filename, lineno]) opgl, v3 = self.genop("getattr", [self.instance_const, 'leave']) oplc, v4 = self.genop("simple_call", [v3, fun_name]) next += [opg, opc, op, opgl, oplc] @@ -81,10 +83,13 @@ arglist = [] for arg in op.args[1:]: if isinstance(arg, model.Constant): - arglist.append(str(arg.value)) + arglist.append(repr(arg.value)) else: arglist.append(str(arg)) - return "(%s)" % ", ".join(arglist) + call_str = "(%s)" % ", ".join(arglist) + filename = getattr(graph, 'filename', '') + lineno = offset2lineno(graph.func.func_code, op.offset) + return call_str, filename, lineno def transform_graph(self, graph): if getattr(graph, 'explicit_traceback', None): From ale at codespeak.net Mon Sep 4 10:34:14 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 4 Sep 2006 10:34:14 +0200 (CEST) Subject: [pypy-svn] r31977 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060904083414.909751006C@code0.codespeak.net> Author: ale Date: Mon Sep 4 10:34:13 2006 New Revision: 31977 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Added better support for (some) XMLSchema types, with tests. bugfixes and performance improvements (especially using generators) Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Mon Sep 4 10:34:13 2006 @@ -1,7 +1,7 @@ from logilab.constraint.propagation import AbstractDomain, AbstractConstraint,\ ConsistencyFailure from rdflib import URIRef - +import autopath import py from pypy.tool.ansi_print import ansi_log log = py.log.Producer("Constraint") @@ -45,7 +45,7 @@ def narrow(self, domains): log(self.formula) - if domains[self.prop].getValues() != []: + if domains[self.prop].size() != 0: log ("%r"% self._variables[0]) for indi in domains[self._variables[0]].getValues(): log("%s" % indi) @@ -59,7 +59,7 @@ self.variable = variable def narrow(self, domains): - if domains[self.variable].getValues() != []: + if domains[self.variable].size() != 0: raise ConsistencyFailure class SubClassConstraint(AbstractConstraint): @@ -81,8 +81,8 @@ subdom = domains[self.variable] superdom = domains[self.object] vals = [] - vals += superdom.getValues() - vals += subdom.getValues() +[self.variable] + vals += list(superdom.getValues()) + vals += list(subdom.getValues()) +[self.variable] superdom.setValues(vals) return 0 @@ -95,9 +95,8 @@ subdom = domains[self.variable] superdom = domains[self.object] vals1 = superdom.getValues() - vals2 = subdom.getValues() for i in vals1: - if i in vals2: + if i in subdom: raise ConsistencyFailure() Thing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Thing') @@ -125,7 +124,7 @@ def narrow(self, domains): vals = domains[self.variable].getValues() - x_vals = domains[self.object].getValues() + x_vals = domains[self.object] remove = [] for v in vals: if v in x_vals: @@ -141,18 +140,9 @@ def narrow(self, domains): propdom = domains[self.variable] rangedom = domains[self.object] - newrange = set(rangedom.getValues()) - res = [] - oldrange = set(propdom.range) - if oldrange: - res = oldrange & newrange - else: - res = newrange - propdom.range = list(res) - prop = Linkeddict(propdom.getValues()) - for pval in prop: - if pval not in res: - raise ConsistencyFailure("Value %r not in range %r"%(pval, res)) + for cls,pval in propdom.getValues(): + if pval not in rangedom: + raise ConsistencyFailure("Value %r of property %r not in range %r"%(pval, self.variable, self.object)) class DomainConstraint(SubClassConstraint): @@ -161,25 +151,15 @@ def narrow(self, domains): propdom = domains[self.variable] domaindom = domains[self.object] - newdomain = set(domaindom.getValues() +[self.object]) - domain = [] - olddomain = set(propdom.domain) - if olddomain: - domain= olddomain & newdomain - else: - domain = newdomain - propdom.domain = list(domain) - prop = Linkeddict(propdom.getValues()) - for pval in prop: - if pval not in domain: - raise ConsistencyFailure("Value %r not in domain %r"%(pval, domain)) + for cls in propdom: + if cls not in domaindom: + raise ConsistencyFailure("Value %r of property %r not in domain %r"%(pval, self.variable, self.object)) class SubPropertyConstraint(SubClassConstraint): def narrow(self, domains): subdom = domains[self.variable] superdom = domains[self.object] - vals = superdom.getValues() for (key, val) in subdom.getValues(): if not (key, val) in superdom: for v in val: @@ -192,9 +172,8 @@ def narrow(self, domains): subdom = domains[self.variable] superdom = domains[self.object] - vals = superdom.getValues() for value in subdom.getValues(): - if not value in vals: + if not value in superdom: superdom.addValue(value[0], value[1]) class TypeConstraint(SubClassConstraint): @@ -203,7 +182,7 @@ subdom = domains[self.variable] superdom = domains[self.object] vals = [] - vals += superdom.getValues() + vals += list(superdom.getValues()) vals.append(self.variable) superdom.setValues(vals) return 1 @@ -214,7 +193,7 @@ def narrow(self, domains): """narrowing algorithm for the constraint""" domain = domains[self.variable].getValues() - domain_dict = Linkeddict(domain) + domain_dict = Linkeddict(list(domain)) for cls, val in domain_dict.items(): if len(val) != 1: for item in val: @@ -309,7 +288,7 @@ return 1 else: for dom in domains.values(): - vals = dom.getValues() + vals = list(dom.getValues()) if hasattr(dom, '_dict'): val = Linkeddict(vals) if self.variable in val.keys() and not self.object in val.keys(): @@ -340,12 +319,12 @@ """narrowing algorithm for the constraint""" vals =[] - vals += domains[self.variable].getValues() + vals += list(domains[self.variable].getValues()) if vals == []: return 0 while True: if vals[-1] in domains.keys() and isinstance(domains[vals[-1]], List): - vals = vals[:-1] + domains[vals[-1]].getValues() + vals = vals[:-1] + list(domains[vals[-1]].getValues()) if domains[vals[-1]].remove : domains.pop(vals[-1]) else: @@ -359,10 +338,10 @@ def narrow(self, domains): prop = domains[self.variable].property - vals = domains[self.variable].getValues() + vals = list(domains[self.variable].getValues()) if vals: cls = vals[0] - props = domains[prop].getValues() + props = list(domains[prop].getValues()) props.append((cls, None)) domains[prop].setValues(props) return 1 @@ -381,12 +360,12 @@ return self.cost def narrow(self, domains): - val = domains[self.List].getValues() + val = domains[self.List] if isinstance(domains[self.variable],Restriction): # This should actually never happen ?? property = domains[self.variable].property - cls = domains[self.variable].getValues()[0] - prop = Linkeddict(domains[property].getValues()) + cls = list(domains[self.variable].getValues())[0] + prop = Linkeddict(list(domains[property].getValues())) for v in prop[cls]: if not v in val: raise ConsistencyFailure( @@ -414,10 +393,10 @@ cost = 200 def narrow(self, domains): - val = domains[self.List].getValues() + val = list(domains[self.List].getValues()) intersection = domains[val[0]].getValues() for v in val[1:]: - vals= domains[v].getValues() + vals= domains[v] remove = [] for u in intersection: if not u in vals: @@ -457,7 +436,7 @@ dom = domains[self.variable] property = dom.property indi = dom.getValues() - prop = Linkeddict(domains[property].getValues()) + prop = Linkeddict(list(domains[property].getValues())) for v in indi: if not v in prop.keys(): dom.removeValue(v) @@ -481,15 +460,15 @@ def narrow(self, domains): val = set(domains[self.List].getValues()) + if not val: + return dom = domains[self.variable] property = dom.property indi = dom.getValues() prop = domains[property]._dict remove = [] for v in indi: - if not val: - dom.removeValue(v) - elif not v in prop: + if not v in prop: dom.removeValue(v) else: prop_val = prop[v] Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Mon Sep 4 10:34:13 2006 @@ -5,7 +5,7 @@ ConsistencyFailure from constraint_classes import * import sys, py -import time +import datetime, time from urllib2 import URLError log = py.log.Producer("Pyontology") from pypy.tool.ansi_print import ansi_log @@ -114,9 +114,11 @@ self.domains.update(dom) self.in_constraint.extend(constraints) # update the store - if ('owl_Thing' in variables.keys() and isinstance(self, ClassDomain) - and self.getValues() == []): - variables[self.name].setValues(variables['owl_Thing'].getValues()) + if prop: + variables[self.name].setValues([v[0] for v in prop.getValues()]) + elif ('owl_Thing' in variables.keys() and isinstance(self, ClassDomain) + and self.size() == 0): + variables[self.name].setValues(list(variables['owl_Thing'].getValues())) # log.finish("setting the domain %s to all individuals %r"%(self.name,variables[self.name])) variables.update(self.domains) glob_constraints.extend(self.in_constraint) @@ -124,13 +126,16 @@ return self.domains, self.un_constraint def __repr__(self): - return "<%s %s %r>" % (self.__class__, str(self.name), self.getValues()) - + return "<%s %s>" % (self.__class__, str(self.name)) + + def __contains__(self, item): + return item in self.values + def copy(self): return self def size(self): - return len(self.getValues()) + return len(self.values) def removeValues(self, values): for val in values: @@ -142,7 +147,7 @@ self.values.pop(value) if not self.values: log.removeValue("Removed the lastvalue of the Domain") - raise ConsistencyFailure + raise ConsistencyFailure("Removed the lastvalue of the Domain") def getBases(self): return self._bases @@ -157,7 +162,8 @@ self.values[value] = True def getValues(self): - return self.values.keys() + for key in self.values: + yield key def __iter__(self): return iter(self.values.keys()) @@ -172,7 +178,10 @@ fixed = True def removeValues(self, values): - pass #raise ConsistencyFailure + raise ConsistencyFailure("Cannot remove values from a FixedClassDomain") + + def removeValue(self, value): + raise ConsistencyFailure("Cannot remove values from a FixedClassDomain") def setValues(self, values): if not self.values: @@ -215,17 +224,15 @@ def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) -class Property(ClassDomain): +class Property(Individual): #ClassDomain): # Property contains the relationship between a class instance and a value # - a pair. To accomodate global assertions like 'range' and 'domain' attributes # for range and domain must be filled in by rdfs:range and rdfs:domain - def __init__(self, name='', values=[], bases = []): - AbstractDomain.__init__(self) + def __init__(self, name='', uri='', values=[], bases = []): + Individual.__init__(self, name, uri, values, bases) self.name = name self._dict = {} - self.range = [] - self.domain = [] self.property = None self.constraint = [] self.un_constraint = [] @@ -237,15 +244,14 @@ return var, constraints def size(self): - return len(self.getValues()) + return len(self._dict) def getValues(self): items = self._dict.items() res = [] for k,vals in items: for v in vals: - res.append((k,v)) - return res + yield (k,v) def getValuesPrKey(self, key= None): if key: @@ -360,6 +366,16 @@ ClassDomain.__init__(self, name, values, bases) self.property = None +def Types(typ): + class Type(ClassDomain): + + def __contains__(self, item): + #assert isinstance(item, Literal) + return item.datatype is None or item.datatype == self.Type + + datatype = Type + datatype.Type = typ + return datatype builtin_voc = { getUriref('owl', 'Thing') : Thing, @@ -381,9 +397,14 @@ getUriref('owl', 'SymmetricProperty') : SymmetricProperty, getUriref('owl', 'TransitiveProperty') : TransitiveProperty, getUriref('rdf', 'List') : List, -# getUriref('xmlschema', 'string') : str } +XMLTypes = ['string', 'float', 'integer', 'date'] + +for typ in XMLTypes: + uri = getUriref('xmlschema', typ) + builtin_voc[uri] = Types(uri) + class Ontology: def __init__(self, store = 'default'): @@ -421,7 +442,6 @@ log("=============================") def finish(self): - t0 = time.time() for constraint in self.constraints: log.exception("Trying %r" %constraint) for key in constraint.affectedVariables(): @@ -429,10 +449,7 @@ if isinstance( self.variables[key], fd): continue self.variables[key].finish(self.variables, self.constraints) - t1 = time.time() constraint.narrow(self.variables) - t2 = time.time() - t0 = time.time() def consider_triple(self,(s, p, o)): if (s, p, o) in self.seen: @@ -510,7 +527,7 @@ elif not cls == self.variables[var].__class__ and issubclass(cls, self.variables[var].__class__): vals = self.variables[var].getValues() tmp = cls(var, a) - tmp.setValues(vals) + tmp.setValues(list(vals)) tmp.property = self.variables[var].property if tmp.constraint: log("make_var constraint 2 %r,%r" %(cls,a)) @@ -642,7 +659,7 @@ # The memebers of the list can be Urirefs (Individuals) or Literals var = self.flatten_rdf_list(var) svar = self.make_var(FixedClassDomain, s) - res = self.variables[var].getValues() + res = list(self.variables[var].getValues()) if type(res[0]) == URIRef: self.variables[svar].setValues([ Individual(self.make_var(Thing, x), x) for x in res]) @@ -653,16 +670,15 @@ def unionOf(self,s, var): var = self.flatten_rdf_list(var) - vals = self.variables[var].getValues() res = [] - for val in vals: + for val in self.variables[var].getValues(): self.get_individuals_of(val) var_name = self.make_var(ClassDomain, val) val = self.variables[var_name].getValues() res.extend([x for x in val]) svar = self.make_var(ClassDomain, s) - vals = self.variables[svar].getValues() + vals = list(self.variables[svar].getValues()) res.extend(vals) self.variables[svar].setValues(res) @@ -701,7 +717,7 @@ self.resolve_predicate(s) avar = self.make_var(Property, var) svar = self.make_var(Property, s) - avals = self.variables[avar].getValues() + avals = self.variables[avar] for pair in self.variables[svar].getValues(): if not pair in avals: self.variables[avar].addValue(pair[0], pair[1]) Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon Sep 4 10:34:13 2006 @@ -28,6 +28,29 @@ ont.rest(own, URIRef(namespaces['rdf']+'#nil')) return owllist +def test_XMLSchema_string(): + O = Ontology() + a = URIRef(u'A') + p = URIRef(u'P') + prop = URIRef(namespaces['owl']+'#Property') + xml_string_uri = URIRef(namespaces['xmlschema']+"#string") + O.type(p, prop) + O.consider_triple((a, p, Literal("ddd", datatype=xml_string_uri))) + O.range(p, xml_string_uri) + O.consistency() + +def test_XMLSchema_string_fail(): + O = Ontology() + a = URIRef(u'A') + p = URIRef(u'P') + prop = URIRef(namespaces['owl']+'#Property') + xml_string_uri = URIRef(namespaces['xmlschema']+"#string") + xml_int_uri= URIRef(namespaces['xmlschema']+"#integer") + O.type(p, prop) + O.consider_triple((a, p, Literal(2, datatype = xml_int_uri))) + O.range(p, xml_string_uri) + raises(ConsistencyFailure, O.consistency) + def test_makevar(): O = Ontology() var = URIRef(u'http://www.w3.org/2002/03owlt/unionOf/premises004#A-and-B') @@ -36,7 +59,7 @@ exec cod assert O.make_var(None, var) in locals() assert isinstance(O.variables[name], ClassDomain) - + def test_subClassof(): O = Ontology() a = URIRef(u'A') @@ -54,16 +77,16 @@ O = Ontology() a = O.make_var(Property, URIRef('a')) O.variables[a].addValue('key', 42) - assert O.variables[a].getValues() == [('key', 42)] + assert ('key', 42) in O.variables[a] O.variables[a].addValue('key', 43) - assert O.variables[a].getValues() == [('key', 42), ('key', 43)] + assert list(O.variables[a].getValues()) == [('key', 42), ('key', 43)] def no_test_ClassDomain(): a = ClassDomain() cls = 1 b = ClassDomain('B',[],[a]) - assert b in b.getValues() - assert a in b.getValues() + assert b in b + assert a in b def test_subClassconstraint(): a = ClassDomain('A') @@ -74,8 +97,8 @@ con.narrow({'a': a, 'b': b, 'c': c}) con2.narrow({'a': a, 'b': b, 'c': c}) con.narrow({'a': a, 'b': b, 'c': c}) - assert 'b' in a.getValues() - assert 'c' in a.getValues() + assert 'b' in a + assert 'c' in a def test_subClassconstraintMulti(): a = ClassDomain('A') @@ -85,8 +108,8 @@ con2 = SubClassConstraint('c','b') con.narrow({'a': a, 'b': b, 'c': c}) con2.narrow({'a': a, 'b': b, 'c': c}) - assert 'c' in a.getValues() - assert 'c' in b.getValues() + assert 'c' in a + assert 'c' in b def test_subClassconstraintMulti2(): a = ClassDomain('A') @@ -98,9 +121,9 @@ con.narrow({'a': a, 'b': b, 'c': c}) con2.narrow({'a': a, 'b': b, 'c': c}) con3.narrow({'a': a, 'b': b, 'c': c}) - assert 'c' in a.getValues() - assert 'c' in b.getValues() - assert 'a' in c.getValues() + assert 'c' in a + assert 'c' in b + assert 'a' in c def test_equivalentClass(): O = Ontology() @@ -142,7 +165,6 @@ O.type(sub, obj) assert len(O.constraints) == 1 O.constraints[0].narrow(O.variables) - assert O.variables['a_'].range == [1,2,3,4] def test_merge(): O = Ontology() @@ -159,7 +181,6 @@ O.type(sub, obj) assert len(O.constraints) == 2 O.consistency() - assert O.variables['a_'].range == [ 3,4] def test_domain(): O = Ontology() @@ -173,7 +194,6 @@ O.type(sub, obj) assert len(O.constraints) == 1 O.constraints[0].narrow(O.variables) - assert O.variables['a_'].domain == ['b_'] def test_domain_merge(): O = Ontology() @@ -190,7 +210,7 @@ assert len(O.constraints) == 2 for con in O.constraints: con.narrow(O.variables) - assert O.variables['a_'].getValues() ==[] + assert O.variables['a_'].size() == 0 def test_subproperty(): O = Ontology() @@ -203,7 +223,7 @@ O.subPropertyOf(sub, b) O.consistency() for val in O.variables['a_'].getValues(): - assert val in O.variables['b_'].getValues() + assert val in O.variables['b_'] def test_functionalproperty(): @@ -290,7 +310,7 @@ O.type(sub, obj) O.variables['friend_'].setValues([('Bob_','Alice_')]) O.consistency() - assert ('Alice_', 'Bob_') in O.variables['friend_'].getValues() + assert ('Alice_', 'Bob_') in O.variables['friend_'] def test_inverseof(): O = Ontology() @@ -314,7 +334,7 @@ O.variables['owner_'].setValues([('Bob_','Fiat_')]) O.inverseOf(own, owned) O.consistency() - assert ('Fiat_','Bob_') in O.variables['ownedby_'].getValues() + assert ('Fiat_','Bob_') in O.variables['ownedby_'] def test_hasvalue(): # py.test.skip("") @@ -341,7 +361,7 @@ O.subClassOf(cls2,restrict) O.variables[O.make_var(None, cls2)].finish(O.variables, O.constraints) O.consistency() - assert cls in O.variables[O.make_var(None, cls2)].getValues() + assert cls in O.variables[O.make_var(None, cls2)] # py.test.raises(ConsistencyFailure, O.consistency) def test_List(): @@ -358,7 +378,7 @@ O.rest( URIRef('2'), URIRef(namespaces['rdf']+'#nil')) O.flatten_rdf_list(own) O.consistency() - assert O.rep._domains['favlist_'].getValues() == [0,1,2] + assert list(O.rep._domains['favlist_'].getValues()) == [0,1,2] def test_oneofclassenumeration(): O = Ontology() @@ -367,7 +387,7 @@ O.oneOf(restrict, own) O.type(restrict, UR(namespaces['owl']+'#Class')) O.consistency() - assert len(O.rep._domains[restrict].getValues()) == 3 + assert O.rep._domains[restrict].size()== 3 assert set(O.rep._domains[restrict].getValues()) == set(own) def test_unification_of_two_oneofclassenumeration(): @@ -384,7 +404,7 @@ O.type(UR('test'), restrict) O.type(UR('test'), restrict1) O.consistency() - assert len(O.rep._domains[restrict].getValues()) == 3 + assert O.rep._domains[restrict].size() == 3 assert set(O.rep._domains[restrict].getValues()) == set(own) @@ -395,7 +415,7 @@ O.oneOf(restrict, own) O.type(restrict, UR(namespaces['owl']+'#DataRange')) O.consistency() - assert len(O.rep._domains[restrict].getValues()) == 3 + assert O.rep._domains[restrict].size() == 3 assert set(O.rep._domains[restrict].getValues()) == set(own) def test_somevaluesfrom_datarange(): @@ -419,7 +439,7 @@ O.someValuesFrom(restrict, datarange) O.subClassOf(cls,restrict) O.consistency() - assert cls in O.variables[O.make_var(None, cls)].getValues() + assert cls in O.variables[O.make_var(None, cls)] def test_allvaluesfrom_datarange(): py.test.skip("") @@ -441,7 +461,7 @@ O.onProperty(restrict,p) O.allValuesFrom(restrict, datarange) O.subClassOf(cls,restrict) - assert cls in O.variables[O.make_var(None, cls)].getValues() + assert cls in O.variables[O.make_var(None, cls)] def test_unionof(): py.test.skip("Rewrite the test") @@ -457,7 +477,7 @@ O.unionOf(cls, own) O.type(cls, namespaces['owl']+'#Class') O.consistency() - res = O.rep._domains[cls].getValues() + res = list(O.rep._domains[cls].getValues()) res.sort() assert res == ['1', '2', '3', '4', '5'] @@ -468,7 +488,7 @@ O.intersectionOf(cls, [['1','2','3'],['3','4','5']]) O.type(cls, namespaces['owl']+'#Class') O.consistency() - assert O.rep._domains[cls].getValues() == ['3'] + assert list(O.rep._domains[cls].getValues()) == ['3'] def test_differentfrom(): O = Ontology() @@ -508,7 +528,7 @@ O.type(sub, obj) O.variables[O.make_var(None,sub)].setValues([(cls,'1')]) O.consistency() - assert ('liist1','1') in O.rep._domains[O.make_var(None,sub)].getValues() + assert ('liist1','1') in O.rep._domains[O.make_var(None,sub)] def test_sameasconsistency(): O = Ontology() @@ -626,7 +646,7 @@ O.type(URIRef('i5'), URIRef(namespaces['owl']+'#Thing')) O.complementOf(b_cls, a_cls) O.consistency() - assert O.variables[O.make_var(None, b_cls)].getValues() == ['i5'] + assert list(O.variables[O.make_var(None, b_cls)].getValues()) == ['i5'] def test_complementof_raise(): O = Ontology() @@ -684,4 +704,4 @@ first = URIRef('first') second = URIRef('second') O.type(first, URIRef(namespaces['owl']+'#Thing')) - assert isinstance((O.variables['owl_Thing'].getValues()[0]), Individual) + assert isinstance(list(O.variables['owl_Thing'].getValues())[0], Individual) From rhymes at codespeak.net Mon Sep 4 11:33:23 2006 From: rhymes at codespeak.net (rhymes at codespeak.net) Date: Mon, 4 Sep 2006 11:33:23 +0200 (CEST) Subject: [pypy-svn] r31980 - pypy/dist/pypy/module/rctime Message-ID: <20060904093323.069D710063@code0.codespeak.net> Author: rhymes Date: Mon Sep 4 11:33:21 2006 New Revision: 31980 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: replaced fmod from math to libc's fmod. Hope this fixes compilation issues Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Sep 4 11:33:21 2006 @@ -6,7 +6,6 @@ from pypy.interpreter.baseobjspace import W_Root, ObjSpace from ctypes import * import os -import math import sys _POSIX = os.name == "posix" @@ -88,6 +87,8 @@ Sleep.restype = None libc.strftime.argtypes = [c_char_p, size_t, c_char_p, POINTER(tm)] libc.strftime.restype = size_t +libc.fmod.argtypes = [c_double, c_double] +libc.fmod.restype = c_double def _init_accept2dyear(): return (1, 0)[bool(os.getenv("PYTHONY2K"))] @@ -265,7 +266,7 @@ buf.tm_year = y - 1900 buf.tm_mon = buf.tm_mon - 1 - buf.tm_wday = int(math.fmod((buf.tm_wday + 1), 7)) + buf.tm_wday = int(libc.fmod((buf.tm_wday + 1), 7)) buf.tm_yday = buf.tm_yday - 1 return buf From bea at codespeak.net Mon Sep 4 11:50:49 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Mon, 4 Sep 2006 11:50:49 +0200 (CEST) Subject: [pypy-svn] r31981 - pypy/extradoc/sprintinfo/ireland-2006 Message-ID: <20060904095049.29ECA10063@code0.codespeak.net> Author: bea Date: Mon Sep 4 11:50:48 2006 New Revision: 31981 Added: pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt (contents, props changed) Log: a sceleton for the limerick sprint report - armin, holger, samuele, arre, michael, majiek - please polish this Added: pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt Mon Sep 4 11:50:48 2006 @@ -0,0 +1,52 @@ +Sprint report Limerick sprint, Ireland 21-27th of August 2006 +======================================= + +Location: University of Limerick, Computer Science building, Limerick, Ireland +Participants: Armin Rigo, Samuele Pedroni, Michael Hudson, Holger Krekel, Anders Chrigstr?m, +Majiek Fijalkowski, Beatrice D?ring + +The goals of the sprint was to focus on JIT compiler works, various optimization +works, porting extension modules, infrastructure works like a build tool for +PyPy, or extended (distributed) testing. + +What _really_ happened was: + +* core optimizations + (mwh) + - (done) did a lot of profiling, main finding: GC + - optimising GC: (done) by mostly just collecting + less often :-/ + - experiment with optimising builtin lookups + e.g caching method lookups or callback-dict + - remove the zeroing assumption (more should be + done on this) + +* ext compiler + maybe a topic for the weekend + +* JIT + - first machine code generation tests are passing + - (samuele, arre) produce machine code in-memory from running the generated CFGs + - (michael, arigo) implement more of the interface to generate I386 + machine code; maybe think about refining the interface (also + considering a PPC asm backend) + + +* distributed testing + (maciej, mick) + more or less done, but many things : + - use "/usr/bin/rsync" to sync to remote + - master does collection of items + - "leaf" items are asynchronously send to "Executors" (running on nodes) + - super-simple reporting + + (next) boxing of processes to catch stdout, segfaults, etc. + (next) http server interface to running tests + (later) make more test options work, e.g. --pdb, --view... + + +* (mick, maciej) writing more JS examples + + + (arigo) wrote a generic interface that works via greenlets or threads interchangeable (svn/user/arigo/hack/pypeers/bluesock.py) + From cfbolz at codespeak.net Mon Sep 4 15:08:11 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Sep 2006 15:08:11 +0200 (CEST) Subject: [pypy-svn] r31986 - pypy/extradoc/talk/ep2005 Message-ID: <20060904130811.5677C1006C@code0.codespeak.net> Author: cfbolz Date: Mon Sep 4 15:08:09 2006 New Revision: 31986 Added: pypy/extradoc/talk/ep2005/pypy_sprinttalk_ep2005bd.pdf (contents, props changed) Log: add pdf version, to link from the talks page Added: pypy/extradoc/talk/ep2005/pypy_sprinttalk_ep2005bd.pdf ============================================================================== Binary file. No diff available. From cfbolz at codespeak.net Mon Sep 4 15:29:34 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Sep 2006 15:29:34 +0200 (CEST) Subject: [pypy-svn] r31987 - pypy/dist/pypy/doc Message-ID: <20060904132934.EB3DB1006E@code0.codespeak.net> Author: cfbolz Date: Mon Sep 4 15:29:34 2006 New Revision: 31987 Modified: pypy/dist/pypy/doc/extradoc.txt Log: add bea's sprint talk too Modified: pypy/dist/pypy/doc/extradoc.txt ============================================================================== --- pypy/dist/pypy/doc/extradoc.txt (original) +++ pypy/dist/pypy/doc/extradoc.txt Mon Sep 4 15:29:34 2006 @@ -41,13 +41,16 @@ +++++++++++++ -* `PyPy - the new Python implementation on the block`_ talk, +* `PyPy - the new Python implementation on the block`_, given by Carl Friedrich Bolz and Holger Krekel at the 22nd Chaos Communication Conference in Berlin, Dec. 2005. -* `Open Source, EU-Funding and Agile Methods`_ talk, given by Holger Krekel +* `Open Source, EU-Funding and Agile Methods`_, given by Holger Krekel and Bea During at the 22nd Chaos Communication Conference in Berlin, Dec. 2005 +* `Sprinting the PyPy way`_, an overview about our sprint methodology, given by + Bea During during EuroPython 2005 + * `PyCon 2005`_ animated slices, mostly reporting on the translator status. * `py lib slides`_ from the py lib talk at PyCon 2005 @@ -84,6 +87,7 @@ .. _`Kill -1`: http://codespeak.net/pypy/extradoc/talk/ep2006/kill_1_agiletalk.pdf .. _`Open Source, EU-Funding and Agile Methods`: http://codespeak.net/pypy/extradoc/talk/22c3/agility.pdf .. _`PyPy Status`: http://codespeak.net/pypy/extradoc/talk/vancouver/talk.html +.. _`Sprinting the PyPy way`: http://codespeak.net/svn/pypy/extradoc/talk/ep2005/pypy_sprinttalk_ep2005bd.pdf Related projects ---------------------------------- From hpk at codespeak.net Mon Sep 4 18:36:16 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 4 Sep 2006 18:36:16 +0200 (CEST) Subject: [pypy-svn] r31989 - pypy/extradoc/sprintinfo/ireland-2006 Message-ID: <20060904163616.0D8AA1006E@code0.codespeak.net> Author: hpk Date: Mon Sep 4 18:36:14 2006 New Revision: 31989 Modified: pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt Log: Fix ReST. Modified: pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt ============================================================================== --- pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt (original) +++ pypy/extradoc/sprintinfo/ireland-2006/limerick_sprint-report.txt Mon Sep 4 18:36:14 2006 @@ -1,5 +1,5 @@ Sprint report Limerick sprint, Ireland 21-27th of August 2006 -======================================= +===================================================================== Location: University of Limerick, Computer Science building, Limerick, Ireland Participants: Armin Rigo, Samuele Pedroni, Michael Hudson, Holger Krekel, Anders Chrigstr?m, @@ -11,18 +11,16 @@ What _really_ happened was: -* core optimizations - (mwh) +* core optimizations (mwh): + - (done) did a lot of profiling, main finding: GC - - optimising GC: (done) by mostly just collecting - less often :-/ + - optimising GC: (done) by mostly just collecting less often :-/ - experiment with optimising builtin lookups e.g caching method lookups or callback-dict - remove the zeroing assumption (more should be done on this) -* ext compiler - maybe a topic for the weekend +* ext compiler - maybe a topic for the weekend * JIT - first machine code generation tests are passing @@ -30,11 +28,11 @@ - (michael, arigo) implement more of the interface to generate I386 machine code; maybe think about refining the interface (also considering a PPC asm backend) - * distributed testing (maciej, mick) more or less done, but many things : + - use "/usr/bin/rsync" to sync to remote - master does collection of items - "leaf" items are asynchronously send to "Executors" (running on nodes) From arigo at codespeak.net Mon Sep 4 21:36:01 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Sep 2006 21:36:01 +0200 (CEST) Subject: [pypy-svn] r31993 - pypy/dist/pypy/rpython Message-ID: <20060904193601.B528110063@code0.codespeak.net> Author: arigo Date: Mon Sep 4 21:35:57 2006 New Revision: 31993 Modified: pypy/dist/pypy/rpython/llinterp.py Log: Make the AssertionError more readable by nicely putting blank lines around the pages and pages of each type's repr. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Sep 4 21:35:57 2006 @@ -190,7 +190,7 @@ try: val = lltype.enforce(var.concretetype, val) except TypeError: - assert False, "type error: %r val -> %r var" % (lltype.typeOf(val), var.concretetype) + assert False, "type error: input value of type:\n\n\t%r\n\n===> variable of type:\n\n\t%r\n" % (lltype.typeOf(val), var.concretetype) assert isinstance(var, Variable) self.bindings[var] = val From arigo at codespeak.net Mon Sep 4 21:37:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Sep 2006 21:37:54 +0200 (CEST) Subject: [pypy-svn] r31994 - in pypy/dist/pypy: jit/timeshifter jit/timeshifter/test tool Message-ID: <20060904193754.CA3B91006E@code0.codespeak.net> Author: arigo Date: Mon Sep 4 21:37:49 2006 New Revision: 31994 Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/tool/uid.py Log: (pedronis, arigo) The timeshifter needs to carry and duplicate the state of the callers in strange ways. This is shown by test_call_4. So a lot of refactorings, most of which are clean-ups (progress). Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Mon Sep 4 21:37:49 2006 @@ -216,8 +216,9 @@ contmemo = memo.containers if self not in contmemo: contmemo[self] = None - for i in range(len(self.content_boxes)): - self.content_boxes[i] = self.content_boxes[i].replace(memo) + content_boxes = self.content_boxes + for i in range(len(content_boxes)): + content_boxes[i] = content_boxes[i].replace(memo) self.ownbox = self.ownbox.replace(memo) def op_getfield(self, jitstate, fielddesc): Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Mon Sep 4 21:37:49 2006 @@ -53,7 +53,7 @@ _opdesc_cache[op_key] = opdesc return opdesc -def ll_generate_operation1(opdesc, jitstate, argbox): +def ll_gen1(opdesc, jitstate, argbox): ARG0 = opdesc.ARG0 RESULT = opdesc.RESULT opname = opdesc.name @@ -65,7 +65,7 @@ genvar = jitstate.curbuilder.genop1(opdesc.opname, gv_arg) return opdesc.redboxcls(opdesc.result_kind, genvar) -def ll_generate_operation2(opdesc, jitstate, argbox0, argbox1): +def ll_gen2(opdesc, jitstate, argbox0, argbox1): ARG0 = opdesc.ARG0 ARG1 = opdesc.ARG1 RESULT = opdesc.RESULT @@ -81,7 +81,7 @@ genvar = jitstate.curbuilder.genop2(opdesc.opname, gv_arg0, gv_arg1) return opdesc.redboxcls(opdesc.result_kind, genvar) -def ll_generate_getfield(jitstate, fielddesc, argbox): +def ll_gengetfield(jitstate, fielddesc, argbox): if fielddesc.immutable and argbox.is_constant(): res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE), fielddesc.fieldname) @@ -93,7 +93,7 @@ else: return argbox.content.op_getfield(jitstate, fielddesc) -def ll_generate_setfield(jitstate, fielddesc, destbox, valuebox): +def ll_gensetfield(jitstate, fielddesc, destbox, valuebox): assert isinstance(destbox, rvalue.PtrRedBox) if destbox.content is None: gv_ptr = destbox.getgenvar(jitstate.curbuilder) @@ -101,7 +101,7 @@ else: destbox.content.op_setfield(jitstate, fielddesc, valuebox) -def ll_generate_getsubstruct(jitstate, fielddesc, argbox): +def ll_gengetsubstruct(jitstate, fielddesc, argbox): if argbox.is_constant(): res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE), fielddesc.fieldname) @@ -114,7 +114,7 @@ return argbox.content.op_getsubstruct(jitstate, fielddesc) -def ll_generate_getarrayitem(jitstate, fielddesc, argbox, indexbox): +def ll_gengetarrayitem(jitstate, fielddesc, argbox, indexbox): if fielddesc.immutable and argbox.is_constant() and indexbox.is_constant(): array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE) res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)] @@ -126,7 +126,7 @@ return fielddesc.redboxcls(fielddesc.kind, genvar) -def ll_generate_getarraysize(jitstate, fielddesc, argbox): +def ll_gengetarraysize(jitstate, fielddesc, argbox): if argbox.is_constant(): array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE) res = len(array) @@ -139,52 +139,44 @@ # ____________________________________________________________ # other jitstate/graph level operations -def enter_graph(backstate): - return JITState(backstate.curbuilder, backstate) +def enter_next_block(jitstate, incoming): + linkargs = [] + kinds = [] + for redbox in incoming: + linkargs.append(redbox.genvar) + kinds.append(redbox.kind) + newblock = jitstate.curbuilder.enter_next_block(kinds, linkargs) + for i in range(len(incoming)): + incoming[i].genvar = linkargs[i] + return newblock -def start_new_block(states_dic, jitstate, key, redboxes): +def start_new_block(states_dic, jitstate, key): memo = rvalue.freeze_memo() - frozens = [redbox.freeze(memo) for redbox in redboxes] + frozen = jitstate.freeze(memo) memo = rvalue.exactmatch_memo() outgoingvarboxes = [] - for i in range(len(redboxes)): - res = frozens[i].exactmatch(redboxes[i], outgoingvarboxes, memo) - assert res, "exactmatch() failed" - linkargs = [] - kinds = [] - for box in outgoingvarboxes: # all variables - linkargs.append(box.genvar) - kinds.append(box.kind) - newblock = jitstate.curbuilder.enter_next_block(kinds, linkargs) - states_dic[key] = frozens, newblock - for i in range(len(outgoingvarboxes)): - box = outgoingvarboxes[i] - box.genvar = linkargs[i] - return jitstate + res = frozen.exactmatch(jitstate, outgoingvarboxes, memo) + assert res, "exactmatch() failed" + newblock = enter_next_block(jitstate, outgoingvarboxes) + states_dic[key] = frozen, newblock start_new_block._annspecialcase_ = "specialize:arglltype(2)" def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes): - mylocalredboxes = redboxes - redboxes = list(redboxes) - jitstate.extend_with_parent_locals(redboxes) + jitstate.local_boxes = redboxes if key not in states_dic: - return start_new_block(states_dic, jitstate, key, redboxes) + start_new_block(states_dic, jitstate, key) + return False # continue - frozens, oldblock = states_dic[key] + frozen, oldblock = states_dic[key] memo = rvalue.exactmatch_memo() outgoingvarboxes = [] - exactmatch = True - for i in range(len(redboxes)): - frozen = frozens[i] - if not frozen.exactmatch(redboxes[i], outgoingvarboxes, memo): - exactmatch = False - if exactmatch: + if frozen.exactmatch(jitstate, outgoingvarboxes, memo): linkargs = [] for box in outgoingvarboxes: linkargs.append(box.getgenvar(jitstate.curbuilder)) jitstate.curbuilder.finish_and_goto(linkargs, oldblock) - return None + return True # finished # We need a more general block. Do it by generalizing all the # redboxes from outgoingvarboxes, by making them variables. @@ -193,34 +185,16 @@ for box in outgoingvarboxes: box = box.forcevar(jitstate.curbuilder, replace_memo) if replace_memo.boxes: - for i in range(len(mylocalredboxes)): - newbox = redboxes[i].replace(replace_memo) - mylocalredboxes[i] = redboxes[i] = newbox - return start_new_block(states_dic, jitstate, key, redboxes) + jitstate.replace(replace_memo) + start_new_block(states_dic, jitstate, key) + return False # continue retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)" - -def enter_block(jitstate, redboxes): - # 'redboxes' is a fixed-size list (s_box_list) of the current red boxes + +def enter_block(jitstate): incoming = [] memo = rvalue.enter_block_memo() - for redbox in redboxes: - redbox.enter_block(incoming, memo) -## XXX -## js = jitstate.backstate -## while js is not None: -## lrb = js.localredboxes -## assert lrb is not None -## for redbox in lrb: -## redbox.enter_block(incoming, memo) -## js = js.backstate - linkargs = [] - kinds = [] - for redbox in incoming: # all variables - linkargs.append(redbox.genvar) - kinds.append(redbox.kind) - jitstate.curbuilder.enter_next_block(kinds, linkargs) - for i in range(len(incoming)): - incoming[i].genvar = linkargs[i] + jitstate.enter_block(incoming, memo) + enter_next_block(jitstate, incoming) def leave_block_split(jitstate, switchredbox, exitindex, redboxes_true, redboxes_false): @@ -230,64 +204,131 @@ exitgvar = switchredbox.getgenvar(jitstate.curbuilder) later_builder = jitstate.curbuilder.jump_if_false(exitgvar) memo = rvalue.copy_memo() - redboxcopies = [None] * len(redboxes_false) - for i in range(len(redboxes_false)): - redboxcopies[i] = redboxes_false[i].copy(memo) - jitstate.split_queue.append((exitindex, later_builder, redboxcopies)) - enter_block(jitstate, redboxes_true) + jitstate.local_boxes = redboxes_false + later_jitstate = jitstate.copy(memo) + later_jitstate.curbuilder = later_builder + later_jitstate.exitindex = exitindex + jitstate.split_queue.append(later_jitstate) + jitstate.local_boxes = redboxes_true + enter_block(jitstate) return True -def dispatch_next(jitstate, outredboxes): - split_queue = jitstate.split_queue +def dispatch_next(oldjitstate, return_cache): + split_queue = oldjitstate.split_queue if split_queue: - exitindex, later_builder, redboxes = split_queue.pop() - jitstate.curbuilder = later_builder - enter_block(jitstate, redboxes) - for box in redboxes: - outredboxes.append(box) - return exitindex - return -1 - -def save_return(jitstate, redboxes): - returnbox = redboxes[0] - jitstate.return_queue.append((jitstate.curbuilder, returnbox)) - -def prepare_return(jitstate, cache, return_type): - for builder, retbox in jitstate.return_queue[:-1]: - jitstate.curbuilder = builder - res = retrieve_jitstate_for_merge(cache, jitstate, (), [retbox]) - assert res is None - frozens, block = cache[()] - builder, returnbox = jitstate.return_queue[-1] - jitstate.backstate.curbuilder = builder - return returnbox + jitstate = split_queue.pop() + enter_block(jitstate) + return jitstate + else: + return_queue = oldjitstate.return_queue + for jitstate in return_queue[:-1]: + res = retrieve_jitstate_for_merge(return_cache, jitstate, (), + jitstate.local_boxes) + assert res is True # finished + frozen, block = return_cache[()] + jitstate = return_queue[-1] + retbox = jitstate.local_boxes[0] + backstate = jitstate.backstate + backstate.curbuilder = jitstate.curbuilder + backstate.local_boxes.append(retbox) + backstate.exitindex = -1 + # XXX for now the return value box is put in the parent's local_boxes, + # where a 'restore_local' operation will fetch it + return backstate + +def getexitindex(jitstate): + return jitstate.exitindex + +def getlocalbox(jitstate, i): + return jitstate.local_boxes[i] + +def save_return(jitstate): + jitstate.return_queue.append(jitstate) def ll_gvar_from_redbox(jitstate, redbox): return redbox.getgenvar(jitstate.curbuilder) def ll_gvar_from_constant(jitstate, ll_value): - return jitstate.rgenop.genconst(ll_value) + return jitstate.curbuilder.rgenop.genconst(ll_value) def save_locals(jitstate, redboxes): - jitstate.localredboxes = redboxes + jitstate.local_boxes = redboxes # ____________________________________________________________ + +class FrozenJITState(object): + fz_backstate = None + #fz_local_boxes = ... set by freeze() + + def exactmatch(self, jitstate, outgoingvarboxes, memo): + self_boxes = self.fz_local_boxes + live_boxes = jitstate.local_boxes + fullmatch = True + for i in range(len(self_boxes)): + if not self_boxes[i].exactmatch(live_boxes[i], + outgoingvarboxes, + memo): + fullmatch = False + if self.fz_backstate is not None: + assert jitstate.backstate is not None + if not self.fz_backstate.exactmatch(jitstate.backstate, + outgoingvarboxes, + memo): + fullmatch = False + else: + assert jitstate.backstate is None + return fullmatch + + class JITState(object): - # XXX obscure interface - localredboxes = [] + exitindex = -1 - def __init__(self, builder, backstate=None): - self.split_queue = [] - self.return_queue = [] + def __init__(self, split_queue, return_queue, builder, backstate): + self.split_queue = split_queue + self.return_queue = return_queue self.curbuilder = builder - self.rgenop = builder.rgenop self.backstate = backstate + #self.local_boxes = ... set by callers + + def enter_block(self, incoming, memo): + for box in self.local_boxes: + box.enter_block(incoming, memo) + if self.backstate is not None: + self.backstate.enter_block(incoming, memo) + + def freeze(self, memo): + result = FrozenJITState() + frozens = [box.freeze(memo) for box in self.local_boxes] + result.fz_local_boxes = frozens + if self.backstate is not None: + result.fz_backstate = self.backstate.freeze(memo) + return result + + def copy(self, memo): + if self.backstate is None: + newbackstate = None + else: + newbackstate = self.backstate.copy(memo) + result = JITState(self.split_queue, + self.return_queue, + None, + newbackstate) + result.local_boxes = [box.copy(memo) for box in self.local_boxes] + return result + + def replace(self, memo): + local_boxes = self.local_boxes + for i in range(len(local_boxes)): + local_boxes[i] = local_boxes[i].replace(memo) + if self.backstate is not None: + self.backstate.replace(memo) + - def extend_with_parent_locals(self, redboxes): - js = self.backstate - while js is not None: - lrb = js.localredboxes - assert lrb is not None - redboxes.extend(lrb) - js = js.backstate +def enter_graph(backstate): + return JITState([], [], backstate.curbuilder, backstate) + +def fresh_jitstate(builder): + jitstate = JITState([], [], builder, None) + jitstate.local_boxes = [] + return jitstate Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Mon Sep 4 21:37:49 2006 @@ -44,7 +44,7 @@ originalconcretetype = staticmethod(originalconcretetype) def make_new_lloplist(self, block): - return HintLowLevelOpList(self.timeshifter, block) + return HintLowLevelOpList(self.timeshifter) def getgreenrepr(self, lowleveltype): try: @@ -88,9 +88,9 @@ # the same operation at run-time opdesc = rtimeshift.make_opdesc(hop) if opdesc.nb_args == 1: - ll_generate = rtimeshift.ll_generate_operation1 + ll_generate = rtimeshift.ll_gen1 elif opdesc.nb_args == 2: - ll_generate = rtimeshift.ll_generate_operation2 + ll_generate = rtimeshift.ll_gen2 ts = self.timeshifter c_opdesc = inputconst(lltype.Void, opdesc) s_opdesc = ts.rtyper.annotator.bookkeeper.immutablevalue(opdesc) @@ -132,7 +132,7 @@ c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() - return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getfield, + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gengetfield, [ts.s_JITState, s_fielddesc, ts.s_RedBox], [v_jitstate, c_fielddesc, v_argbox ], ts.s_RedBox) @@ -152,7 +152,7 @@ s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall( - rtimeshift.ll_generate_getarrayitem, + rtimeshift.ll_gengetarrayitem, [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox], [v_jitstate, c_fielddesc, v_argbox, v_index ], ts.s_RedBox) @@ -171,7 +171,7 @@ s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall( - rtimeshift.ll_generate_getarraysize, + rtimeshift.ll_gengetarraysize, [ts.s_JITState, s_fielddesc, ts.s_RedBox], [v_jitstate, c_fielddesc, v_argbox ], ts.s_RedBox) @@ -193,7 +193,7 @@ c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() - return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_setfield, + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gensetfield, [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox], [v_jitstate, c_fielddesc, v_destbox, v_valuebox], annmodel.s_None) @@ -210,7 +210,7 @@ c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() - return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getsubstruct, + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gengetsubstruct, [ts.s_JITState, s_fielddesc, ts.s_RedBox], [v_jitstate, c_fielddesc, v_argbox ], ts.s_RedBox) @@ -224,59 +224,50 @@ r_result = hop.r_result return r_result.create(hop) - def translate_op_direct_call(self, hop): - c_func = hop.args_v[0] - assert isinstance(c_func, flowmodel.Constant) + def guess_call_kind(self, spaceop): + assert spaceop.opname == 'direct_call' + c_func = spaceop.args[0] fnobj = c_func.value._obj + s_result = self.annotator.binding(spaceop.result) + r_result = self.getrepr(s_result) if hasattr(fnobj._callable, 'oopspec'): - # special-cased call, for things like list methods - hop.r_s_popfirstarg() - return self.handle_highlevel_operation(fnobj, hop) - elif (originalconcretetype(hop.s_result) is not lltype.Void and - isinstance(hop.r_result, GreenRepr)): - # green-returning call, for now (XXX) we assume it's an - # all-green function that we can just call - for r_arg in hop.args_r: - assert isinstance(r_arg, GreenRepr) - v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype) - return v + return 'oopspec' + elif (originalconcretetype(s_result) is not lltype.Void and + isinstance(r_result, GreenRepr)): + return 'green' else: - bk = self.annotator.bookkeeper - ts = self.timeshifter - v_jitstate = hop.llops.getjitstate() - hop.r_s_popfirstarg() - args_hs = hop.args_s[:] - # fixed is always false here - graph = bk.get_graph_for_call(fnobj.graph, False, args_hs) - args_r = [self.getrepr(hs) for hs in args_hs] - args_v = hop.inputargs(*args_r) - ARGS = [ts.r_JITState.lowleveltype] - ARGS += [r.lowleveltype for r in args_r] - RESULT = ts.r_RedBox.lowleveltype - fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), - graph.name, - graph=graph, - _callable = graph.func) - self.timeshifter.schedule_graph(graph) - args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate] - return hop.genop('direct_call', args_v, RESULT) + return 'red' + + def translate_op_direct_call(self, hop): + kind = self.guess_call_kind(hop.spaceop) + meth = getattr(self, 'handle_%s_call' % (kind,)) + return meth(hop) def translate_op_save_locals(self, hop): ts = self.timeshifter v_jitstate = hop.llops.getjitstate() - boxes_v = [] - for r, v in zip(hop.args_r, hop.args_v): - if isinstance(r, RedRepr): - boxes_v.append(v) - v_boxes = ts.build_box_list(hop.llops, boxes_v) + v_boxes = ts.build_box_list(hop.llops, hop.args_v) hop.llops.genmixlevelhelpercall(rtimeshift.save_locals, [ts.s_JITState, ts.s_box_list], [v_jitstate, v_boxes], annmodel.s_None) - def handle_highlevel_operation(self, fnobj, hop): + def translate_op_restore_local(self, hop): + ts = self.timeshifter + assert isinstance(hop.args_v[0], flowmodel.Constant) + index = hop.args_v[0].value + v_jitstate = hop.llops.getjitstate() + return ts.read_out_box(hop.llops, v_jitstate, index) + + + def handle_oopspec_call(self, hop): + # special-cased call, for things like list methods from pypy.jit.timeshifter.oop import OopSpecDesc, Index + + c_func = hop.args_v[0] + fnobj = c_func.value._obj oopspecdesc = OopSpecDesc(self, fnobj) + hop.r_s_popfirstarg() args_v = [] for obj in oopspecdesc.argtuple: @@ -318,13 +309,45 @@ [v_jitstate, c_oopspecdesc] + args_v, s_result) + def handle_green_call(self, hop): + # green-returning call, for now (XXX) we assume it's an + # all-green function that we can just call + for r_arg in hop.args_r: + assert isinstance(r_arg, GreenRepr) + v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype) + return v + + def handle_red_call(self, hop): + bk = self.annotator.bookkeeper + ts = self.timeshifter + v_jitstate = hop.llops.getjitstate() + c_func = hop.args_v[0] + fnobj = c_func.value._obj + hop.r_s_popfirstarg() + args_hs = hop.args_s[:] + # fixed is always false here + graph = bk.get_graph_for_call(fnobj.graph, False, args_hs) + args_r = [self.getrepr(hs) for hs in args_hs] + args_v = hop.inputargs(*args_r) + ARGS = [ts.r_JITState.lowleveltype] + ARGS += [r.lowleveltype for r in args_r] + RESULT = ts.r_JITState.lowleveltype + fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), + graph.name, + graph=graph, + _callable = graph.func) + self.timeshifter.schedule_graph(graph) + args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate] + v_newjitstate = hop.genop('direct_call', args_v, RESULT) + hop.llops.setjitstate(v_newjitstate) + class HintLowLevelOpList(LowLevelOpList): """Warning: the HintLowLevelOpList's rtyper is the *original* rtyper, while the HighLevelOp's rtyper is actually our HintRTyper... """ - def __init__(self, timeshifter, originalblock): - LowLevelOpList.__init__(self, timeshifter.rtyper, originalblock) + def __init__(self, timeshifter): + LowLevelOpList.__init__(self, timeshifter.rtyper) self.timeshifter = timeshifter def hasparentgraph(self): @@ -358,8 +381,11 @@ resulttype = RESULT) def getjitstate(self): - assert self.originalblock is not None - return self.timeshifter.block2jitstate[self.originalblock] + return self.genop('getjitstate', [], + resulttype = self.timeshifter.r_JITState) + + def setjitstate(self, v_newjitstate): + self.genop('setjitstate', [v_newjitstate]) # ____________________________________________________________ Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Mon Sep 4 21:37:49 2006 @@ -90,7 +90,7 @@ def ll_fromvalue(jitstate, value): "Make a constant RedBox from a low-level value." - rgenop = jitstate.rgenop + rgenop = jitstate.curbuilder.rgenop T = lltype.typeOf(value) kind = rgenop.kindToken(T) gv = rgenop.genconst(value) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Mon Sep 4 21:37:49 2006 @@ -96,9 +96,6 @@ for graph in ha.translator.graphs: checkgraph(graph) t.graphs.append(graph) - if conftest.option.view: - from pypy.translator.tool.graphpage import FlowGraphPage - FlowGraphPage(t, ha.translator.graphs).display() # make an interface to the timeshifted graphs: # @@ -140,7 +137,7 @@ timeshifted_entrypoint_fnptr, [htshift.s_JITState] + timeshifted_entrypoint_args_s, - htshift.s_RedBox) + htshift.s_JITState) FUNC = lltype.FuncType(residual_argtypes, RESTYPE) argcolors = unrolling_iterable(argcolors) self.argcolors = argcolors @@ -173,9 +170,10 @@ i += 1 timeshifted_entrypoint_args += (box,) - top_jitstate = rtimeshift.JITState(builder) - returnbox = timeshifted_entrypoint(top_jitstate, - *timeshifted_entrypoint_args) + top_jitstate = rtimeshift.fresh_jitstate(builder) + top_jitstate = timeshifted_entrypoint(top_jitstate, + *timeshifted_entrypoint_args) + returnbox = top_jitstate.local_boxes[0] gv_ret = returnbox.getgenvar(top_jitstate.curbuilder) top_jitstate.curbuilder.finish_and_return(sigtoken, gv_ret) @@ -214,6 +212,9 @@ self.rtyper = rtyper self.htshift = htshift self.annotate_interface_functions() + if conftest.option.view: + from pypy.translator.tool.graphpage import FlowGraphPage + FlowGraphPage(t, ha.translator.graphs).display() cache = self.__dict__.copy() self._cache[key] = cache, getargtypes(rtyper.annotator, values) @@ -756,3 +757,22 @@ res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL) assert res == 10 self.check_insns({'int_add': 2, 'int_sub': 1, 'int_mul': 1}) + + def test_call_4(self): + def ll_two(x): + if x > 0: + return x + 5 + else: + return x - 4 + def ll_function(y): + return ll_two(y) * y + + res = self.timeshift(ll_function, [3], [], policy=P_NOVIRTUAL) + assert res == 24 + self.check_insns({'int_gt': 1, 'int_add': 1, + 'int_sub': 1, 'int_mul': 1}) + + res = self.timeshift(ll_function, [-3], [], policy=P_NOVIRTUAL) + assert res == 21 + self.check_insns({'int_gt': 1, 'int_add': 1, + 'int_sub': 1, 'int_mul': 1}) Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Mon Sep 4 21:37:49 2006 @@ -39,15 +39,15 @@ getrepr = self.rtyper.getrepr bk = rtyper.annotator.bookkeeper - box_list_def = listdef.ListDef(None, self.s_RedBox, mutated = True) + box_list_def = listdef.ListDef(None, self.s_RedBox, resized = True) self.s_box_list = annmodel.SomeList(box_list_def) self.r_box_list = getrepr(self.s_box_list) self.r_box_list.setup() - box_accum_def = listdef.ListDef(None, self.s_RedBox, resized = True) - self.s_box_accum = annmodel.SomeList(box_accum_def) - self.r_box_accum = getrepr(self.s_box_accum) - self.r_box_accum.setup() +## box_accum_def = listdef.ListDef(None, self.s_RedBox, resized = True) +## self.s_box_accum = annmodel.SomeList(box_accum_def) +## self.r_box_accum = getrepr(self.s_box_accum) +## self.r_box_accum.setup() def s_r_instanceof(self, cls, can_be_None=True): # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. @@ -66,21 +66,20 @@ # def getexitindex(self, link, entering_links): self.latestexitindex += 1 - v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') - v_boxes = varoftype(self.r_box_accum.lowleveltype, 'boxes') - reentry_block = flowmodel.Block([v_jitstate, v_boxes]) + reentry_block = flowmodel.Block([]) - llops = HintLowLevelOpList(self, None) + llops = HintLowLevelOpList(self) + v_jitstate = llops.getjitstate() - reenter_vars = [v_jitstate] + reenter_vars = [] i = 0 - for var in link.args[1:]: + for var in link.args: if isinstance(var, flowmodel.Constant): reenter_vars.append(var) continue r = self.hrtyper.bindingrepr(var) - v_box = self.read_out_box(llops, v_boxes, i) + v_box = self.read_out_box(llops, v_jitstate, i) i += 1 if isinstance(r, RedRepr): reenter_vars.append(v_box) @@ -102,7 +101,7 @@ reentry_block.operations[:] = llops reentry_block.closeblock(reenter_link) - from_dispatch =flowmodel.Link([None, None], reentry_block) + from_dispatch = flowmodel.Link([], reentry_block) self.dispatch_to.append((self.latestexitindex, from_dispatch)) return self.latestexitindex @@ -129,7 +128,6 @@ self.graph = graph self.dispatch_to = [] self.statecaches = [] - self.block2jitstate = {} self.return_cache = None entering_links = flowmodel.mkentrymap(graph) @@ -149,28 +147,16 @@ graph.returnblock = None # we need to get the jitstate to the before block of the return block self.dispatchblock = flowmodel.Block([]) - self.insert_jitstate_arg(self.dispatchblock) -# before_returnblock = self.insert_before_block(returnblock, -# entering_links[returnblock], -# closeblock=False) - # fix its concretetypes - #self.hrtyper.setup_block_entry(before_returnblock) - #self.insert_jitstate_arg(before_returnblock) - for block in originalblocks: - self.insert_jitstate_arg(block) +## self.insert_jitstate_arg(self.dispatchblock) +## for block in originalblocks: +## self.insert_jitstate_arg(block) for block in originalblocks: block_entering_links = entering_links.pop(block) - before_block = self.insert_before_block(block, - block_entering_links) - self.insert_bookkeeping_enter(block, before_block, - inputlinkcounters[block]) + self.insert_bookkeeping_enter(block, inputlinkcounters[block], + block_entering_links) self.insert_bookkeeping_leave_block(block, entering_links) - #self.hrtyper.insert_link_conversions(before_returnblock) - # add booking logic - #self.insert_return_bookkeeping(before_returnblock) - # fix its concretetypes self.insert_dispatch_logic() @@ -190,36 +176,43 @@ annmodel.s_None) self.insert_start_setup() + self.insert_v_jitstate_everywhere() #print 'timeshift_graph END', graph + def insert_v_jitstate_everywhere(self): + for block in self.graph.iterblocks(): + v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') + block.inputargs = [v_jitstate] + block.inputargs + for op in block.operations: + if op.opname == 'getjitstate': + op.opname = 'same_as' + op.args = [v_jitstate] + elif op.opname == 'setjitstate': + [v_jitstate] = op.args + for i in range(len(block.operations)-1, -1, -1): + if block.operations[i].opname == 'setjitstate': + del block.operations[i] + for link in block.exits: + link.args = [v_jitstate] + link.args + def insert_start_setup(self): - newstartblock = self.insert_before_block(self.graph.startblock, None, closeblock=True) - v_backstate = varoftype(self.r_JITState.lowleveltype, 'backstate') - v_jitstate = newstartblock.inputargs[0] - newstartblock.inputargs[:1] = [v_backstate] - llops = HintLowLevelOpList(self, None) + newstartblock = self.insert_before_block(self.graph.startblock, None, + closeblock=True) + llops = HintLowLevelOpList(self) + v_backstate = llops.getjitstate() llops.genop('direct_call', [self.c_ll_clearcaches_ptr]) v_jitstate1 = llops.genmixlevelhelpercall(rtimeshift.enter_graph, [self.s_JITState], [v_backstate], self.s_JITState) - llops.append(flowmodel.SpaceOperation('same_as', [v_jitstate1], v_jitstate)) + llops.setjitstate(v_jitstate1) newstartblock.operations = list(llops) - - def insert_jitstate_arg(self, block): - # pass 'jitstate' as an extra argument around the whole graph - #if block.operations != (): - v_jitstate = self.getjitstate(block) - block.inputargs.insert(0, v_jitstate) - for link in block.exits: - #if link.target.operations != (): - link.args.insert(0, v_jitstate) - #elif len(link.args) == 1: - # assert False, "the return block should not be seen" - def insert_before_block(self, block, block_entering_links, closeblock=True): - newinputargs = [copyvar(self.hannotator, var) for var in block.inputargs] + def insert_before_block(self, block, block_entering_links, + closeblock=True): + newinputargs = [copyvar(self.hannotator, var) + for var in block.inputargs] newblock = flowmodel.Block(newinputargs) if block.isstartblock: # xxx @@ -243,82 +236,48 @@ self.s_RedBox) return v_box - - def read_out_box(self, llops, v_boxes, i): - c_i = rmodel.inputconst(lltype.Signed, i) - v_box = llops.gendirectcall(rlist.ll_getitem_fast, v_boxes, c_i) - v_box = llops.convertvar(v_box, self.r_box_list.item_repr, self.r_RedBox) - return v_box - - def insert_read_out_boxes(self, bridge, llops, v_newjitstate, v_boxes, args_r, newinputargs): - newinputargs2 = [v_newjitstate] - if bridge.target.operations == (): # special case the return block - assert False, "the return block should not be seen" - else: - i = 0 - for r, newvar in zip(args_r[1:], newinputargs[1:]): - if isinstance(r, RedRepr): - newinputargs2.append(self.read_out_box(llops, v_boxes, i)) - i += 1 - else: - newinputargs2.append(newvar) + def build_box_list(self, llops, boxes_v): + type_erased_v = [llops.convertvar(v_box, self.r_RedBox, + self.r_box_list.item_repr) + for v_box in boxes_v] + v_boxes = rlist.newlist(llops, self.r_box_list, type_erased_v) + return v_boxes - # patch bridge - bridge.args = newinputargs2 # patch the link + def read_out_box(self, llops, v_jitstate, i): + c_i = rmodel.inputconst(lltype.Signed, i) + v_box = llops.genmixlevelhelpercall(rtimeshift.getlocalbox, + [self.s_JITState, annmodel.SomeInteger(nonneg=True)], + [v_jitstate , c_i ], + self.s_RedBox) + return v_box - def insert_bookkeeping_enter(self, block, before_block, nentrylinks): - newinputargs = before_block.inputargs - args_r = [] - for var in newinputargs: - args_r.append(self.hrtyper.bindingrepr(var)) - - llops = HintLowLevelOpList(self, None) - - - TYPES = [] - boxes_v = [] - for r, newvar in zip(args_r, newinputargs): - if isinstance(r, RedRepr): - boxes_v.append(newvar) - TYPES.append(r.original_concretetype) - getrepr = self.rtyper.getrepr - - v_boxes = self.build_box_list(llops, boxes_v) - + def insert_bookkeeping_enter(self, block, nentrylinks, + block_entering_links): is_returnblock = len(block.exits) == 0 - if nentrylinks > 1 or is_returnblock: - enter_block_logic = self.bookkeeping_enter_for_join - else: - enter_block_logic = self.bookkeeping_enter_simple + if nentrylinks == 1 and not is_returnblock: + # simple non-merging and non-returning case: nothing to do + return + before_block = self.insert_before_block(block, block_entering_links) + newinputargs = before_block.inputargs + llops = HintLowLevelOpList(self) + v_boxes = self.pack_state_into_boxes(llops, newinputargs) # fill the block with logic - cache = enter_block_logic(args_r, newinputargs, - before_block, - llops, - v_boxes, - is_returnblock) + cache = self.bookkeeping_enter_for_join(newinputargs, + before_block, + llops, + v_boxes, + is_returnblock) if is_returnblock: assert self.return_cache is None self.return_cache = cache - def build_box_list(self, llops, boxes_v): - type_erased_v = [llops.convertvar(v_box, self.r_RedBox, - self.r_box_list.item_repr) - for v_box in boxes_v] - v_boxes = rlist.newlist(llops, self.r_box_list, type_erased_v) - return v_boxes - - - def bookkeeping_enter_simple(self, args_r, newinputargs, before_block, - llops, v_boxes, is_returnblock=False): - return None - # insert before join blocks a block with: # - # newjiststate = merge_point(jitstate, key, boxes) + # finished_flag = merge_point(jitstate, key, boxes) # where # key = (current-green-values) # boxes = [current-redboxes] @@ -326,32 +285,34 @@ # rtimeshift.retrieve_jitstate_for_merge( # constant {}, jitstate, # key, boxes)) - # if newjistate is None then go to dispatch_block(jitstate) - # else go to read_boxes_block(newjiststate, boxes) + # if finished_flag then go to dispatch_block + # else go to read_boxes_block # - # and the other block read_boxes_block which reads the redboxes back out boxes - # and pass them along to the original block together with the new jitstate + # it also inserts another block 'read_boxes_block' which reads the + # redboxes back out 'jitstate.local_boxes' and pass them along to + # the original block, together with the 'jitstate' as usual # # for the return block case (which is always considered a join block) the - # read_boxes_block is special: + # 'read_boxes_block' is special: # - # rtimeshift.save_return(newjitstate, boxes) - # go to dispatch_block(newjitstate) + # rtimeshift.save_return(jitstate) + # go to dispatch_block # - # retrieve_jitstate_for_merge is supposed to use the "constant" dict as cache - # mapping green values combinations to frozen states for red boxes values - # and generated blocks + # retrieve_jitstate_for_merge is supposed to use the "constant" dict as + # the cache that maps green values combinations to frozen states for red + # boxes values and generated blocks # - # if the newjitstate is None, it means an old state/block could be reused + # if finished_flag is True, it means an old state/block could be reused # and execution continues to the dispatch_block # - def bookkeeping_enter_for_join(self, args_r, newinputargs, before_block, + def bookkeeping_enter_for_join(self, newinputargs, before_block, llops, v_boxes, is_returnblock): getrepr = self.rtyper.getrepr items_s = [] key_v = [] orig_key_v = [] - for r, newvar in zip(args_r, newinputargs): + for newvar in newinputargs: + r = self.hrtyper.bindingrepr(newvar) if isinstance(r, GreenRepr): r_from = getrepr(r.annotation()) s_erased = r.erased_annotation() @@ -366,7 +327,7 @@ r_key.setup() v_key = rtuple.newtuple(llops, r_key, key_v) - v_oldjitstate = newinputargs[0] + v_jitstate = llops.getjitstate() cache = {} self.statecaches.append(cache) @@ -375,60 +336,59 @@ return rtimeshift.retrieve_jitstate_for_merge(cache, jitstate, key, boxes) - v_newjitstate = llops.genmixlevelhelpercall(merge_point, + v_finished_flag = llops.genmixlevelhelpercall(merge_point, [self.s_JITState, s_key_tuple, self.s_box_list], - [v_oldjitstate, v_key, v_boxes], - self.s_JITState) - - v_continue = llops.genop('ptr_nonzero', [v_newjitstate], resulttype=lltype.Bool) + [v_jitstate, v_key, v_boxes], + annmodel.SomeBool()) # now read out the possibly modified red boxes out of v_boxes - - v_newjitstate2 = varoftype(self.r_JITState.lowleveltype, v_newjitstate) - v_boxes2 = varoftype(self.r_box_list.lowleveltype, v_boxes) - read_boxes_block_vars = [v_newjitstate2, v_boxes2] + read_boxes_block_vars = [] for greenvar in orig_key_v: read_boxes_block_vars.append(copyvar(None, greenvar)) read_boxes_block = flowmodel.Block(read_boxes_block_vars) - to_read_boxes_block = flowmodel.Link([v_newjitstate, v_boxes] + orig_key_v, read_boxes_block) - to_read_boxes_block.exitcase = to_read_boxes_block.llexitcase = True + to_read_boxes_block = flowmodel.Link(orig_key_v, read_boxes_block) + to_read_boxes_block.exitcase = to_read_boxes_block.llexitcase = False - to_dispatch_block = flowmodel.Link([v_oldjitstate], self.dispatchblock) - to_dispatch_block.exitcase = to_dispatch_block.llexitcase = False + to_dispatch_block = flowmodel.Link([], self.dispatchblock) + to_dispatch_block.exitcase = to_dispatch_block.llexitcase = True - target = before_block.exits[0].target - before_block.operations[:] = llops - before_block.exitswitch = v_continue - before_block.recloseblock(to_dispatch_block, to_read_boxes_block) - llops = HintLowLevelOpList(self, None) + next_block = before_block.exits[0].target - newinputargs2 = [v_newjitstate2] + before_block.operations[:] = llops + before_block.exitswitch = v_finished_flag + before_block.recloseblock(to_read_boxes_block, + to_dispatch_block) + + llops = HintLowLevelOpList(self) + v_jitstate2 = llops.getjitstate() + + linkargs = [] if not is_returnblock: i = 0 j = 0 - for r in args_r[1:]: + for newvar in newinputargs: + r = self.hrtyper.bindingrepr(newvar) if isinstance(r, RedRepr): - newinputargs2.append(self.read_out_box(llops, v_boxes2, i)) + linkargs.append(self.read_out_box(llops, v_jitstate2, i)) i += 1 else: - newinputargs2.append(read_boxes_block_vars[j+2]) + linkargs.append(read_boxes_block_vars[j]) j += 1 + target = next_block else: # xxx reorganize llops.genmixlevelhelpercall(rtimeshift.save_return, - [self.s_JITState, self.s_box_list], - [v_newjitstate2, v_boxes2], + [self.s_JITState], + [v_jitstate2], annmodel.s_None) target = self.dispatchblock read_boxes_block.operations[:] = llops - - to_target = flowmodel.Link(newinputargs2, target) - + to_target = flowmodel.Link(linkargs, target) read_boxes_block.closeblock(to_target) return cache @@ -436,7 +396,7 @@ # insert at the end of blocks the following logic: # if the block is the returnblock: # - # go to dispatch_block(jitstate) + # go to dispatch_block # # if the block has just one exit or the exitswitch is green: # @@ -468,14 +428,13 @@ exitswitch = block.exitswitch if len(exits) == 0: # this is the original returnblock - block.recloseblock(flowmodel.Link(block.inputargs[:1], - self.dispatchblock)) + block.recloseblock(flowmodel.Link([], self.dispatchblock)) elif (len(exits) == 1 or isinstance(self.hrtyper.bindingrepr(exitswitch), GreenRepr)): pass # nothing to do else: - llops = HintLowLevelOpList(self, None) - v_jitstate = self.getjitstate(block) + llops = HintLowLevelOpList(self) + v_jitstate = llops.getjitstate() assert len(exits) == 2 false_exit, true_exit = exits if true_exit.exitcase is False: @@ -486,13 +445,10 @@ true_exit.llexitcase = True false_exit.llexitcase = False v_boxes_true = self.pack_state_into_boxes(llops, - true_exit.args[1:], - v_jitstate, - pack_greens_too=False) + true_exit.args) v_boxes_false = self.pack_state_into_boxes(llops, - false_exit.args[1:], - v_jitstate, - pack_greens_too=True) + false_exit.args, + pack_greens_too = True) exitindex = self.getexitindex(false_exit, entering_links) c_exitindex = rmodel.inputconst(lltype.Signed, exitindex) v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split, @@ -511,8 +467,8 @@ block.operations.extend(llops) - def pack_state_into_boxes(self, llops, statevars, v_jitstate, - pack_greens_too): + def pack_state_into_boxes(self, llops, statevars, pack_greens_too=False): + v_jitstate = None boxes_v = [] for var in statevars: if isinstance(var, flowmodel.Constant): @@ -522,6 +478,8 @@ boxes_v.append(var) elif isinstance(r, GreenRepr): if pack_greens_too: + if v_jitstate is None: + v_jitstate = llops.getjitstate() v_box = self.make_const_box(llops, r, var, v_jitstate) boxes_v.append(v_box) else: @@ -530,53 +488,57 @@ # put the following logic in the dispatch block: # - # boxes = [] - # next = rtimeshift.dispatch_next(jitstate, boxes) + # nextjitstate = dispatch_next(jitstate) + # setjitstate(nextjitstate) + # next = getexitindex(nextjitstate) # switch next: # : - # go to reentry_block(jitstate, boxes) + # go to reentry_block # ... # default: - # go to prepare_return_block(jitstate) + # return nextjitstate # - # the prepare_return_block does: - # - # returnbox = prepare_return(jitstate) # where - # prepare_return = (lambda jitstate: - # rtimeshift.prepare_return(jitstate, return_cache, - # None))) # XXX return type info + # dispatch_next = (lambda jitstate: + # rtimeshift.dispatch_next(jitstate, + # return_cache)) # where return_cache is a predefined cache - # return returnbox # def insert_dispatch_logic(self): dispatchblock = self.dispatchblock - [v_jitstate] = dispatchblock.inputargs - llops = HintLowLevelOpList(self, None) + llops = HintLowLevelOpList(self) - v_returnbox = varoftype(self.r_RedBox.lowleveltype, 'returnbox') - returnblock = flowmodel.Block([v_returnbox]) - returnblock.operations = () - self.graph.returnblock = returnblock - - v_boxes = rlist.newlist(llops, self.r_box_accum, []) - v_next = llops.genmixlevelhelpercall(rtimeshift.dispatch_next, - [self.s_JITState, - self.s_box_accum], - [v_jitstate, v_boxes], - annmodel.SomeInteger()) + return_cache = self.return_cache + assert return_cache is not None + #RETURN_TYPE = self.r_returnvalue.original_concretetype + def dispatch_next(jitstate): + return rtimeshift.dispatch_next(jitstate, return_cache) + + v_nextjitstate = llops.genmixlevelhelpercall(dispatch_next, + [self.s_JITState ], + [llops.getjitstate()], + self.s_JITState) + llops.setjitstate(v_nextjitstate) + v_next = llops.genmixlevelhelpercall(rtimeshift.getexitindex, + [self.s_JITState], + [v_nextjitstate], + annmodel.SomeInteger()) dispatchblock.operations = list(llops) + # make a new return block + returnblock = flowmodel.Block([]) + returnblock.operations = () + self.graph.returnblock = returnblock + + # produce the dispatch switch dispatch_to = self.dispatch_to - v_jitstate2 = varoftype(self.r_JITState.lowleveltype, 'jitstate') - prepare_return_block = flowmodel.Block([v_jitstate2]) - prepare_return_link = flowmodel.Link([v_jitstate], prepare_return_block) - dispatch_to.append(('default', prepare_return_link)) + return_link = flowmodel.Link([], returnblock) + dispatch_to.append(('default', return_link)) if len(dispatch_to) == 1: - dispatchblock.closeblock(prepare_return_link) + dispatchblock.closeblock(return_link) else: dispatchblock.exitswitch = v_next exitlinks = [] @@ -584,67 +546,72 @@ link.exitcase = case if case != 'default': link.llexitcase = case - link.args = [v_jitstate, v_boxes] else: link.llexitcase = None exitlinks.append(link) dispatchblock.closeblock(*exitlinks) - return_cache = self.return_cache - assert return_cache is not None - RETURN_TYPE = self.r_returnvalue.original_concretetype - - def prepare_return(jitstate): - return rtimeshift.prepare_return(jitstate, return_cache, - None) - llops = HintLowLevelOpList(self, None) - v_return_builder = llops.genmixlevelhelpercall(prepare_return, - [self.s_JITState], [v_jitstate2], - self.s_RedBox) - - prepare_return_block.operations = list(llops) - finishedlink = flowmodel.Link([v_return_builder], returnblock) - prepare_return_block.closeblock(finishedlink) - - def getjitstate(self, block): - if block not in self.block2jitstate: - v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') - self.block2jitstate[block] = v_jitstate - return self.block2jitstate[block] def timeshift_block(self, timeshifted_blocks, entering_links, block): + hrtyper = self.hrtyper blocks = [block] i = 0 # XXX in-progress, split block at direct_calls for call support while i < len(block.operations): op = block.operations[i] - if op.opname == 'direct_call': + if (op.opname == 'direct_call' + and hrtyper.guess_call_kind(op) == 'red'): + link = support.split_block_with_keepalive(block, i+1, annotator=self.hannotator) # the 'save_locals' pseudo-operation is used to save all # alive local variables into the current JITState - args = list(link.args) - while op.result in args: - args.remove(op.result) + vars_to_save = [] + for var in link.args: + if isinstance(var, flowmodel.Variable): + if var is not op.result: + r = hrtyper.bindingrepr(var) + if isinstance(r, RedRepr): + vars_to_save.append(var) + assert op is block.operations[i] + assert len(block.operations) == i+1 v_dummy = varoftype(lltype.Void) self.hannotator.setbinding(v_dummy, annmodel.s_ImpossibleValue) extraop = flowmodel.SpaceOperation('save_locals', - args, + vars_to_save, v_dummy) block.operations.insert(i, extraop) + replacement = {} + # XXX for now, the call appends the return value box to + # the local_boxes of our jitstate, from where we can fish + # it using a 'restore_local' ----------vvvvvvvvvvv + for i, var in enumerate(vars_to_save + [op.result]): + newvar = copyvar(self.hannotator, var) + c_index = flowmodel.Constant(i, concretetype=lltype.Signed) + extraop = flowmodel.SpaceOperation('restore_local', + [c_index], + newvar) + block.operations.append(extraop) + replacement[var] = newvar + + link.args = [replacement.get(var, var) for var in link.args] block = link.target entering_links[block] = [link] blocks.append(block) self.hannotator.annotated[block] = self.graph + # for now the call doesn't return its redbox result, but only + # has the hidden side-effect of putting it in the jitstate + op.result = varoftype(lltype.Void) + self.hannotator.setbinding(op.result, + annmodel.s_ImpossibleValue) i = 0 continue i += 1 for block in blocks: - self.getjitstate(block) # force this to be precomputed - self.hrtyper.specialize_block(block) + hrtyper.specialize_block(block) timeshifted_blocks.extend(blocks) def originalconcretetype(self, var): Modified: pypy/dist/pypy/tool/uid.py ============================================================================== --- pypy/dist/pypy/tool/uid.py (original) +++ pypy/dist/pypy/tool/uid.py Mon Sep 4 21:37:49 2006 @@ -69,5 +69,5 @@ hasattr(self.value, '__name__')): r = '%s %s' % (type(self.value).__name__, self.value.__name__) elif len(r) > 60 or (len(r) > 30 and type(self.value) is not str): - r = r[:20] + '...' + r[-8:] + r = r[:22] + '...' + r[-7:] return r From arigo at codespeak.net Mon Sep 4 21:53:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Sep 2006 21:53:40 +0200 (CEST) Subject: [pypy-svn] r31995 - pypy/dist/pypy/translator/transformer Message-ID: <20060904195340.D797A1006E@code0.codespeak.net> Author: arigo Date: Mon Sep 4 21:53:39 2006 New Revision: 31995 Modified: pypy/dist/pypy/translator/transformer/basictransform.py Log: Forgot 'svn add' ? Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Mon Sep 4 21:53:39 2006 @@ -6,7 +6,7 @@ from pypy.translator.unsimplify import varoftype from pypy.annotation import model as annmodel from pypy.objspace.flow import model -from pypy.translator.js.helper import main_exception_helper, ExceptionHelper +#from pypy.translator.js.helper import main_exception_helper, ExceptionHelper from pypy.rpython.ootypesystem import ootype from pypy.rpython.ootypesystem import rclass from pypy.rpython.annlowlevel import MixLevelHelperAnnotator From rhymes at codespeak.net Tue Sep 5 11:29:34 2006 From: rhymes at codespeak.net (rhymes at codespeak.net) Date: Tue, 5 Sep 2006 11:29:34 +0200 (CEST) Subject: [pypy-svn] r31996 - pypy/dist/pypy/module/rctime Message-ID: <20060905092934.7667910075@code0.codespeak.net> Author: rhymes Date: Tue Sep 5 11:29:29 2006 New Revision: 31996 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: went back to math module because fmod breaks in linux. Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Tue Sep 5 11:29:29 2006 @@ -5,6 +5,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace from ctypes import * +import math import os import sys @@ -87,8 +88,7 @@ Sleep.restype = None libc.strftime.argtypes = [c_char_p, size_t, c_char_p, POINTER(tm)] libc.strftime.restype = size_t -libc.fmod.argtypes = [c_double, c_double] -libc.fmod.restype = c_double + def _init_accept2dyear(): return (1, 0)[bool(os.getenv("PYTHONY2K"))] @@ -266,7 +266,7 @@ buf.tm_year = y - 1900 buf.tm_mon = buf.tm_mon - 1 - buf.tm_wday = int(libc.fmod((buf.tm_wday + 1), 7)) + buf.tm_wday = int(math.fmod((buf.tm_wday + 1), 7)) buf.tm_yday = buf.tm_yday - 1 return buf From arigo at codespeak.net Tue Sep 5 12:43:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Sep 2006 12:43:05 +0200 (CEST) Subject: [pypy-svn] r31999 - pypy/dist/pypy/annotation/test Message-ID: <20060905104305.055EA10075@code0.codespeak.net> Author: arigo Date: Tue Sep 5 12:43:03 2006 New Revision: 31999 Modified: pypy/dist/pypy/annotation/test/test_model.py Log: Need a pseudo-bookkeeper for this test. Modified: pypy/dist/pypy/annotation/test/test_model.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_model.py (original) +++ pypy/dist/pypy/annotation/test/test_model.py Tue Sep 5 12:43:03 2006 @@ -89,8 +89,8 @@ assert commonbase(A2,B3) is A0 def test_list_union(): - listdef1 = ListDef(None, SomeInteger(nonneg=True)) - listdef2 = ListDef(None, SomeInteger(nonneg=False)) + listdef1 = ListDef('dummy', SomeInteger(nonneg=True)) + listdef2 = ListDef('dummy', SomeInteger(nonneg=False)) s1 = SomeList(listdef1) s2 = SomeList(listdef2) assert s1 != s2 From cfbolz at codespeak.net Tue Sep 5 12:56:54 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Sep 2006 12:56:54 +0200 (CEST) Subject: [pypy-svn] r32000 - pypy/dist/pypy/doc Message-ID: <20060905105654.7848610072@code0.codespeak.net> Author: cfbolz Date: Tue Sep 5 12:56:53 2006 New Revision: 32000 Modified: pypy/dist/pypy/doc/news.txt Log: intentionally wrong rest for testing the mail notification Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Tue Sep 5 12:56:53 2006 @@ -31,12 +31,12 @@ Ireland sprint 21st-27th August ================================================================== -The next PyPy sprint will happen in the nice city of +``The last PyPy sprint happened in the nice city of Limerick in Ireland from 21st till 27th August. -The main focus of the sprint will be on JIT compiler works, +The main focus of the sprint was on JIT compiler works, various optimization works, porting extension modules, -infrastructure works like a build tool for PyPy, or -extended (distributed) testing. It's also open to new topics. +infrastructure works like a build tool for PyPy and +extended (distributed) testing. Read the full `announcement`_ for more details. .. _`announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ireland-2006/announce.html From rhymes at codespeak.net Tue Sep 5 12:59:47 2006 From: rhymes at codespeak.net (rhymes at codespeak.net) Date: Tue, 5 Sep 2006 12:59:47 +0200 (CEST) Subject: [pypy-svn] r32001 - in pypy/dist/pypy/lib: . test2 Message-ID: <20060905105947.3745C10079@code0.codespeak.net> Author: rhymes Date: Tue Sep 5 12:59:44 2006 New Revision: 32001 Added: pypy/dist/pypy/lib/test2/test_binascii.py (contents, props changed) Modified: pypy/dist/pypy/lib/binascii.py Log: Resolved issue #250: crc32 reported uncorrect results because of the implicit between int and longs in CPython. Also added the CPython test case for binascii module. Thanks Jerub. Modified: pypy/dist/pypy/lib/binascii.py ============================================================================== --- pypy/dist/pypy/lib/binascii.py (original) +++ pypy/dist/pypy/lib/binascii.py Tue Sep 5 12:59:44 2006 @@ -642,6 +642,9 @@ #/* Note: (crc >> 8) MUST zero fill on left result = crc ^ 0xffffffffL + + if result > 2**31: + result = ((result + 2**31) % 2**32) - 2**31 return result Added: pypy/dist/pypy/lib/test2/test_binascii.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/test2/test_binascii.py Tue Sep 5 12:59:44 2006 @@ -0,0 +1,148 @@ +from pypy.lib import binascii + +# Create binary test data +data = "The quick brown fox jumps over the lazy dog.\r\n" +# Be slow so we don't depend on other modules +data += "".join(map(chr, xrange(256))) +data += "\r\nHello world.\n" + +def test_exceptions(): + # Check module exceptions + assert issubclass(binascii.Error, Exception) + assert issubclass(binascii.Incomplete, Exception) + +def test_functions(): + # Check presence of all functions + funcs = [] + for suffix in "base64", "hqx", "uu", "hex": + prefixes = ["a2b_", "b2a_"] + if suffix == "hqx": + prefixes.extend(["crc_", "rlecode_", "rledecode_"]) + for prefix in prefixes: + name = prefix + suffix + assert callable(getattr(binascii, name)) + raises(TypeError, getattr(binascii, name)) + for name in ("hexlify", "unhexlify"): + assert callable(getattr(binascii, name)) + raises(TypeError, getattr(binascii, name)) + +def test_base64valid(): + # Test base64 with valid data + MAX_BASE64 = 57 + lines = [] + for i in range(0, len(data), MAX_BASE64): + b = data[i:i+MAX_BASE64] + a = binascii.b2a_base64(b) + lines.append(a) + res = "" + for line in lines: + b = binascii.a2b_base64(line) + res = res + b + assert res == data + +def test_base64invalid(): + # Test base64 with random invalid characters sprinkled throughout + # (This requires a new version of binascii.) + MAX_BASE64 = 57 + lines = [] + for i in range(0, len(data), MAX_BASE64): + b = data[i:i+MAX_BASE64] + a = binascii.b2a_base64(b) + lines.append(a) + + fillers = "" + valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" + for i in xrange(256): + c = chr(i) + if c not in valid: + fillers += c + def addnoise(line): + noise = fillers + ratio = len(line) // len(noise) + res = "" + while line and noise: + if len(line) // len(noise) > ratio: + c, line = line[0], line[1:] + else: + c, noise = noise[0], noise[1:] + res += c + return res + noise + line + res = "" + for line in map(addnoise, lines): + b = binascii.a2b_base64(line) + res += b + assert res == data + + # Test base64 with just invalid characters, which should return + # empty strings. TBD: shouldn't it raise an exception instead ? + assert binascii.a2b_base64(fillers) == '' + +def test_uu(): + MAX_UU = 45 + lines = [] + for i in range(0, len(data), MAX_UU): + b = data[i:i+MAX_UU] + a = binascii.b2a_uu(b) + lines.append(a) + res = "" + for line in lines: + b = binascii.a2b_uu(line) + res += b + assert res == data + + assert binascii.a2b_uu("\x7f") == "\x00"*31 + assert binascii.a2b_uu("\x80") == "\x00"*32 + assert binascii.a2b_uu("\xff") == "\x00"*31 + raises(binascii.Error, binascii.a2b_uu, "\xff\x00") + raises(binascii.Error, binascii.a2b_uu, "!!!!") + + raises(binascii.Error, binascii.b2a_uu, 46*"!") + +def test_crc32(): + crc = binascii.crc32("Test the CRC-32 of") + crc = binascii.crc32(" this string.", crc) + assert crc == 1571220330 + + crc = binascii.crc32('frotz\n', 0) + assert crc == -372923920 + + raises(TypeError, binascii.crc32) + +def test_hex(): + # test hexlification + s = '{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000' + t = binascii.b2a_hex(s) + u = binascii.a2b_hex(t) + assert s == u + raises(TypeError, binascii.a2b_hex, t[:-1]) + raises(TypeError, binascii.a2b_hex, t[:-1] + 'q') + + # Verify the treatment of Unicode strings + assert binascii.hexlify(unicode('a', 'ascii')) == '61' + +def test_qp(): + # A test for SF bug 534347 (segfaults without the proper fix) + try: + binascii.a2b_qp("", **{1:1}) + except TypeError: + pass + else: + fail("binascii.a2b_qp(**{1:1}) didn't raise TypeError") + assert binascii.a2b_qp("= ") == "" + assert binascii.a2b_qp("==") == "=" + assert binascii.a2b_qp("=AX") == "=AX" + raises(TypeError, binascii.b2a_qp, foo="bar") + assert binascii.a2b_qp("=00\r\n=00") == "\x00\r\n\x00" + assert binascii.b2a_qp("\xff\r\n\xff\n\xff") == "=FF\r\n=FF\r\n=FF" + target = "0"*75+"=\r\n=FF\r\n=FF\r\n=FF" + assert binascii.b2a_qp("0"*75+"\xff\r\n\xff\r\n\xff") == target + +def test_empty_string(): + # A test for SF bug #1022953. Make sure SystemError is not raised. + for n in ['b2a_qp', 'a2b_hex', 'b2a_base64', 'a2b_uu', 'a2b_qp', + 'b2a_hex', 'unhexlify', 'hexlify', 'crc32', 'b2a_hqx', + 'a2b_hqx', 'a2b_base64', 'rlecode_hqx', 'b2a_uu', + 'rledecode_hqx']: + f = getattr(binascii, n) + f('') + binascii.crc_hqx('', 0) From arigo at codespeak.net Tue Sep 5 13:25:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Sep 2006 13:25:02 +0200 (CEST) Subject: [pypy-svn] r32004 - in pypy/dist/pypy: annotation objspace/std rpython rpython/lltypesystem rpython/ootypesystem translator translator/test Message-ID: <20060905112502.2321410072@code0.codespeak.net> Author: arigo Date: Tue Sep 5 13:24:57 2006 New Revision: 32004 Modified: pypy/dist/pypy/annotation/listdef.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/objspace/std/setobject.py pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/ootypesystem/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/geninterplevel.py pypy/dist/pypy/translator/simplify.py pypy/dist/pypy/translator/test/test_simplify.py pypy/dist/pypy/translator/translator.py Log: Finished the list comprehension optimization. Disabled by default for now, until we know a bit more if it really gives any benefit and/or what kind of subtle bugs it contains. Modified: pypy/dist/pypy/annotation/listdef.py ============================================================================== --- pypy/dist/pypy/annotation/listdef.py (original) +++ pypy/dist/pypy/annotation/listdef.py Tue Sep 5 13:24:57 2006 @@ -170,7 +170,9 @@ self.listitem.generalize(s_value) def __repr__(self): - return '<[%r]>' % (self.listitem.s_value,) + return '<[%r]%s%s>' % (self.listitem.s_value, + self.listitem.mutated and 'm' or '', + self.listitem.resized and 'r' or '') def mutate(self): self.listitem.mutate() Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Tue Sep 5 13:24:57 2006 @@ -24,7 +24,7 @@ 'iter', 'next', 'invert', 'type', 'issubtype', 'pos', 'neg', 'nonzero', 'abs', 'hex', 'oct', 'ord', 'int', 'float', 'long', 'id', - 'neg_ovf', 'abs_ovf']) + 'neg_ovf', 'abs_ovf', 'hint']) for opname in UNARY_OPERATIONS: missing_operation(SomeObject, opname) @@ -177,6 +177,9 @@ def op_contains(obj, s_element): return SomeBool() + def hint(self, *args_s): + return self + class __extend__(SomeFloat): def pos(flt): @@ -314,6 +317,20 @@ lst.listdef.generalize(s_element) return SomeBool() + def hint(lst, *args_s): + hints = args_s[-1].const + if 'maxlength' in hints: + # only for iteration over lists or dicts at the moment, + # not over an iterator object (because it has no known length) + s_iterable = args_s[0] + if isinstance(s_iterable, (SomeList, SomeDict)): + lst.listdef.resize() + lst.listdef.listitem.hint_maxlength = True + elif 'fence' in hints: + lst = lst.listdef.offspring() + return lst + + class __extend__(SomeDict): def len(dct): Modified: pypy/dist/pypy/objspace/std/setobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/setobject.py (original) +++ pypy/dist/pypy/objspace/std/setobject.py Tue Sep 5 13:24:57 2006 @@ -116,7 +116,7 @@ def _is_eq(w_left, w_right): if len(w_left.setdata) != len(w_right.setdata): return False - for w_key in w_left.setdata.iterkeys(): + for w_key in w_left.setdata: if w_key not in w_right.setdata: return False return True @@ -135,7 +135,7 @@ else: ld = ldict.copy() del_list_w = [] - for w_key in ld.iterkeys(): + for w_key in ld: if w_key in rdict: del_list_w.append(w_key) for w_key in del_list_w: @@ -149,7 +149,7 @@ else: ld = ldict.copy() del_list_w = [] - for w_key in ld.iterkeys(): + for w_key in ld: if w_key not in rdict: del_list_w.append(w_key) @@ -166,11 +166,11 @@ ld = ldict.copy() del_list_w = [] add_list_w = [] - for w_key in ld.iterkeys(): + for w_key in ld: if w_key in rdict: del_list_w.append(w_key) - for w_key in rdict.iterkeys(): + for w_key in rdict: if w_key not in ld: add_list_w.append(w_key) @@ -387,7 +387,7 @@ return space.wrap(w_set.hash) hash = 1927868237 hash *= (len(w_set.setdata) + 1) - for w_item in w_set.setdata.iterkeys(): + for w_item in w_set.setdata: h = space.hash_w(w_item) value = ((h ^ (h << 16) ^ 89869747) * multi) hash = intmask(hash ^ value) Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Tue Sep 5 13:24:57 2006 @@ -81,6 +81,20 @@ temp), rstr.list_str_close_bracket)) + def get_itemarray_lowleveltype(self): + ITEM = self.item_repr.lowleveltype + ITEMARRAY = GcArray(ITEM, + adtmeths = ADTIFixedList({ + "ll_newlist": ll_fixed_newlist, + "ll_length": ll_fixed_length, + "ll_items": ll_fixed_items, + ##"list_builder": self.list_builder, + "ITEM": ITEM, + "ll_getitem_fast": ll_fixed_getitem_fast, + "ll_setitem_fast": ll_fixed_setitem_fast, + })) + return ITEMARRAY + ##class ListBuilder(object): ## """Interface to allow lazy list building by the JIT.""" @@ -179,7 +193,7 @@ self.external_item_repr, self.item_repr = externalvsinternal(self.rtyper, self._item_repr_computer()) if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype - ITEMARRAY = GcArray(ITEM) + ITEMARRAY = self.get_itemarray_lowleveltype() # XXX we might think of turning length stuff into Unsigned self.LIST.become(GcStruct("list", ("length", Signed), ("items", Ptr(ITEMARRAY)), @@ -206,6 +220,41 @@ result.items = malloc(self.LIST.items.TO, n) return result + def rtype_method_append(self, hop): + if getattr(self.listitem, 'hint_maxlength', False): + v_lst, v_value = hop.inputargs(self, self.item_repr) + hop.exception_cannot_occur() + hop.gendirectcall(ll_append_noresize, v_lst, v_value) + else: + AbstractListRepr.rtype_method_append(self, hop) + + def rtype_hint(self, hop): + optimized = getattr(self.listitem, 'hint_maxlength', False) + hints = hop.args_s[-1].const + if 'maxlength' in hints: + if optimized: + s_iterable = hop.args_s[1] + r_iterable = hop.args_r[1] + v_list = hop.inputarg(self, arg=0) + v_iterable = hop.inputarg(r_iterable, arg=1) + hop2 = hop.copy() + while hop2.nb_args > 0: + hop2.r_s_popfirstarg() + hop2.v_s_insertfirstarg(v_iterable, s_iterable) + v_maxlength = r_iterable.rtype_len(hop2) + hop.llops.gendirectcall(ll_set_maxlength, v_list, v_maxlength) + return v_list + if 'fence' in hints: + v_list = hop.inputarg(self, arg=0) + if isinstance(hop.r_result, FixedSizeListRepr): + if optimized and 'exactlength' in hints: + llfn = ll_list2fixed_exact + else: + llfn = ll_list2fixed + v_list = hop.llops.gendirectcall(llfn, v_list) + return v_list + return AbstractListRepr.rtype_hint(self, hop) + class FixedSizeListRepr(AbstractFixedSizeListRepr, BaseListRepr): @@ -214,17 +263,7 @@ self.external_item_repr, self.item_repr = externalvsinternal(self.rtyper, self._item_repr_computer()) if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype - ITEMARRAY = GcArray(ITEM, - adtmeths = ADTIFixedList({ - "ll_newlist": ll_fixed_newlist, - "ll_length": ll_fixed_length, - "ll_items": ll_fixed_items, - ##"list_builder": self.list_builder, - "ITEM": ITEM, - "ll_getitem_fast": ll_fixed_getitem_fast, - "ll_setitem_fast": ll_fixed_setitem_fast, - })) - + ITEMARRAY = self.get_itemarray_lowleveltype() self.LIST.become(ITEMARRAY) def compact_repr(self): @@ -317,6 +356,12 @@ _ll_list_resize_really(l, newsize) +def ll_append_noresize(l, newitem): + length = l.length + l.length = length + 1 + l.ll_setitem_fast(length, newitem) +ll_append_noresize.oopspec = 'list.append(l, newitem)' + TEMP = GcArray(Ptr(rstr.STR)) @@ -378,6 +423,25 @@ llops.gendirectcall(ll_setitem_nonneg, v_func, v_result, ci, v_item) return v_result +# special operations for list comprehension optimization +def ll_set_maxlength(l, n): + LIST = typeOf(l).TO + l.items = malloc(LIST.items.TO, n) + +def ll_list2fixed(l): + n = l.length + olditems = l.items + if n == len(olditems): + return olditems + else: + LIST = typeOf(l).TO + newitems = malloc(LIST.items.TO, n) + for i in range(n): + newitems[i] = olditems[i] + return newitems + +def ll_list2fixed_exact(l): + return l.items # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Tue Sep 5 13:24:57 2006 @@ -76,6 +76,16 @@ buf.ll_append_char(']') return buf.ll_build() + def rtype_hint(self, hop): + hints = hop.args_s[-1].const + if 'maxlength' in hints: + v_list = hop.inputarg(self, arg=0) + # XXX give a hint to pre-allocate the list (see lltypesystem/rlist) + return v_list + if 'fence' in hints: + return hop.inputarg(self, arg=0) + return AbstractBaseListRepr.rtype_hint(self, hop) + class ListRepr(AbstractListRepr, BaseListRepr): Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Sep 5 13:24:57 2006 @@ -232,6 +232,9 @@ def make_iterator_repr(self, *variant): raise TyperError("%s is not iterable" % (self,)) + def rtype_hint(self, hop): + return hop.inputarg(hop.r_result, arg=0) + # hlinvoke helpers def get_r_implfunc(self): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Sep 5 13:24:57 2006 @@ -551,13 +551,13 @@ # __________ irregular operations __________ def translate_op_newlist(self, hop): - return self.type_system.rlist.rtype_newlist(hop) + return rlist.rtype_newlist(hop) def translate_op_newdict(self, hop): return self.type_system.rdict.rtype_newdict(hop) def translate_op_alloc_and_set(self, hop): - return self.type_system.rlist.rtype_alloc_and_set(hop) + return rlist.rtype_alloc_and_set(hop) def translate_op_newtuple(self, hop): return self.type_system.rtuple.rtype_newtuple(hop) @@ -903,7 +903,7 @@ from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat from pypy.rpython import rslice, rrange -from pypy.rpython import rstr, rdict +from pypy.rpython import rstr, rdict, rlist from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase from pypy.rpython import rexternalobj from pypy.rpython import rptr Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Tue Sep 5 13:24:57 2006 @@ -282,6 +282,9 @@ "shape": repr(shape), "data_w": self.arglist(op.args[2:], localscope), 'Arg': self.nameof(Arguments) } + if op.opname == "hint": + return "%s = %s" % (self.expr(op.result, localscope), + self.expr(op.args[0], localscope)) if op.opname in self.has_listarg: fmt = "%s = %s([%s])" else: @@ -1486,7 +1489,8 @@ entrypoint = dic t = TranslationContext(verbose=False, simplifying=needed_passes, do_imports_immediately=do_imports_immediately, - builtins_can_raise_exceptions=True) + builtins_can_raise_exceptions=True, + list_comprehension_operations=False) gen = GenRpy(t, entrypoint, modname, dic) finally: Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Tue Sep 5 13:24:57 2006 @@ -710,15 +710,16 @@ # ____________________________________________________________ def detect_list_comprehension(graph): - """Look for the pattern: Replace it with marker operations: + """Look for the pattern: Replace it with marker operations: - v1 = newlist() v0 = newlistbuilder(length) - loop start loop start - ... ... - exactly one append per loop v0.append(..) - and nothing else done with v1 - ... ... - loop end v1 = listbuilder_done(v0) + v0 = newlist() + v2 = newlist() v1 = hint(v0, iterable, {'maxlength'}) + loop start loop start + ... ... + exactly one append per loop v1.append(..) + and nothing else done with v2 + ... ... + loop end v2 = hint(v1, {'fence'}) """ # NB. this assumes RPythonicity: we can only iterate over something # that has a len(), and this len() cannot change as long as we are @@ -781,12 +782,17 @@ return detector = ListComprehensionDetector(graph, loops, newlist_v, variable_families) + graphmutated = False for location in append_v: + if graphmutated: + # new variables introduced, must restart the whole process + return detect_list_comprehension(graph) try: detector.run(*location) except DetectorFailed: pass - + else: + graphmutated = True class DetectorFailed(Exception): pass @@ -798,6 +804,7 @@ self.loops = loops self.newlist_v = newlist_v self.variable_families = variable_families + self.reachable_cache = {} def enum_blocks_from(self, fromblock, avoid): found = {avoid: True} @@ -811,7 +818,7 @@ for exit in block.exits: pending.append(exit.target) - def enum_reachable_blocks(self, fromblock, stop_at): + def enum_reachable_blocks(self, fromblock, stop_at, stay_within=None): if fromblock is stop_at: return found = {stop_at: True} @@ -822,15 +829,35 @@ continue found[block] = True for exit in block.exits: - yield exit.target - pending.append(exit.target) + if stay_within is None or exit.target in stay_within: + yield exit.target + pending.append(exit.target) + + def reachable_within(self, fromblock, toblock, avoid, stay_within): + if toblock is avoid: + return False + for block in self.enum_reachable_blocks(fromblock, avoid, stay_within): + if block is toblock: + return True + return False def reachable(self, fromblock, toblock, avoid): if toblock is avoid: return False + try: + return self.reachable_cache[fromblock, toblock, avoid] + except KeyError: + pass + future = [fromblock] for block in self.enum_reachable_blocks(fromblock, avoid): + self.reachable_cache[fromblock, block, avoid] = True if block is toblock: return True + future.append(block) + # 'toblock' is unreachable from 'fromblock', so it is also + # unreachable from any of the 'future' blocks + for block in future: + self.reachable_cache[block, toblock, avoid] = False return False def vlist_alive(self, block): @@ -965,29 +992,21 @@ raise DetectorFailed # no suitable loop # Found a suitable loop, let's patch the graph: - - # - remove newlist() - for op in newlistblock.operations: - if op.opname == 'newlist': - res = self.variable_families.find_rep(op.result) - if res is self.vlistfamily: - newlistblock.operations.remove(op) - break - else: - raise AssertionError("bad newlistblock") - - # - remove the vlist variable from all blocks of the loop header, - # up to the iterblock - for block in loopheader: - if block is not newlistblock: - self.remove_vlist(block.inputargs) - if block is not iterblock: - for link in block.exits: - self.remove_vlist(link.args) - - # - add a newlistbuilder() in the iterblock, where we can compute - # the known maximum length - vlist = self.contains_vlist(iterblock.exits[0].args) + assert iterblock not in loopbody + assert loopnextblock in loopbody + assert stopblock not in loopbody + + # at StopIteration, the new list is exactly of the same length as + # the one we iterate over if it's not possible to skip the appendblock + # in the body: + exactlength = not self.reachable_within(loopnextblock, loopnextblock, + avoid = appendblock, + stay_within = loopbody) + + # - add a hint(vlist, iterable, {'maxlength'}) in the iterblock, + # where we can compute the known maximum length + link = iterblock.exits[0] + vlist = self.contains_vlist(link.args) assert vlist for op in iterblock.operations: res = self.variable_families.find_rep(op.result) @@ -996,11 +1015,16 @@ else: raise AssertionError("lost 'iter' operation") vlength = Variable('maxlength') + vlist2 = Variable(vlist) + chint = Constant({'maxlength': True}) iterblock.operations += [ - SpaceOperation('len', [op.args[0]], vlength), - SpaceOperation('newlistbuilder', [vlength], vlist)] + SpaceOperation('hint', [vlist, op.args[0], chint], vlist2)] + link.args = list(link.args) + for i in range(len(link.args)): + if link.args[i] is vlist: + link.args[i] = vlist2 - # - wherever the list exits the loop body, add a 'listbuilder_done' + # - wherever the list exits the loop body, add a 'hint({fence})' from pypy.translator.unsimplify import insert_empty_block for block in loopbody: for link in block.exits: @@ -1008,13 +1032,18 @@ vlist = self.contains_vlist(link.args) if vlist is None: continue # list not passed along this link anyway + hints = {'fence': True} + if (exactlength and block is loopnextblock and + link.target is stopblock): + hints['exactlength'] = True + chints = Constant(hints) newblock = insert_empty_block(None, link) index = link.args.index(vlist) vlist2 = newblock.inputargs[index] - vlist3 = Variable('listbuilder') + vlist3 = Variable(vlist2) newblock.inputargs[index] = vlist3 newblock.operations.append( - SpaceOperation('listbuilder_done', [vlist3], vlist2)) + SpaceOperation('hint', [vlist3, chints], vlist2)) # done! Modified: pypy/dist/pypy/translator/test/test_simplify.py ============================================================================== --- pypy/dist/pypy/translator/test/test_simplify.py (original) +++ pypy/dist/pypy/translator/test/test_simplify.py Tue Sep 5 13:24:57 2006 @@ -198,12 +198,91 @@ if conftest.option.view: graph.show() assert summary(graph) == { + 'newlist': 1, 'iter': 1, - 'len': 1, - 'newlistbuilder': 1, 'next': 1, 'mul': 1, 'getattr': 1, 'simple_call': 1, - 'listbuilder_done': 1, + 'hint': 2, } + +class TestLLSpecializeListComprehension: + typesystem = 'lltype' + + def specialize(self, func, argtypes): + from pypy.rpython.llinterp import LLInterpreter + t = TranslationContext(list_comprehension_operations=True) + t.buildannotator().build_types(func, argtypes) + if conftest.option.view: + t.view() + t.buildrtyper(self.typesystem).specialize() + if self.typesystem == 'lltype': + backend_optimizations(t) + if conftest.option.view: + t.view() + graph = graphof(t, func) + interp = LLInterpreter(t.rtyper) + return interp, graph + + def test_simple(self): + def main(n): + lst = [x*17 for x in range(n)] + return lst[5] + interp, graph = self.specialize(main, [int]) + res = interp.eval_graph(graph, [10]) + assert res == 5 * 17 + + def test_mutated_after_listcomp(self): + def main(n): + lst = [x*17 for x in range(n)] + lst.append(-42) + return lst[5] + interp, graph = self.specialize(main, [int]) + res = interp.eval_graph(graph, [10]) + assert res == 5 * 17 + res = interp.eval_graph(graph, [5]) + assert res == -42 + + def test_two_loops(self): + def main(n, m): + lst1 = [] + lst2 = [] + for i in range(n): + lst1.append(i) + for i in range(m): + lst2.append(i) + sum = 0 + for i in lst1: + sum += i + for i in lst2: + sum -= i + return sum + interp, graph = self.specialize(main, [int, int]) + res = interp.eval_graph(graph, [8, 3]) + assert res == 28 - 3 + + def test_list_iterator(self): + # for now, this is not optimized as a list comp + def main(n): + r = range(n) + lst = [i*17 for i in iter(r)] + return lst[5] + interp, graph = self.specialize(main, [int]) + res = interp.eval_graph(graph, [8]) + assert res == 5 * 17 + + def test_dict_iterator(self): + # for now, this is not optimized as a list comp + def main(n, m): + d = {n: m, m: n} + lst = [i*17 for i in d.iterkeys()] + return len(lst) + lst[0] + lst[-1] + interp, graph = self.specialize(main, [int, int]) + res = interp.eval_graph(graph, [8, 5]) + assert res == 2 + 8 * 17 + 5 * 17 + res = interp.eval_graph(graph, [4, 4]) + assert res == 1 + 4 * 17 + 4 * 17 + +class TestOOSpecializeListComprehension(TestLLSpecializeListComprehension): + typesystem = 'ootype' Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Tue Sep 5 13:24:57 2006 @@ -21,7 +21,7 @@ 'simplifying': True, 'do_imports_immediately': True, 'builtins_can_raise_exceptions': False, - 'list_comprehension_operations': False, + 'list_comprehension_operations': False, # True, - not super-tested } def __init__(self, **flowing_flags): From pedronis at codespeak.net Tue Sep 5 14:47:45 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Sep 2006 14:47:45 +0200 (CEST) Subject: [pypy-svn] r32008 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060905124745.3565810077@code0.codespeak.net> Author: pedronis Date: Tue Sep 5 14:47:37 2006 New Revision: 32008 Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (arre, pedronis) bug fix and test for cast_pointer timeshifting. Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Tue Sep 5 14:47:37 2006 @@ -217,7 +217,7 @@ def translate_op_cast_pointer(self, hop): FROM_TYPE = originalconcretetype(hop.args_s[0]) - v_argbox = hop.inputargs(self.getredrepr(FROM_TYPE)) + [v_argbox] = hop.inputargs(self.getredrepr(FROM_TYPE)) return v_argbox def translate_op_malloc(self, hop): Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Tue Sep 5 14:47:37 2006 @@ -704,6 +704,24 @@ assert res == 42 self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) + + def test_red_subcontainer_cast(self): + S = lltype.GcStruct('S', ('n', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float)) + def ll_function(k): + t = lltype.malloc(T) + s = lltype.cast_pointer(lltype.Ptr(S), t) + s.n = k + if k < 0: + return -123 + result = s.n * (k-1) + keepalive_until_here(t) + return result + res = self.timeshift(ll_function, [7], [], policy=P_NOVIRTUAL) + assert res == 42 + self.check_insns({'int_lt': 1, 'int_mul': 1, 'int_sub': 1}) + + def test_merge_structures(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) T = lltype.GcStruct('T', ('s', lltype.Ptr(S)), ('n', lltype.Signed)) From cfbolz at codespeak.net Tue Sep 5 15:30:06 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Sep 2006 15:30:06 +0200 (CEST) Subject: [pypy-svn] r32009 - pypy/dist/pypy/doc Message-ID: <20060905133006.B970010079@code0.codespeak.net> Author: cfbolz Date: Tue Sep 5 15:30:03 2006 New Revision: 32009 Modified: pypy/dist/pypy/doc/news.txt Log: fix rest Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Tue Sep 5 15:30:03 2006 @@ -31,7 +31,7 @@ Ireland sprint 21st-27th August ================================================================== -``The last PyPy sprint happened in the nice city of +The last PyPy sprint happened in the nice city of Limerick in Ireland from 21st till 27th August. The main focus of the sprint was on JIT compiler works, various optimization works, porting extension modules, From pedronis at codespeak.net Tue Sep 5 15:31:11 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Sep 2006 15:31:11 +0200 (CEST) Subject: [pypy-svn] r32010 - pypy/dist/pypy/jit/hintannotator/test Message-ID: <20060905133111.5A95510079@code0.codespeak.net> Author: pedronis Date: Tue Sep 5 15:31:09 2006 New Revision: 32010 Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Log: (arre, pedronis) adding some tests about exceptions, skipped for now. Some pass, but what we want to achieve is exception transform the graphs before hint annotating them. Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Tue Sep 5 15:31:09 2006 @@ -470,3 +470,45 @@ py.test.skip("in-progress: I think we expect a HintError here, do we?") py.test.raises(HintError, hannotate, ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))]) + + +def test_raise_exc(): + py.test.skip("work in-progress") + class E(Exception): + pass + def f1(): + raise E + hannotate(f1, [], policy=P_OOPSPEC_NOVIRTUAL) + + def f2(): + e = E() + e.a = 3 + raise e + hannotate(f2, [], policy=P_OOPSPEC_NOVIRTUAL) + + +def test_raise_and_catch_exc(): + py.test.skip("work in-progress") + class E(Exception): + pass + def f(flag): + if flag: + raise E + + def g(flag): + try: + f(flag) + except E: + return -1 + return 0 + + hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) + + def f(flag): + if flag: + e = E() + e.a = 3 + raise e + + hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) + From cfbolz at codespeak.net Tue Sep 5 15:35:32 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Sep 2006 15:35:32 +0200 (CEST) Subject: [pypy-svn] r32011 - pypy/dist/pypy/doc Message-ID: <20060905133532.EE3A210079@code0.codespeak.net> Author: cfbolz Date: Tue Sep 5 15:35:32 2006 New Revision: 32011 Modified: pypy/dist/pypy/doc/news.txt Log: once again, intentionally bad rest to test the error reporting Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Tue Sep 5 15:35:32 2006 @@ -1,4 +1,4 @@ -The PyPy project aims at producing a flexible and fast Python_ +``The PyPy project aims at producing a flexible and fast Python_ implementation. The guiding idea is to translate a Python-level description of the Python language itself to lower level languages. Rumors have it that the secret goal is being faster-than-C which is From cfbolz at codespeak.net Tue Sep 5 16:12:52 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Sep 2006 16:12:52 +0200 (CEST) Subject: [pypy-svn] r32012 - pypy/dist/pypy/doc Message-ID: <20060905141252.F22A910079@code0.codespeak.net> Author: cfbolz Date: Tue Sep 5 16:12:52 2006 New Revision: 32012 Modified: pypy/dist/pypy/doc/news.txt Log: yet another faulty rest checkin (sorry for the spam mails) Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Tue Sep 5 16:12:52 2006 @@ -1,4 +1,4 @@ -``The PyPy project aims at producing a flexible and fast Python_ +**The PyPy project aims at producing a flexible and fast Python_ implementation. The guiding idea is to translate a Python-level description of the Python language itself to lower level languages. Rumors have it that the secret goal is being faster-than-C which is From cfbolz at codespeak.net Tue Sep 5 16:25:09 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Sep 2006 16:25:09 +0200 (CEST) Subject: [pypy-svn] r32013 - pypy/dist/pypy/doc Message-ID: <20060905142509.EAC591007A@code0.codespeak.net> Author: cfbolz Date: Tue Sep 5 16:25:09 2006 New Revision: 32013 Modified: pypy/dist/pypy/doc/news.txt Log: works now, rest back to a legal state Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Tue Sep 5 16:25:09 2006 @@ -1,4 +1,4 @@ -**The PyPy project aims at producing a flexible and fast Python_ +The PyPy project aims at producing a flexible and fast Python_ implementation. The guiding idea is to translate a Python-level description of the Python language itself to lower level languages. Rumors have it that the secret goal is being faster-than-C which is From ac at codespeak.net Tue Sep 5 16:35:35 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 5 Sep 2006 16:35:35 +0200 (CEST) Subject: [pypy-svn] r32014 - pypy/dist/pypy/rpython/memory Message-ID: <20060905143535.2C47B1007B@code0.codespeak.net> Author: ac Date: Tue Sep 5 16:35:34 2006 New Revision: 32014 Modified: pypy/dist/pypy/rpython/memory/gc.py Log: Turn of spamming by default. Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Tue Sep 5 16:35:34 2006 @@ -109,7 +109,7 @@ return init_gc_object_immortal = init_gc_object -DEBUG_PRINT = True +DEBUG_PRINT = False memoryError = MemoryError() class MarkSweepGC(GCBase): _alloc_flavor_ = "raw" From pedronis at codespeak.net Tue Sep 5 18:35:14 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Sep 2006 18:35:14 +0200 (CEST) Subject: [pypy-svn] r32018 - pypy/dist/pypy/annotation Message-ID: <20060905163514.DCBFA10079@code0.codespeak.net> Author: pedronis Date: Tue Sep 5 18:35:13 2006 New Revision: 32018 Modified: pypy/dist/pypy/annotation/annrpython.py Log: (arre, pedronis) let takes the base annotator extra_passes too. For the hint-annotator for which simplifying makes sense too but not the extra_passes. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Tue Sep 5 18:35:13 2006 @@ -432,10 +432,11 @@ else: raise CannotSimplify - def simplify(self, block_subset=None): + def simplify(self, block_subset=None, extra_passes=None): # Generic simplifications from pypy.translator import transform - transform.transform_graph(self, block_subset=block_subset) + transform.transform_graph(self, block_subset=block_subset, + extra_passes=extra_passes) from pypy.translator import simplify if block_subset is None: graphs = self.translator.graphs From pedronis at codespeak.net Tue Sep 5 18:42:39 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Sep 2006 18:42:39 +0200 (CEST) Subject: [pypy-svn] r32019 - pypy/dist/pypy/translator Message-ID: <20060905164239.644B51007A@code0.codespeak.net> Author: pedronis Date: Tue Sep 5 18:42:38 2006 New Revision: 32019 Modified: pypy/dist/pypy/translator/transform.py Log: (arre, pedronis) oops, should have gone with the previous checking about adding a extra_passes arg to annotator.simplify. Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Tue Sep 5 18:42:38 2006 @@ -218,10 +218,12 @@ transform_allocate, ] -def transform_graph(ann, extra_passes=default_extra_passes, block_subset=None): +def transform_graph(ann, extra_passes=None, block_subset=None): """Apply set of transformations available.""" # WARNING: this produces incorrect results if the graph has been # modified by t.simplify() after it had been annotated. + if extra_passes is None: + extra_passes = default_extra_passes if block_subset is None: block_subset = fully_annotated_blocks(ann) if not isinstance(block_subset, dict): From pedronis at codespeak.net Tue Sep 5 18:46:06 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Sep 2006 18:46:06 +0200 (CEST) Subject: [pypy-svn] r32020 - in pypy/dist/pypy/translator/c: . test Message-ID: <20060905164606.C6E9B1007A@code0.codespeak.net> Author: pedronis Date: Tue Sep 5 18:46:05 2006 New Revision: 32020 Modified: pypy/dist/pypy/translator/c/exceptiontransform.py pypy/dist/pypy/translator/c/test/test_boehm.py Log: (arre, pedronis) at least for the cases of "allocation" operations where a null pointer return can only mean failure and that an exception is being raised, just check for the result of the operation instead of in the global exception values. This allows in the hint-annotator more control over avoding virtual container construction (which is compile-time) to be surrounded by confusing runtime malloc exception checking. Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Tue Sep 5 18:46:05 2006 @@ -299,9 +299,28 @@ #block.operations.append(SpaceOperation("safe_call", [self.rpyexc_occured_ptr], var_exc_occured)) llops = rtyper.LowLevelOpList(None) - v_exc_type = self.ExcData_repr.getfield(self.cexcdata, 'exc_type', llops) - llops.genop('debug_log_exc', [v_exc_type], lltype.Void) - var_exc_occured = llops.genop('ptr_ne', [v_exc_type, self.cnulltype], lltype.Bool) + alloc_shortcut = False + + spaceop = block.operations[-1] + if spaceop.opname in ('malloc', 'malloc_varsize'): + alloc_shortcut = True + elif spaceop.opname == 'direct_call': + fnobj = spaceop.args[0].value._obj + if hasattr(fnobj, '_callable'): + oopspec = getattr(fnobj._callable, 'oopspec', None) + if oopspec and oopspec == 'newlist(length)': + alloc_shortcut = True + + if alloc_shortcut: + T = spaceop.result.concretetype + var_exc_occured = llops.genop('ptr_eq', [spaceop.result, + Constant(lltype.nullptr(T.TO), T)], + lltype.Bool) + else: + v_exc_type = self.ExcData_repr.getfield(self.cexcdata, 'exc_type', llops) + llops.genop('debug_log_exc', [v_exc_type], lltype.Void) + var_exc_occured = llops.genop('ptr_ne', [v_exc_type, self.cnulltype], lltype.Bool) + block.operations.extend(llops) block.exitswitch = var_exc_occured Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Tue Sep 5 18:46:05 2006 @@ -111,6 +111,7 @@ a = A() # this should not keep a alive s.a = cast_object_to_weakgcaddress(a) + a = None llop.gc__collect(lltype.Void) llop.gc__collect(lltype.Void) llop.gc__collect(lltype.Void) From pedronis at codespeak.net Tue Sep 5 18:52:08 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Sep 2006 18:52:08 +0200 (CEST) Subject: [pypy-svn] r32021 - in pypy/dist/pypy/jit: hintannotator hintannotator/test timeshifter timeshifter/test Message-ID: <20060905165208.815011007C@code0.codespeak.net> Author: pedronis Date: Tue Sep 5 18:52:06 2006 New Revision: 32021 Modified: pypy/dist/pypy/jit/hintannotator/annotator.py pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/test/test_vlist.py Log: (arre, pedronis) start of having the hint-annotator exception transform the copied graphs it annotates. with this in place we need to be careful about what pointer comparisons mean for virtual or red virtual containers. Not all tests work with exceptiontransform on, to have them pass we need to avoid pointer equality comparisions to force things to eagerly: next thing to do. (For completely blue container this is controlled at annotation time, see code added to annotate ptr_eq/ptr_ne for constant/virtual container pairs). Modified: pypy/dist/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/annotator.py Tue Sep 5 18:52:06 2006 @@ -3,14 +3,20 @@ from pypy.jit.hintannotator.bookkeeper import HintBookkeeper from pypy.rpython.lltypesystem import lltype +from pypy.translator.c.exceptiontransform import ExceptionTransformer + class HintAnnotator(RPythonAnnotator): - def __init__(self, translator=None, policy=None): - bookkeeper = HintBookkeeper(self) + def __init__(self, translator=None, base_translator=None, policy=None): + bookkeeper = HintBookkeeper(self) RPythonAnnotator.__init__(self, translator, policy=policy, bookkeeper=bookkeeper) + self.base_translator = base_translator + if getattr(policy, 'exceptiontransform', True) and base_translator is not None: + self.exceptiontransformer = ExceptionTransformer(base_translator) + def build_types(self, origgraph, input_args_hs): desc = self.bookkeeper.getdesc(origgraph) flowgraph = desc.specialize(input_args_hs) @@ -38,5 +44,10 @@ def consider_op_keepalive(self, hs_v): pass + def consider_op_debug_log_exc(self, hs_v): + pass + + def simplify(self): + RPythonAnnotator.simplify(self, extra_passes=[]) HintAnnotator._registeroperations(hintmodel) Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Tue Sep 5 18:52:06 2006 @@ -1,6 +1,7 @@ from pypy.tool.tls import tlsobject from pypy.objspace.flow.model import copygraph from pypy.annotation import model as annmodel +from pypy.rpython.lltypesystem import lltype TLS = tlsobject() @@ -31,7 +32,15 @@ try: return self._cache[key] except KeyError: + bk = self.bookkeeper graph = copygraph(self.origgraph) + try: + exceptiontransformer = bk.annotator.exceptiontransformer + except AttributeError: + pass + else: + # except transform the copied graph before its hint-annotation + exceptiontransformer.create_exception_handling(graph) if alt_name is not None: graph.name = alt_name self._cache[key] = graph @@ -89,6 +98,12 @@ res.const = const.value return res + def immutablevalue(self, value): + from pypy.jit.hintannotator import model as hintmodel + res = hintmodel.SomeLLAbstractConstant(lltype.typeOf(value), {}) + res.const = value + return res + def current_op_concretetype(self): _, block, i = self.position_key op = block.operations[i] Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Tue Sep 5 18:52:06 2006 @@ -19,7 +19,8 @@ char_gt char_lt char_le char_ge char_eq char_ne int_gt int_lt int_le int_ge int_eq int_ne uint_gt uint_lt uint_le uint_ge uint_eq uint_ne - getarrayitem""".split() + getarrayitem + ptr_eq ptr_ne""".split() class HintError(Exception): pass @@ -360,12 +361,27 @@ return pair(hs_cont2, hs_val1).union() + + class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractConstant)): def getarrayitem((hs_a1, hs_index)): hs_res = hs_a1.contentdef.read_item() return reorigin(hs_res, hs_res, hs_index) + def ptr_eq((hs_cont1, hs_ptr2)): + return getbookkeeper().immutablevalue(False) + + def ptr_ne((hs_cont1, hs_ptr2)): + return getbookkeeper().immutablevalue(True) + +class __extend__(pairtype(SomeLLAbstractConstant, SomeLLAbstractContainer)): + + def ptr_eq((hs_ptr1, hs_cont2)): + return getbookkeeper().immutablevalue(False) + + def ptr_ne((hs_ptr1, hs_cont2)): + return getbookkeeper().immutablevalue(True) # ____________________________________________________________ Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Tue Sep 5 18:52:06 2006 @@ -28,11 +28,11 @@ auto_inlining(t, inline) graph1 = graphof(t, func) # build hint annotator types - hannotator = HintAnnotator(policy=policy) - hannotator.base_translator = t + hannotator = HintAnnotator(base_translator=t, policy=policy) hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype, {OriginFlags(): True}) for v in graph1.getargs()]) + hannotator.simplify() t = hannotator.translator if conftest.option.view: t.view() @@ -258,6 +258,12 @@ assert hs.concretetype == lltype.Signed assert len(hs.origins) == 4 +def test_make_a_list(): + def ll_function(x, y): + return [x, y] + hs = hannotate(ll_function, [int, int], policy=P_OOPSPEC) + assert isinstance(hs, SomeLLAbstractContainer) + def test_simple_cast_pointer(): GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed)) GCS2 = lltype.GcStruct('s2', ('sub', GCS1), ('y', lltype.Signed)) @@ -473,7 +479,6 @@ def test_raise_exc(): - py.test.skip("work in-progress") class E(Exception): pass def f1(): @@ -488,7 +493,6 @@ def test_raise_and_catch_exc(): - py.test.skip("work in-progress") class E(Exception): pass def f(flag): @@ -502,7 +506,11 @@ return -1 return 0 - hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) + hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) + # xxx this has a green return but the function has side effects + # we need to proper notice that for correct timeshifting + assert isinstance(hs, SomeLLAbstractConstant) + assert hs.concretetype == lltype.Signed def f(flag): if flag: @@ -510,5 +518,8 @@ e.a = 3 raise e - hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) - + hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) + # xxx this has a green return but the function has side effects + # we need to proper notice that for correct timeshifting + assert isinstance(hs, SomeLLAbstractConstant) + assert hs.concretetype == lltype.Signed Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Tue Sep 5 18:52:06 2006 @@ -3,7 +3,16 @@ from pypy.jit.timeshifter import rvalue class AbstractContainer(object): - pass + + def op_getfield(self, jitstate, fielddesc): + raise NotImplementedError + + def op_setfield(self, jitstate, fielddesc, valuebox): + raise NotImplementedError + + def op_getsubstruct(self, jitstate, fielddesc): + raise NotImplementedError + # ____________________________________________________________ Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Tue Sep 5 18:52:06 2006 @@ -107,6 +107,9 @@ # don't try to generate hint operations, just discard them return hop.inputarg(hop.r_result, arg=0) + def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc + pass + def translate_op_keepalive(self,hop): pass Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Tue Sep 5 18:52:06 2006 @@ -21,6 +21,8 @@ P_NOVIRTUAL = AnnotatorPolicy() P_NOVIRTUAL.novirtualcontainer = True +P_NOVIRTUAL.exceptiontransform = False # XXX for now, needs to make ptr_ne/eq + # not force things def getargtypes(annotator, values): return [annotation(annotator, x) for x in values] @@ -45,11 +47,11 @@ auto_inlining(t, inline) graph1 = graphof(t, func) # build hint annotator types - hannotator = HintAnnotator(policy=policy) - hannotator.base_translator = t + hannotator = HintAnnotator(base_translator=t, policy=policy) hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype, {OriginFlags(): True}) for v in graph1.getargs()]) + hannotator.simplify() if conftest.option.view: hannotator.translator.view() return hs, hannotator, rtyper Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py Tue Sep 5 18:52:06 2006 @@ -4,6 +4,8 @@ P_OOPSPEC = AnnotatorPolicy() P_OOPSPEC.novirtualcontainer = True P_OOPSPEC.oopspec = True +P_OOPSPEC.exceptiontransform = False # XXX for now, needs to make ptr_ne/eq + # not force things class TestVList(TimeshiftingTests): From fijal at codespeak.net Wed Sep 6 11:12:38 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 6 Sep 2006 11:12:38 +0200 (CEST) Subject: [pypy-svn] r32024 - in pypy/dist/pypy/translator/js: . modules test Message-ID: <20060906091238.5922D1007A@code0.codespeak.net> Author: fijal Date: Wed Sep 6 11:12:11 2006 New Revision: 32024 Added: pypy/dist/pypy/translator/js/helper.py (contents, props changed) Modified: pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/js/modules/_dom.py pypy/dist/pypy/translator/js/test/test_transformer.py Log: Added basic transformation which allows you to display traceback. Added: pypy/dist/pypy/translator/js/helper.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js/helper.py Wed Sep 6 11:12:11 2006 @@ -0,0 +1,34 @@ + +""" Some helpers +""" + +from pypy.translator.js.modules._dom import get_document + +def escape(s): + #return s.replace("&", "&").replace("<", "<").replace(">", ">"). \ + # replace("'", "\\'").replace(" ", " ").replace("\n", "
") + return s + +def create_debug_div(): + debug_div = get_document().createElement("div") + # XXX attach it somewhere... + #body = get_document().getElementsByTagName('body')[0] + get_document().childNodes[0].childNodes[1].appendChild(debug_div) + return debug_div + +def show_traceback(tb): + debug_div = get_document().getElementById("debug_div") + if not debug_div: + # create div here + debug_div = create_debug_div() + + pre_div = get_document().createElement("pre") + pre_div.style.color = "#FF0000" + debug_div.appendChild(pre_div) + for tb_entry in tb: + # list of tuples... + fun_name, args, filename, lineno = tb_entry + # some source maybe? or so? + line1 = escape("%s %s" % (fun_name, args)) + line2 = escape(" %s: %s\n" % (filename, lineno)) + pre_div.innerHTML += line1 + '\n' + line2 Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Wed Sep 6 11:12:11 2006 @@ -11,6 +11,7 @@ from pypy.rpython.nonconst import NonConstant from pypy.annotation.policy import AnnotatorPolicy import optparse +import py class FunctionNotFound(Exception): pass @@ -25,7 +26,11 @@ l = [] for i in xrange(func_data.func_code.co_argcount): l.append("NonConstant(%s)" % repr(func_data.func_defaults[i])) - return "(%s)" % ",".join(l) + return ",".join(l) + +def get_arg_names(func_data): + return ",".join(func_data.func_code.co_varnames\ + [:func_data.func_code.co_argcount]) def rpython2javascript_main(argv): if len(argv) < 1: @@ -39,6 +44,56 @@ mod = __import__(module_name, None, None, ["Module"]) return rpython2javascript(mod, function_names) +# some strange function source +source_ssf_base = """ + +import %(module_name)s +from pypy.translator.js.helper import show_traceback +from pypy.translator.transformer.debug import traceback_handler +from pypy.rpython.nonconst import NonConstant as NonConst + +%(function_defs)s + +def some_strange_function_which_will_never_be_called(): + +%(functions)s +""" + +wrapped_function_def_base = """ +def %(fun_name)s(%(arg_names)s): + try: + traceback_handler.enter(NonConst("entrypoint"), NonConst("()"), NonConst(""), NonConst(0)) + %(module_name)s.%(fun_name)s(%(arg_names)s) + traceback_handler.leave(NonConst("entrypoint")) + except: + new_tb = traceback_handler.tb[:] + show_traceback(new_tb) +""" + +function_base = "%(module)s.%(fun_name)s(%(args)s)" +wrapped_function_base = "%(fun_name)s(%(args)s)" + +def get_source_ssf(mod, module_name, function_names, use_debug=True): + #source_ssf = "\n".join(["import %s" % module_name, "def some_strange_function_which_will_never_be_called():"] + [" "+\ + # module_name+"."+fun_name+get_args(mod.__dict__[fun_name]) for fun_name in function_names]) + function_list = [] + function_def_list = [] + for fun_name in function_names: + args = get_args(mod.__dict__[fun_name]) + arg_names = get_arg_names(mod.__dict__[fun_name]) + if not use_debug: + base = function_base + else: + base = wrapped_function_base + function_def_list.append(py.code.Source(wrapped_function_def_base % + locals())) + function_list.append(py.code.Source(base % locals())) + function_defs = "\n\n".join([str(i) for i in function_def_list]) + functions = "\n".join([str(i.indent()) for i in function_list]) + retval = source_ssf_base % locals() + print retval + return retval + def rpython2javascript(mod, function_names, use_debug=True): module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: @@ -47,13 +102,13 @@ if func_name not in mod.__dict__: raise FunctionNotFound("function %r was not found in module %r" % (func_name, module_name)) func_code = mod.__dict__[func_name] - if func_code.func_code.co_argcount > 0 and func_code.func_code.co_argcount != len(func_code.func_defaults): + if func_code.func_code.co_argcount > 0 and func_code.func_code. \ + co_argcount != len(func_code.func_defaults): raise BadSignature("Function %s does not have default arguments" % func_name) - source_ssf = "\n".join(["import %s" % module_name, "def some_strange_function_which_will_never_be_called():"] + [" "+\ - module_name+"."+fun_name+get_args(mod.__dict__[fun_name]) for fun_name in function_names]) + source_ssf = get_source_ssf(mod, module_name, function_names, use_debug) exec(source_ssf) in globals() - #fn = compile_function([mod.__dict__[f_name] for f_name in function_names], [[] for i in function_names]) # now we gonna just cut off not needed function + # XXX: Really do that options = optparse.Values(defaults=DEFAULT_OPTIONS) options.debug_transform = use_debug driver = TranslationDriver(options=options) @@ -61,6 +116,7 @@ driver.setup(some_strange_function_which_will_never_be_called, [], policy = JsPolicy()) driver.proceed(["compile_js"]) return driver.gen.tmpfile.open().read() + # XXX: Add some possibility to write down selected file except Exception, e: # do something nice with it debug(driver) Modified: pypy/dist/pypy/translator/js/modules/_dom.py ============================================================================== --- pypy/dist/pypy/translator/js/modules/_dom.py (original) +++ pypy/dist/pypy/translator/js/modules/_dom.py Wed Sep 6 11:12:11 2006 @@ -237,7 +237,7 @@ 'getAttributeNS' : MethodDesc(["aa", "aa"], "aa"), 'getAttributeNode' : MethodDesc(["aa"], Element()), 'getAttributeNodeNS' : MethodDesc(["aa", "aa"], Element()), - 'getElementsByTagName' : MethodDesc(["aa"], [Element()]), + 'getElementsByTagName' : MethodDesc(["aa"], [Element(), Element()]), 'hasAttribute' : MethodDesc(["aa"], True), 'hasAttributeNS' : MethodDesc(["aa", "aa"], True), 'hasAttributes' : MethodDesc([], True), Modified: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_transformer.py (original) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Wed Sep 6 11:12:11 2006 @@ -86,3 +86,5 @@ lst = retval.split("|") check_tb(lst[1], "g", "()", wrapper, 3) check_tb(lst[2], "f", "(3, 'dupa'", g, 1) + +# XXX: indirect call test as well From xoraxax at codespeak.net Wed Sep 6 16:47:43 2006 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 6 Sep 2006 16:47:43 +0200 (CEST) Subject: [pypy-svn] r32030 - in pypy/dist/pypy/module/_codecs: . test Message-ID: <20060906144743.08BA210079@code0.codespeak.net> Author: xoraxax Date: Wed Sep 6 16:47:40 2006 New Revision: 32030 Modified: pypy/dist/pypy/module/_codecs/app_codecs.py pypy/dist/pypy/module/_codecs/test/test_codecs.py Log: Fixed _codecs module: it did not normalise codec names before looking them up. Thanks to Victor Stinner for the patch. Interestingly, the added patch did not fail with py.test because py.py got it right, pypy-c did not. Modified: pypy/dist/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/dist/pypy/module/_codecs/app_codecs.py (original) +++ pypy/dist/pypy/module/_codecs/app_codecs.py Wed Sep 6 16:47:40 2006 @@ -65,26 +65,26 @@ Looks up a codec tuple in the Python codec registry and returns a tuple of functions. """ - - result = codec_search_cache.get(encoding, None) + if not isinstance(encoding, str): + raise TypeError("Encoding must be a string") + normalized_encoding = encoding.replace(" ", "-").lower() + result = codec_search_cache.get(normalized_encoding, None) if not result: if codec_need_encodings: import encodings if len(codec_search_path) == 0: raise LookupError("no codec search functions registered: can't find encoding") del codec_need_encodings[:] - if not isinstance(encoding, str): - raise TypeError("Encoding must be a string") for search in codec_search_path: - result = search(encoding) - if result : - if not( type(result) == tuple and len(result) == 4): + result = search(normalized_encoding) + if result: + if not (type(result) == tuple and len(result) == 4): raise TypeError("codec search functions must return 4-tuples") else: - codec_search_cache[encoding] = result + codec_search_cache[normalized_encoding] = result return result if not result: - raise LookupError( "unknown encoding: %s" % encoding) + raise LookupError("unknown encoding: %s" % encoding) return result Modified: pypy/dist/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/dist/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/dist/pypy/module/_codecs/test/test_codecs.py Wed Sep 6 16:47:40 2006 @@ -254,3 +254,7 @@ assert '\\100'.decode('string_escape') == '@' assert '\\253'.decode('string_escape') == chr(0253) assert '\\312'.decode('string_escape') == chr(0312) + + def test_decode_utf8_different_case(self): + constant = u"a" + assert constant.encode("utf-8") == constant.encode("UTF-8") From arigo at codespeak.net Wed Sep 6 19:24:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Sep 2006 19:24:21 +0200 (CEST) Subject: [pypy-svn] r32031 - pypy/dist/pypy/translator/c Message-ID: <20060906172421.6790810079@code0.codespeak.net> Author: arigo Date: Wed Sep 6 19:24:19 2006 New Revision: 32031 Modified: pypy/dist/pypy/translator/c/exceptiontransform.py Log: (pedronis, arigo) There is ptr_nonzero and ptr_iszero, that's more convenient. Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Wed Sep 6 19:24:19 2006 @@ -139,7 +139,6 @@ self.ExcData_repr = rclass.getinstancerepr(translator.rtyper, ExcDataDef) exc_data_ptr = self.ExcData_repr.convert_const(exc_data) self.cexcdata = Constant(exc_data_ptr, self.ExcData_repr.lowleveltype) - self.cnulltype = Constant(null_type, self.lltype_of_exception_type) self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping() @@ -313,13 +312,13 @@ if alloc_shortcut: T = spaceop.result.concretetype - var_exc_occured = llops.genop('ptr_eq', [spaceop.result, - Constant(lltype.nullptr(T.TO), T)], + var_exc_occured = llops.genop('ptr_iszero', [spaceop.result], lltype.Bool) else: v_exc_type = self.ExcData_repr.getfield(self.cexcdata, 'exc_type', llops) llops.genop('debug_log_exc', [v_exc_type], lltype.Void) - var_exc_occured = llops.genop('ptr_ne', [v_exc_type, self.cnulltype], lltype.Bool) + var_exc_occured = llops.genop('ptr_nonzero', [v_exc_type], + lltype.Bool) block.operations.extend(llops) From arigo at codespeak.net Wed Sep 6 19:31:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Sep 2006 19:31:35 +0200 (CEST) Subject: [pypy-svn] r32032 - in pypy/dist/pypy/jit: codegen/i386 hintannotator hintannotator/test timeshifter timeshifter/test Message-ID: <20060906173135.D29EA1007B@code0.codespeak.net> Author: arigo Date: Wed Sep 6 19:31:32 2006 New Revision: 32032 Added: pypy/dist/pypy/jit/timeshifter/test/test_exception.py (contents, props changed) Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/test/test_vlist.py pypy/dist/pypy/jit/timeshifter/timeshift.py Log: (pedronis, arigo) Timeshift functions with exceptions. In more details: - split JITState / VirtualFrame classes - exc_value_box and exc_type_box on the jitstate - more support for functions returning Void - ptr_iszero/ptr_nonzero operation support (in the hintannotator, in the timeshifter, in the i386 backend) Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Wed Sep 6 19:31:32 2006 @@ -363,7 +363,7 @@ self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_setarrayitem(self, (gv_ptr, gv_index, gv_value), gv_RESTYPE): + def op_setarrayitem(self, hello_world): # XXX! only works for GcArray(Signed) for now!! XXX-fixme A = DUMMY_A @@ -381,6 +381,9 @@ op = memSIB(edx, ecx, 0, startoffset) self.mc.MOV(op, eax) + op_ptr_nonzero = op_int_is_true + op_ptr_iszero = op_bool_not # for now + DUMMY_A = lltype.GcArray(lltype.Signed) SIZE2SHIFT = {1: 0, Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Wed Sep 6 19:31:32 2006 @@ -12,7 +12,9 @@ cast_int_to_uint cast_uint_to_int cast_char_to_int - cast_bool_to_int""".split() + cast_bool_to_int + ptr_nonzero + ptr_iszero""".split() BINARY_OPERATIONS = """int_add int_sub int_mul int_mod int_and int_rshift int_floordiv uint_add uint_sub uint_mul uint_mod uint_and uint_rshift uint_floordiv @@ -302,6 +304,13 @@ res_vstruct =hs_s1.contentdef.cast(TO) return SomeLLAbstractContainer(res_vstruct) + def ptr_nonzero(hs_s1): + return getbookkeeper().immutablevalue(True) + + def ptr_iszero(hs_s1): + return getbookkeeper().immutablevalue(False) + + # ____________________________________________________________ # binary @@ -348,6 +357,12 @@ contentdef = hs_cont1.contentdef.union(hs_cont2.contentdef) return SomeLLAbstractContainer(contentdef) + def ptr_eq((hs_cont1, hs_cont2)): + return SomeLLAbstractConstant(lltype.Bool, {}) + + def ptr_ne((hs_cont1, hs_cont2)): + return SomeLLAbstractConstant(lltype.Bool, {}) + class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue)): def union((hs_cont1, hs_val2)): @@ -361,6 +376,14 @@ return pair(hs_cont2, hs_val1).union() +class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue), + pairtype(SomeLLAbstractValue, SomeLLAbstractContainer)): + + def ptr_eq(_): + return getbookkeeper().immutablevalue(False) + + def ptr_ne(_): + return getbookkeeper().immutablevalue(True) class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractConstant)): @@ -369,20 +392,6 @@ hs_res = hs_a1.contentdef.read_item() return reorigin(hs_res, hs_res, hs_index) - def ptr_eq((hs_cont1, hs_ptr2)): - return getbookkeeper().immutablevalue(False) - - def ptr_ne((hs_cont1, hs_ptr2)): - return getbookkeeper().immutablevalue(True) - -class __extend__(pairtype(SomeLLAbstractConstant, SomeLLAbstractContainer)): - - def ptr_eq((hs_ptr1, hs_cont2)): - return getbookkeeper().immutablevalue(False) - - def ptr_ne((hs_ptr1, hs_cont2)): - return getbookkeeper().immutablevalue(True) - # ____________________________________________________________ def handle_highlevel_operation(bookkeeper, ll_func, *args_hs): Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Wed Sep 6 19:31:32 2006 @@ -507,8 +507,6 @@ return 0 hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) - # xxx this has a green return but the function has side effects - # we need to proper notice that for correct timeshifting assert isinstance(hs, SomeLLAbstractConstant) assert hs.concretetype == lltype.Signed @@ -519,7 +517,5 @@ raise e hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) - # xxx this has a green return but the function has side effects - # we need to proper notice that for correct timeshifting assert isinstance(hs, SomeLLAbstractConstant) assert hs.concretetype == lltype.Signed Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Wed Sep 6 19:31:32 2006 @@ -126,6 +126,7 @@ NamedFieldDesc.__init__(self, RGenOp, PTRTYPE, name) self.fieldindex = index self.gv_default = RGenOp.constPrebuiltGlobal(self.RESTYPE._defl()) + self.defaultbox = self.redboxcls(self.kind, self.gv_default) class ArrayFieldDesc(FieldDesc): def __init__(self, RGenOp, PTRTYPE): Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Wed Sep 6 19:31:32 2006 @@ -136,6 +136,22 @@ argbox.getgenvar(jitstate.curbuilder)) return rvalue.IntRedBox(fielddesc.indexkind, genvar) +def ll_genptrnonzero(jitstate, argbox, reverse): + if argbox.is_constant(): + addr = rvalue.ll_getvalue(argbox, llmemory.Address) + return rvalue.ll_fromvalue(jitstate, bool(addr) ^ reverse) + assert isinstance(argbox, rvalue.PtrRedBox) + builder = jitstate.curbuilder + if argbox.content is None: + gv_addr = argbox.getgenvar(builder) + if reverse: + gv_res = builder.genop1("ptr_iszero", gv_addr) + else: + gv_res = builder.genop1("ptr_nonzero", gv_addr) + else: + gv_res = builder.rgenop.genconst(True ^ reverse) + return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res) + # ____________________________________________________________ # other jitstate/graph level operations @@ -162,7 +178,7 @@ start_new_block._annspecialcase_ = "specialize:arglltype(2)" def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes): - jitstate.local_boxes = redboxes + save_locals(jitstate, redboxes) if key not in states_dic: start_new_block(states_dic, jitstate, key) return False # continue @@ -203,47 +219,47 @@ else: exitgvar = switchredbox.getgenvar(jitstate.curbuilder) later_builder = jitstate.curbuilder.jump_if_false(exitgvar) - memo = rvalue.copy_memo() - jitstate.local_boxes = redboxes_false - later_jitstate = jitstate.copy(memo) - later_jitstate.curbuilder = later_builder - later_jitstate.exitindex = exitindex - jitstate.split_queue.append(later_jitstate) - jitstate.local_boxes = redboxes_true + save_locals(jitstate, redboxes_false) + jitstate.split(later_builder, exitindex) + save_locals(jitstate, redboxes_true) enter_block(jitstate) return True def dispatch_next(oldjitstate, return_cache): - split_queue = oldjitstate.split_queue + split_queue = oldjitstate.frame.split_queue if split_queue: jitstate = split_queue.pop() enter_block(jitstate) return jitstate else: - return_queue = oldjitstate.return_queue - for jitstate in return_queue[:-1]: - res = retrieve_jitstate_for_merge(return_cache, jitstate, (), - jitstate.local_boxes) - assert res is True # finished - frozen, block = return_cache[()] - jitstate = return_queue[-1] - retbox = jitstate.local_boxes[0] - backstate = jitstate.backstate - backstate.curbuilder = jitstate.curbuilder - backstate.local_boxes.append(retbox) - backstate.exitindex = -1 - # XXX for now the return value box is put in the parent's local_boxes, - # where a 'restore_local' operation will fetch it - return backstate + return leave_graph(oldjitstate.frame.return_queue, return_cache) def getexitindex(jitstate): return jitstate.exitindex +def save_locals(jitstate, redboxes): + jitstate.frame.local_boxes = redboxes + def getlocalbox(jitstate, i): - return jitstate.local_boxes[i] + return jitstate.frame.local_boxes[i] + +def getreturnbox(jitstate): + return jitstate.returnbox + +def getexctypebox(jitstate): + return jitstate.exc_type_box + +def getexcvaluebox(jitstate): + return jitstate.exc_value_box + +def setexctypebox(jitstate, box): + jitstate.exc_type_box = box + +def setexcvaluebox(jitstate, box): + jitstate.exc_value_box = box def save_return(jitstate): - jitstate.return_queue.append(jitstate) + jitstate.frame.return_queue.append(jitstate) def ll_gvar_from_redbox(jitstate, redbox): return redbox.getgenvar(jitstate.curbuilder) @@ -251,69 +267,85 @@ def ll_gvar_from_constant(jitstate, ll_value): return jitstate.curbuilder.rgenop.genconst(ll_value) -def save_locals(jitstate, redboxes): - jitstate.local_boxes = redboxes - # ____________________________________________________________ -class FrozenJITState(object): - fz_backstate = None +class FrozenVirtualFrame(object): + fz_backframe = None #fz_local_boxes = ... set by freeze() - def exactmatch(self, jitstate, outgoingvarboxes, memo): + def exactmatch(self, vframe, outgoingvarboxes, memo): self_boxes = self.fz_local_boxes - live_boxes = jitstate.local_boxes + live_boxes = vframe.local_boxes fullmatch = True for i in range(len(self_boxes)): if not self_boxes[i].exactmatch(live_boxes[i], outgoingvarboxes, memo): fullmatch = False - if self.fz_backstate is not None: - assert jitstate.backstate is not None - if not self.fz_backstate.exactmatch(jitstate.backstate, + if self.fz_backframe is not None: + assert vframe.backframe is not None + if not self.fz_backframe.exactmatch(vframe.backframe, outgoingvarboxes, memo): fullmatch = False else: - assert jitstate.backstate is None + assert vframe.backframe is None return fullmatch -class JITState(object): - exitindex = -1 +class FrozenJITState(object): + #fz_frame = ... set by freeze() + #fz_exc_type_box = ... set by freeze() + #fz_exc_value_box = ... set by freeze() - def __init__(self, split_queue, return_queue, builder, backstate): + def exactmatch(self, jitstate, outgoingvarboxes, memo): + fullmatch = True + if not self.fz_frame.exactmatch(jitstate.frame, + outgoingvarboxes, + memo): + fullmatch = False + if not self.fz_exc_type_box.exactmatch(jitstate.exc_type_box, + outgoingvarboxes, + memo): + fullmatch = False + if not self.fz_exc_value_box.exactmatch(jitstate.exc_value_box, + outgoingvarboxes, + memo): + fullmatch = False + return fullmatch + + +class VirtualFrame(object): + + def __init__(self, backframe, split_queue, return_queue): + self.backframe = backframe self.split_queue = split_queue self.return_queue = return_queue - self.curbuilder = builder - self.backstate = backstate #self.local_boxes = ... set by callers def enter_block(self, incoming, memo): for box in self.local_boxes: box.enter_block(incoming, memo) - if self.backstate is not None: - self.backstate.enter_block(incoming, memo) + if self.backframe is not None: + self.backframe.enter_block(incoming, memo) def freeze(self, memo): - result = FrozenJITState() + result = FrozenVirtualFrame() frozens = [box.freeze(memo) for box in self.local_boxes] result.fz_local_boxes = frozens - if self.backstate is not None: - result.fz_backstate = self.backstate.freeze(memo) + if self.backframe is not None: + result.fz_backframe = self.backframe.freeze(memo) return result def copy(self, memo): - if self.backstate is None: - newbackstate = None + if self.backframe is None: + newbackframe = None else: - newbackstate = self.backstate.copy(memo) - result = JITState(self.split_queue, - self.return_queue, - None, - newbackstate) + newbackframe = self.backframe.copy(memo) + result = VirtualFrame(newbackframe, + self.split_queue, + self.return_queue) result.local_boxes = [box.copy(memo) for box in self.local_boxes] return result @@ -321,14 +353,63 @@ local_boxes = self.local_boxes for i in range(len(local_boxes)): local_boxes[i] = local_boxes[i].replace(memo) - if self.backstate is not None: - self.backstate.replace(memo) + if self.backframe is not None: + self.backframe.replace(memo) -def enter_graph(backstate): - return JITState([], [], backstate.curbuilder, backstate) +class JITState(object): + returnbox = None + + def __init__(self, builder, frame, exc_type_box, exc_value_box, + exitindex=-1): + self.curbuilder = builder + self.frame = frame + self.exc_type_box = exc_type_box + self.exc_value_box = exc_value_box + self.exitindex = exitindex -def fresh_jitstate(builder): - jitstate = JITState([], [], builder, None) - jitstate.local_boxes = [] + def split(self, newbuilder, newexitindex): + memo = rvalue.copy_memo() + later_jitstate = JITState(newbuilder, + self.frame.copy(memo), + self.exc_type_box .copy(memo), + self.exc_value_box.copy(memo), + newexitindex) + self.frame.split_queue.append(later_jitstate) + + def enter_block(self, incoming, memo): + self.frame.enter_block(incoming, memo) + self.exc_type_box .enter_block(incoming, memo) + self.exc_value_box.enter_block(incoming, memo) + + def freeze(self, memo): + result = FrozenJITState() + result.fz_frame = self.frame.freeze(memo) + result.fz_exc_type_box = self.exc_type_box .freeze(memo) + result.fz_exc_value_box = self.exc_value_box.freeze(memo) + return result + + def replace(self, memo): + self.frame.replace(memo) + self.exc_type_box = self.exc_type_box .replace(memo) + self.exc_value_box = self.exc_value_box.replace(memo) + + +def enter_graph(jitstate): + jitstate.frame = VirtualFrame(jitstate.frame, [], []) + +def leave_graph(return_queue, return_cache): + for jitstate in return_queue[:-1]: + res = retrieve_jitstate_for_merge(return_cache, jitstate, (), + # XXX strange next argument + jitstate.frame.local_boxes) + assert res is True # finished + frozen, block = return_cache[()] + jitstate = return_queue[-1] + myframe = jitstate.frame + if myframe.local_boxes: # else it's a green Void return + jitstate.returnbox = myframe.local_boxes[0] + # ^^^ fetched by an 'fetch_return' operation + jitstate.frame = myframe.backframe + jitstate.exitindex = -1 return jitstate Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Wed Sep 6 19:31:32 2006 @@ -120,6 +120,21 @@ def translate_op_getfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_getfield(hop) + ts = self.timeshifter + if hop.args_v[0] == ts.cexcdata: + # reading one of the exception boxes (exc_type or exc_value) + fieldname = hop.args_v[1].value + if fieldname.endswith('exc_type'): + reader = rtimeshift.getexctypebox + elif fieldname.endswith('exc_value'): + reader = rtimeshift.getexcvaluebox + else: + raise Exception("getfield(exc_data, %r)" % (fieldname,)) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(reader, + [ts.s_JITState], + [v_jitstate ], + ts.s_RedBox) # non virtual case PTRTYPE = originalconcretetype(hop.args_s[0]) if PTRTYPE.TO._hints.get('immutable', False): # foldable if all green @@ -127,7 +142,6 @@ if res is not None: return res - ts = self.timeshifter v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE), green_void_repr) structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO) @@ -183,10 +197,26 @@ def translate_op_setfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_setfield(hop) - # non virtual case ... ts = self.timeshifter PTRTYPE = originalconcretetype(hop.args_s[0]) VALUETYPE = originalconcretetype(hop.args_s[2]) + if hop.args_v[0] == ts.cexcdata: + # reading one of the exception boxes (exc_type or exc_value) + fieldname = hop.args_v[1].value + if fieldname.endswith('exc_type'): + writer = rtimeshift.setexctypebox + elif fieldname.endswith('exc_value'): + writer = rtimeshift.setexcvaluebox + else: + raise Exception("setfield(exc_data, %r)" % (fieldname,)) + v_valuebox = hop.inputarg(self.getredrepr(VALUETYPE), arg=2) + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(writer, + [ts.s_JITState, ts.s_RedBox], + [v_jitstate, v_valuebox ], + annmodel.s_None) + return + # non virtual case ... v_destbox, c_fieldname, v_valuebox = hop.inputargs(self.getredrepr(PTRTYPE), green_void_repr, self.getredrepr(VALUETYPE) @@ -227,6 +257,21 @@ r_result = hop.r_result return r_result.create(hop) + def translate_op_ptr_nonzero(self, hop, reverse=False): + ts = self.timeshifter + PTRTYPE = originalconcretetype(hop.args_s[0]) + v_argbox, = hop.inputargs(self.getredrepr(PTRTYPE)) + v_jitstate = hop.llops.getjitstate() + c_reverse = hop.inputconst(lltype.Bool, reverse) + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genptrnonzero, + [ts.s_JITState, ts.s_RedBox, annmodel.SomeBool()], + [v_jitstate, v_argbox, c_reverse ], + ts.s_RedBox) + + def translate_op_ptr_iszero(self, hop): + return self.translate_op_ptr_nonzero(hop, reverse=True) + + def guess_call_kind(self, spaceop): assert spaceop.opname == 'direct_call' c_func = spaceop.args[0] @@ -262,6 +307,13 @@ v_jitstate = hop.llops.getjitstate() return ts.read_out_box(hop.llops, v_jitstate, index) + def translate_op_fetch_return(self, hop): + ts = self.timeshifter + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.getreturnbox, + [ts.s_JITState], + [v_jitstate ], + ts.s_RedBox) def handle_oopspec_call(self, hop): # special-cased call, for things like list methods Added: pypy/dist/pypy/jit/timeshifter/test/test_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/timeshifter/test/test_exception.py Wed Sep 6 19:31:32 2006 @@ -0,0 +1,69 @@ +import py +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.llinterp import LLException +from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests +from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL + + +class TestException(TimeshiftingTests): + + def test_exception_check_melts_away(self): + def ll_two(x): + if x == 0: + raise ValueError + return x-1 + def ll_function(y): + return ll_two(y) + 40 + + res = self.timeshift(ll_function, [3], [0], policy=P_NOVIRTUAL) + assert res == 42 + self.check_insns({}) + + def test_propagate_exception(self): + S = lltype.Struct('S', ('flag', lltype.Signed)) + s = lltype.malloc(S, immortal=True) + def ll_two(x): + if x == 0: + raise ValueError + return x+7 + def ll_function(y): + res = ll_two(y) + s.flag = 1 + return res + + s.flag = 0 + res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL) + assert res == -1 + assert s.flag == 0 + + s.flag = 0 + res = self.timeshift(ll_function, [0], [0], policy=P_NOVIRTUAL) + assert res == -1 + assert s.flag == 0 + + s.flag = 0 + res = self.timeshift(ll_function, [17], [0], policy=P_NOVIRTUAL) + assert res == 24 + assert s.flag == 1 + self.check_insns({'setfield': 1}) + + def test_catch(self): + def ll_two(x): + if x == 0: + raise ValueError + return x+7 + def ll_function(y): + try: + return ll_two(y) + except ValueError: + return 42 + + res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL) + assert res == 42 + + res = self.timeshift(ll_function, [0], [0], policy=P_NOVIRTUAL) + assert res == 42 + + res = self.timeshift(ll_function, [17], [0], policy=P_NOVIRTUAL) + assert res == 24 + self.check_insns({}) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Wed Sep 6 19:31:32 2006 @@ -21,8 +21,6 @@ P_NOVIRTUAL = AnnotatorPolicy() P_NOVIRTUAL.novirtualcontainer = True -P_NOVIRTUAL.exceptiontransform = False # XXX for now, needs to make ptr_ne/eq - # not force things def getargtypes(annotator, values): return [annotation(annotator, x) for x in values] @@ -91,6 +89,7 @@ # make the timeshifted graphs htshift = HintTimeshift(ha, rtyper, self.RGenOp) + fresh_jitstate = htshift.ll_fresh_jitstate RESTYPE = htshift.originalconcretetype( ha.translator.graphs[0].getreturnvar()) htshift.timeshift() @@ -172,10 +171,10 @@ i += 1 timeshifted_entrypoint_args += (box,) - top_jitstate = rtimeshift.fresh_jitstate(builder) + top_jitstate = fresh_jitstate(builder) top_jitstate = timeshifted_entrypoint(top_jitstate, *timeshifted_entrypoint_args) - returnbox = top_jitstate.local_boxes[0] + returnbox = rtimeshift.getreturnbox(top_jitstate) gv_ret = returnbox.getgenvar(top_jitstate.curbuilder) top_jitstate.curbuilder.finish_and_return(sigtoken, gv_ret) @@ -796,3 +795,13 @@ assert res == 21 self.check_insns({'int_gt': 1, 'int_add': 1, 'int_sub': 1, 'int_mul': 1}) + + def test_void_call(self): + def ll_do_nothing(x): + pass + def ll_function(y): + ll_do_nothing(y) + return y + + res = self.timeshift(ll_function, [3], [], policy=P_NOVIRTUAL) + assert res == 3 Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py Wed Sep 6 19:31:32 2006 @@ -4,8 +4,6 @@ P_OOPSPEC = AnnotatorPolicy() P_OOPSPEC.novirtualcontainer = True P_OOPSPEC.oopspec = True -P_OOPSPEC.exceptiontransform = False # XXX for now, needs to make ptr_ne/eq - # not force things class TestVList(TimeshiftingTests): Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Wed Sep 6 19:31:32 2006 @@ -49,6 +49,21 @@ ## self.r_box_accum = getrepr(self.s_box_accum) ## self.r_box_accum.setup() + self.cexcdata = hannotator.exceptiontransformer.cexcdata + gv_excdata = RGenOp.constPrebuiltGlobal(self.cexcdata.value) + LL_EXC_TYPE = rtyper.exceptiondata.lltype_of_exception_type + LL_EXC_VALUE = rtyper.exceptiondata.lltype_of_exception_value + null_exc_type_box = rvalue.redbox_from_prebuilt_value(RGenOp, + lltype.nullptr(LL_EXC_TYPE.TO)) + null_exc_value_box = rvalue.redbox_from_prebuilt_value(RGenOp, + lltype.nullptr(LL_EXC_VALUE.TO)) + + def ll_fresh_jitstate(builder): + return JITState(builder, None, + null_exc_type_box, + null_exc_value_box) + self.ll_fresh_jitstate = ll_fresh_jitstate + def s_r_instanceof(self, cls, can_be_None=True): # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) @@ -199,14 +214,13 @@ newstartblock = self.insert_before_block(self.graph.startblock, None, closeblock=True) llops = HintLowLevelOpList(self) - v_backstate = llops.getjitstate() + v_jitstate = llops.getjitstate() llops.genop('direct_call', [self.c_ll_clearcaches_ptr]) - v_jitstate1 = llops.genmixlevelhelpercall(rtimeshift.enter_graph, - [self.s_JITState], - [v_backstate], - self.s_JITState) - llops.setjitstate(v_jitstate1) + llops.genmixlevelhelpercall(rtimeshift.enter_graph, + [self.s_JITState], + [v_jitstate ], + annmodel.s_None) newstartblock.operations = list(llops) def insert_before_block(self, block, block_entering_links, @@ -313,7 +327,7 @@ orig_key_v = [] for newvar in newinputargs: r = self.hrtyper.bindingrepr(newvar) - if isinstance(r, GreenRepr): + if isinstance(r, GreenRepr) and r.lowleveltype is not lltype.Void: r_from = getrepr(r.annotation()) s_erased = r.erased_annotation() r_to = getrepr(s_erased) @@ -585,10 +599,7 @@ block.operations.insert(i, extraop) replacement = {} - # XXX for now, the call appends the return value box to - # the local_boxes of our jitstate, from where we can fish - # it using a 'restore_local' ----------vvvvvvvvvvv - for i, var in enumerate(vars_to_save + [op.result]): + for i, var in enumerate(vars_to_save): newvar = copyvar(self.hannotator, var) c_index = flowmodel.Constant(i, concretetype=lltype.Signed) extraop = flowmodel.SpaceOperation('restore_local', @@ -597,6 +608,15 @@ block.operations.append(extraop) replacement[var] = newvar + if isinstance(hrtyper.bindingrepr(op.result), RedRepr): + var = op.result + newvar = copyvar(self.hannotator, var) + extraop = flowmodel.SpaceOperation('fetch_return', + [], + newvar) + block.operations.append(extraop) + replacement[var] = newvar + link.args = [replacement.get(var, var) for var in link.args] block = link.target entering_links[block] = [link] From arigo at codespeak.net Wed Sep 6 21:34:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Sep 2006 21:34:35 +0200 (CEST) Subject: [pypy-svn] r32034 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/test translator/c translator/c/test Message-ID: <20060906193435.ED2C41007D@code0.codespeak.net> Author: arigo Date: Wed Sep 6 21:34:33 2006 New Revision: 32034 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/translator/c/exceptiontransform.py pypy/dist/pypy/translator/c/test/test_exceptiontransform.py Log: (pedronis, arigo) Attach the ExcData produced by the exception transformer to each transformed graph. This allows llinterpretation of a mixture of transformed and non-transformed graphs, with conversion between the stored-in-ExcData and raised-as-LLException styles. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed Sep 6 21:34:33 2006 @@ -1,6 +1,7 @@ from pypy.objspace.flow.model import FunctionGraph, Constant, Variable, c_last_exception from pypy.rpython.rarithmetic import intmask, r_uint, ovfcheck, r_longlong, r_ulonglong from pypy.rpython.lltypesystem import lltype, llmemory, lloperation, llheap +from pypy.rpython.lltypesystem import rclass from pypy.rpython.ootypesystem import ootype from pypy.rpython.objectmodel import ComputedIntSymbolic @@ -14,7 +15,7 @@ class LLException(Exception): def __str__(self): etype = self.args[0] - evalue = self.args[0] + #evalue = self.args[1] if len(self.args) > 2: f = cStringIO.StringIO() original_type, original_value, original_tb = self.args[2] @@ -277,6 +278,15 @@ evalue = self.getval(evaluevar) # watch out, these are _ptr's raise LLException(etype, evalue) + if hasattr(self.graph, 'exceptiontransformed'): + # re-raise the exception set by this graph, if any + exc_data = self.graph.exceptiontransformed + etype = rclass.fishllattr(exc_data, 'exc_type') + if etype: + evalue = rclass.fishllattr(exc_data, 'exc_value') + if tracer: + tracer.dump('raise') + raise LLException(etype, evalue) if tracer: tracer.dump('return') resultvar, = block.getvariables() @@ -504,7 +514,19 @@ def op_direct_call(self, f, *args): FTYPE = self.llinterpreter.typer.type_system.derefType(lltype.typeOf(f)) - return self.perform_call(f, FTYPE.ARGS, args) + try: + return self.perform_call(f, FTYPE.ARGS, args) + except LLException, e: + if hasattr(self.graph, 'exceptiontransformed'): + # store the LLException into the exc_data used by this graph + exc_data = self.graph.exceptiontransformed + etype = e.args[0] + evalue = e.args[1] + rclass.feedllattr(exc_data, 'exc_type', etype) + rclass.feedllattr(exc_data, 'exc_value', evalue) + from pypy.translator.c.exceptiontransform import error_value + return error_value(FTYPE.RESULT).value + raise op_safe_call = op_direct_call Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Wed Sep 6 21:34:33 2006 @@ -858,3 +858,17 @@ raise AttributeError("%s has no field %s" % (lltype.typeOf(widest), name)) return default + +def feedllattr(inst, name, llvalue): + p = widest = lltype.normalizeptr(inst) + while True: + try: + return setattr(p, 'inst_' + name, llvalue) + except AttributeError: + pass + try: + p = p.super + except AttributeError: + break + raise AttributeError("%s has no field %s" % (lltype.typeOf(widest), + name)) Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Wed Sep 6 21:34:33 2006 @@ -5,7 +5,7 @@ from pypy.rpython.rmodel import inputconst from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.rint import signed_repr -from pypy.rpython.lltypesystem import rstr +from pypy.rpython.lltypesystem import rstr, lltype from pypy.annotation import model as annmodel from pypy.annotation.model import lltype_to_annotation from pypy.rpython.rarithmetic import r_uint, ovfcheck @@ -495,3 +495,53 @@ graph = graphof(t, bb) interp = LLInterpreter(t.rtyper) res = interp.eval_graph(graph, [1]) + +def test_half_exceptiontransformed_graphs(): + from pypy.translator.c import exceptiontransform + def f1(x): + if x < 0: + raise ValueError + return 754 + def g1(x): + try: + return f1(x) + except ValueError: + return 5 + def f2(x): + if x < 0: + raise ValueError + return 21 + def g2(x): + try: + return f2(x) + except ValueError: + return 6 + f3 = lltype.functionptr(lltype.FuncType([lltype.Signed], lltype.Signed), + 'f3', _callable = f1) + def g3(x): + try: + return f3(x) + except ValueError: + return 7 + def f(flag, x): + if flag == 1: + return g1(x) + elif flag == 2: + return g2(x) + else: + return g3(x) + t = TranslationContext() + t.buildannotator().build_types(f, [int, int]) + t.buildrtyper().specialize() + etrafo = exceptiontransform.ExceptionTransformer(t) + etrafo.create_exception_handling(graphof(t, f1)) + etrafo.create_exception_handling(graphof(t, g2)) + etrafo.create_exception_handling(graphof(t, g3)) + graph = graphof(t, f) + interp = LLInterpreter(t.rtyper) + res = interp.eval_graph(graph, [1, -64]) + assert res == 5 + res = interp.eval_graph(graph, [2, -897]) + assert res == 6 + res = interp.eval_graph(graph, [3, -9831]) + assert res == 7 Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Wed Sep 6 21:34:33 2006 @@ -137,13 +137,12 @@ ExcDataDef = translator.annotator.bookkeeper.getuniqueclassdef(ExcData) self.ExcData_repr = rclass.getinstancerepr(translator.rtyper, ExcDataDef) - exc_data_ptr = self.ExcData_repr.convert_const(exc_data) - self.cexcdata = Constant(exc_data_ptr, self.ExcData_repr.lowleveltype) + self.exc_data_ptr = self.ExcData_repr.convert_const(exc_data) + self.cexcdata = Constant(self.exc_data_ptr, + self.ExcData_repr.lowleveltype) self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping() - self.seen_graphs = {} - def transform_completely(self): for graph in self.translator.graphs: self.create_exception_handling(graph) @@ -156,8 +155,12 @@ from the current graph with a special value (False/-1/-1.0/null). Because of the added exitswitch we need an additional block. """ - assert graph not in self.seen_graphs - self.seen_graphs[graph] = True + if hasattr(graph, 'exceptiontransformed'): + assert self.exc_data_ptr._same_obj(graph.exceptiontransformed) + return + else: + graph.exceptiontransformed = self.exc_data_ptr + join_blocks(graph) # collect the blocks before changing them n_need_exc_matching_blocks = 0 Modified: pypy/dist/pypy/translator/c/test/test_exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/test/test_exceptiontransform.py Wed Sep 6 21:34:33 2006 @@ -185,4 +185,5 @@ g = graphof(t, f) etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(g) - py.test.raises(AssertionError, etrafo.create_exception_handling, g) + etrafo2 = exceptiontransform.ExceptionTransformer(t) + py.test.raises(AssertionError, etrafo2.create_exception_handling, g) From arigo at codespeak.net Thu Sep 7 00:25:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 00:25:50 +0200 (CEST) Subject: [pypy-svn] r32035 - in pypy/dist/pypy: jit/hintannotator jit/timeshifter jit/timeshifter/test rpython translator translator/backendopt translator/c Message-ID: <20060906222550.7F96410077@code0.codespeak.net> Author: arigo Date: Thu Sep 7 00:25:47 2006 New Revision: 32035 Modified: pypy/dist/pypy/jit/hintannotator/annotator.py pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/timeshifter/oop.py pypy/dist/pypy/jit/timeshifter/test/test_exception.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/jit/timeshifter/vlist.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/translator/backendopt/constfold.py pypy/dist/pypy/translator/c/exceptiontransform.py pypy/dist/pypy/translator/unsimplify.py Log: (pedronis, arigo) Pass an extra test about catching exceptions in JITted code. More and more based on the exceptiontransform, this required some clean-ups and a strange flag to the latter to produce graphs that give more hints to the JIT. Added a sanity-check to llinterp: when returning from exceptiontransformed graphs with an exception set, the return value should really be the special error value. Modified: pypy/dist/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/annotator.py Thu Sep 7 00:25:47 2006 @@ -14,8 +14,8 @@ bookkeeper=bookkeeper) self.base_translator = base_translator - if getattr(policy, 'exceptiontransform', True) and base_translator is not None: - self.exceptiontransformer = ExceptionTransformer(base_translator) + assert base_translator is not None # None not supported any more + self.exceptiontransformer = ExceptionTransformer(base_translator) def build_types(self, origgraph, input_args_hs): desc = self.bookkeeper.getdesc(origgraph) Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Thu Sep 7 00:25:47 2006 @@ -35,12 +35,12 @@ bk = self.bookkeeper graph = copygraph(self.origgraph) try: - exceptiontransformer = bk.annotator.exceptiontransformer + etrafo = bk.annotator.exceptiontransformer except AttributeError: pass else: # except transform the copied graph before its hint-annotation - exceptiontransformer.create_exception_handling(graph) + etrafo.create_exception_handling(graph, always_exc_clear=True) if alt_name is not None: graph.name = alt_name self._cache[key] = graph Modified: pypy/dist/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/oop.py (original) +++ pypy/dist/pypy/jit/timeshifter/oop.py Thu Sep 7 00:25:47 2006 @@ -54,7 +54,14 @@ None, None, [method]) self.ll_handler = getattr(vmodule, method) - def residual_call(self, builder, argboxes): + # exception handling + ts = hrtyper.timeshifter + graph = fnobj.graph + self.can_raise = ts.etrafo.raise_analyzer.analyze_direct_call(graph) + self.fetch_global_excdata = ts.fetch_global_excdata + + def residual_call(self, jitstate, argboxes): + builder = jitstate.curbuilder args_gv = self.args_gv[:] argpositions = self.argpositions for i in range(len(argpositions)): @@ -63,4 +70,6 @@ gv_arg = argboxes[i].getgenvar(builder) args_gv[pos] = gv_arg gv_result = builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv) + if self.can_raise: + self.fetch_global_excdata(jitstate) return self.redboxbuilder(self.result_kind, gv_result) Modified: pypy/dist/pypy/jit/timeshifter/test/test_exception.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_exception.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_exception.py Thu Sep 7 00:25:47 2006 @@ -3,6 +3,7 @@ from pypy.rpython.llinterp import LLException from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL +from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC class TestException(TimeshiftingTests): @@ -67,3 +68,43 @@ res = self.timeshift(ll_function, [17], [0], policy=P_NOVIRTUAL) assert res == 24 self.check_insns({}) + + def test_catch_from_outside(self): + def ll_function(x): + lst = [5] + if x: + lst.append(x) + # 'lst' is forced at this point + try: + return lst[1] * 2 # direct_call to ll_getitem + except IndexError: + return -11 + + res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC) + assert res == -11 + + res = self.timeshift(ll_function, [0], [0], policy=P_OOPSPEC) + assert res == -11 + + res = self.timeshift(ll_function, [17], [0], policy=P_OOPSPEC) + assert res == 34 + + def test_exception_from_virtual(self): + py.test.skip("in-progress... regress... sidewaysgress") + def ll_function(n): + lst = [] + lst.append(5) + try: + return lst[n] # direct_call to ll_getitem + except IndexError: + return -11 + + res = self.timeshift(ll_function, [2], [0], policy=P_OOPSPEC) + assert res == -11 + + res = self.timeshift(ll_function, [0], [0], policy=P_OOPSPEC) + assert res == 5 + + # the next case degenerates anyway + res = self.timeshift(ll_function, [2], [], policy=P_OOPSPEC) + assert res == -11 Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 7 00:25:47 2006 @@ -265,6 +265,7 @@ # now try to run the residual graph generated by the builder residual_graph = ll_generated._obj.graph + residual_graph.exceptiontransformed = self.htshift.exc_data_ptr if conftest.option.view: residual_graph.show() self.insns = summary(residual_graph) Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Thu Sep 7 00:25:47 2006 @@ -49,8 +49,10 @@ ## self.r_box_accum = getrepr(self.s_box_accum) ## self.r_box_accum.setup() - self.cexcdata = hannotator.exceptiontransformer.cexcdata - gv_excdata = RGenOp.constPrebuiltGlobal(self.cexcdata.value) + self.etrafo = hannotator.exceptiontransformer + self.cexcdata = self.etrafo.cexcdata + self.exc_data_ptr = self.cexcdata.value + gv_excdata = RGenOp.constPrebuiltGlobal(self.exc_data_ptr) LL_EXC_TYPE = rtyper.exceptiondata.lltype_of_exception_type LL_EXC_VALUE = rtyper.exceptiondata.lltype_of_exception_value null_exc_type_box = rvalue.redbox_from_prebuilt_value(RGenOp, @@ -58,6 +60,33 @@ null_exc_value_box = rvalue.redbox_from_prebuilt_value(RGenOp, lltype.nullptr(LL_EXC_VALUE.TO)) + p = self.etrafo.rpyexc_fetch_type_ptr.value + gv_rpyexc_fetch_type = RGenOp.constPrebuiltGlobal(p) + tok_fetch_type = RGenOp.sigToken(lltype.typeOf(p).TO) + kind_etype = RGenOp.kindToken(LL_EXC_TYPE) + + p = self.etrafo.rpyexc_fetch_value_ptr.value + gv_rpyexc_fetch_value = RGenOp.constPrebuiltGlobal(p) + tok_fetch_value = RGenOp.sigToken(lltype.typeOf(p).TO) + kind_evalue = RGenOp.kindToken(LL_EXC_VALUE) + + p = self.etrafo.rpyexc_clear_ptr.value + gv_rpyexc_clear = RGenOp.constPrebuiltGlobal(p) + tok_clear = RGenOp.sigToken(lltype.typeOf(p).TO) + + def fetch_global_excdata(jitstate): + builder = jitstate.curbuilder + gv_etype = builder.genop_call(tok_fetch_type, + gv_rpyexc_fetch_type, []) + gv_evalue = builder.genop_call(tok_fetch_value, + gv_rpyexc_fetch_value, []) + builder.genop_call(tok_clear, gv_rpyexc_clear, []) + etypebox = rvalue.PtrRedBox(kind_etype, gv_etype) + evaluebox = rvalue.PtrRedBox(kind_evalue, gv_evalue) + rtimeshift.setexctypebox (jitstate, etypebox) + rtimeshift.setexcvaluebox(jitstate, evaluebox) + self.fetch_global_excdata = fetch_global_excdata + def ll_fresh_jitstate(builder): return JITState(builder, None, null_exc_type_box, @@ -192,6 +221,10 @@ self.insert_start_setup() self.insert_v_jitstate_everywhere() + + # and now... the graph is timeshifted, so it is *itself* no longer + # exception-transformed... + del graph.exceptiontransformed #print 'timeshift_graph END', graph def insert_v_jitstate_everywhere(self): Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Thu Sep 7 00:25:47 2006 @@ -135,24 +135,24 @@ length = rvalue.ll_getvalue(lengthbox, lltype.Signed) if length == 0 or itembox is not None: return oopspecdesc.typedesc.factory(length, itembox) - return oopspecdesc.residual_call(jitstate.curbuilder, [lengthbox, itembox]) + return oopspecdesc.residual_call(jitstate, [lengthbox, itembox]) def oop_list_append(jitstate, oopspecdesc, selfbox, itembox): if isinstance(selfbox.content, VirtualList): selfbox.content.item_boxes.append(itembox) else: - oopspecdesc.residual_call(jitstate.curbuilder, [selfbox, itembox]) + oopspecdesc.residual_call(jitstate, [selfbox, itembox]) def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) return selfbox.content.item_boxes[index] else: - return oopspecdesc.residual_call(jitstate.curbuilder, [selfbox, indexbox]) + return oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) def oop_list_setitem(jitstate, oopspecdesc, selfbox, indexbox, itembox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) selfbox.content.item_boxes[index] = itembox else: - oopspecdesc.residual_call(jitstate.curbuilder, [selfbox, indexbox, itembox]) + oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Sep 7 00:25:47 2006 @@ -278,6 +278,8 @@ evalue = self.getval(evaluevar) # watch out, these are _ptr's raise LLException(etype, evalue) + resultvar, = block.getvariables() + result = self.getval(resultvar) if hasattr(self.graph, 'exceptiontransformed'): # re-raise the exception set by this graph, if any exc_data = self.graph.exceptiontransformed @@ -286,11 +288,15 @@ evalue = rclass.fishllattr(exc_data, 'exc_value') if tracer: tracer.dump('raise') + from pypy.translator.c import exceptiontransform + T = resultvar.concretetype + errvalue = exceptiontransform.error_value(T) + # check that the exc-transformed graph returns the error + # value when it returns with an exception set + assert result == errvalue raise LLException(etype, evalue) if tracer: tracer.dump('return') - resultvar, = block.getvariables() - result = self.getval(resultvar) return None, result elif block.exitswitch is None: # single-exit block @@ -524,8 +530,8 @@ evalue = e.args[1] rclass.feedllattr(exc_data, 'exc_type', etype) rclass.feedllattr(exc_data, 'exc_value', evalue) - from pypy.translator.c.exceptiontransform import error_value - return error_value(FTYPE.RESULT).value + from pypy.translator.c import exceptiontransform + return exceptiontransform.error_value(FTYPE.RESULT) raise op_safe_call = op_direct_call Modified: pypy/dist/pypy/translator/backendopt/constfold.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/constfold.py (original) +++ pypy/dist/pypy/translator/backendopt/constfold.py Thu Sep 7 00:25:47 2006 @@ -187,7 +187,7 @@ else: # split the block at the given position splitlink = split_block_with_keepalive(block, position) - assert block.exits == [splitlink] + assert list(block.exits) == [splitlink] assert link.target is block assert splitlink.prevblock is block complete_constants(link, constants) Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Thu Sep 7 00:25:47 2006 @@ -1,5 +1,6 @@ from pypy.translator.simplify import join_blocks, cleanup_graph from pypy.translator.unsimplify import copyvar, varoftype +from pypy.translator.unsimplify import insert_empty_block from pypy.translator.backendopt import canraise, inline, support, removenoops from pypy.objspace.flow.model import Block, Constant, Variable, Link, \ c_last_exception, SpaceOperation, checkgraph, FunctionGraph @@ -26,11 +27,14 @@ def error_value(T): if isinstance(T, lltype.Primitive): - return Constant(PrimitiveErrorValue[T], T) + return PrimitiveErrorValue[T] elif isinstance(T, lltype.Ptr): - return Constant(lltype.nullptr(T.TO), T) + return lltype.nullptr(T.TO) assert 0, "not implemented yet" +def error_constant(T): + return Constant(error_value(T), T) + class ExceptionTransformer(object): def __init__(self, translator): self.translator = translator @@ -142,12 +146,16 @@ self.ExcData_repr.lowleveltype) self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping() + p = lltype.nullptr(self.lltype_of_exception_type.TO) + self.c_null_etype = Constant(p, self.lltype_of_exception_type) + p = lltype.nullptr(self.lltype_of_exception_value.TO) + self.c_null_evalue = Constant(p, self.lltype_of_exception_value) def transform_completely(self): for graph in self.translator.graphs: self.create_exception_handling(graph) - def create_exception_handling(self, graph): + def create_exception_handling(self, graph, always_exc_clear=False): """After an exception in a direct_call (or indirect_call), that is not caught by an explicit except statement, we need to reraise the exception. So after this @@ -161,6 +169,7 @@ else: graph.exceptiontransformed = self.exc_data_ptr + self.always_exc_clear = always_exc_clear join_blocks(graph) # collect the blocks before changing them n_need_exc_matching_blocks = 0 @@ -202,11 +211,8 @@ if lastblock is block: lastblock = afterblock - self.gen_exc_check(block, graph.returnblock) + self.gen_exc_check(block, graph.returnblock, afterblock) n_gen_exc_checks += 1 - - #non-exception case - block.exits[0].exitcase = block.exits[0].llexitcase = False if need_exc_matching: assert lastblock.exitswitch == c_last_exception if not self.raise_analyzer.can_raise(lastblock.operations[-1]): @@ -228,9 +234,8 @@ result.concretetype = lltype.Void block.operations = [SpaceOperation( "direct_call", [self.rpyexc_raise_ptr] + block.inputargs, result)] - l = Link([error_value(graph.returnblock.inputargs[0].concretetype)], graph.returnblock) - l.prevblock = block - block.exits = [l] + l = Link([error_constant(graph.returnblock.inputargs[0].concretetype)], graph.returnblock) + block.recloseblock(l) def insert_matching(self, block, graph): proxygraph, op = self.create_proxy_graph(block.operations[-1]) @@ -271,31 +276,28 @@ startblock.operations.append(newop) newgraph = FunctionGraph("dummy_exc1", startblock) startblock.closeblock(Link([result], newgraph.returnblock)) - startblock.exits = list(startblock.exits) newgraph.returnblock.inputargs[0].concretetype = op.result.concretetype self.gen_exc_check(startblock, newgraph.returnblock) - startblock.exits[0].exitcase = startblock.exits[0].llexitcase = False excblock = Block([]) - var_value = varoftype(self.lltype_of_exception_value) - var_type = varoftype(self.lltype_of_exception_type) - var_void = varoftype(lltype.Void) - excblock.operations.append(SpaceOperation( - "direct_call", [self.rpyexc_fetch_value_ptr], var_value)) - excblock.operations.append(SpaceOperation( - "direct_call", [self.rpyexc_fetch_type_ptr], var_type)) - excblock.operations.append(SpaceOperation( - "direct_call", [self.rpyexc_clear_ptr], var_void)) + + llops = rtyper.LowLevelOpList(None) + r = self.ExcData_repr + var_value = r.getfield(self.cexcdata, 'exc_value', llops) + var_type = r.getfield(self.cexcdata, 'exc_type', llops) + r.setfield(self.cexcdata, 'exc_value', self.c_null_evalue, llops) + r.setfield(self.cexcdata, 'exc_type', self.c_null_etype, llops) + excblock.operations[:] = llops newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value excblock.closeblock(Link([var_type, var_value], newgraph.exceptblock)) startblock.exits[True].target = excblock startblock.exits[True].args = [] FUNCTYPE = lltype.FuncType(ARGTYPES, op.result.concretetype) - fptr = Constant(lltype.functionptr(FUNCTYPE, "dummy_exc2", graph=newgraph), + fptr = Constant(lltype.functionptr(FUNCTYPE, "dummy_exc1", graph=newgraph), lltype.Ptr(FUNCTYPE)) return newgraph, SpaceOperation("direct_call", [fptr] + callargs, op.result) - def gen_exc_check(self, block, returnblock): + def gen_exc_check(self, block, returnblock, normalafterblock=None): #var_exc_occured = Variable() #var_exc_occured.concretetype = lltype.Bool #block.operations.append(SpaceOperation("safe_call", [self.rpyexc_occured_ptr], var_exc_occured)) @@ -327,9 +329,22 @@ block.exitswitch = var_exc_occured #exception occurred case - l = Link([error_value(returnblock.inputargs[0].concretetype)], returnblock) - l.prevblock = block + l = Link([error_constant(returnblock.inputargs[0].concretetype)], returnblock) l.exitcase = l.llexitcase = True - block.exits.append(l) + #non-exception case + l0 = block.exits[0] + l0.exitcase = l0.llexitcase = False + + block.recloseblock(l0, l) + if self.always_exc_clear: + # insert code that clears the exception even in the non-exceptional + # case... this is a hint for the JIT, but pointless otherwise + if normalafterblock is None: + normalafterblock = insert_empty_block(None, l0) + llops = rtyper.LowLevelOpList(None) + r = self.ExcData_repr + r.setfield(self.cexcdata, 'exc_value', self.c_null_evalue, llops) + r.setfield(self.cexcdata, 'exc_type', self.c_null_etype, llops) + normalafterblock.operations[:0] = llops Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Thu Sep 7 00:25:47 2006 @@ -101,15 +101,12 @@ #from block the old block newblock = Block(varmap.values()) newblock.operations = moved_operations - newblock.exits = links + newblock.recloseblock(*links) newblock.exitswitch = exitswitch newblock.exc_handler = block.exc_handler - for link in newblock.exits: - link.prevblock = newblock link = Link(varmap.keys(), newblock) - link.prevblock = block block.operations = block.operations[:index] - block.exits = [link] + block.recloseblock(link) block.exitswitch = None block.exc_handler = False return link From arigo at codespeak.net Thu Sep 7 00:43:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 00:43:02 +0200 (CEST) Subject: [pypy-svn] r32036 - pypy/dist/pypy/rpython Message-ID: <20060906224302.9AD2310077@code0.codespeak.net> Author: arigo Date: Thu Sep 7 00:43:00 2006 New Revision: 32036 Modified: pypy/dist/pypy/rpython/llinterp.py Log: (arigo, pedronis) clear the values in excdata when reading them otherwise confusing reraising could happen. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Sep 7 00:43:00 2006 @@ -288,6 +288,10 @@ evalue = rclass.fishllattr(exc_data, 'exc_value') if tracer: tracer.dump('raise') + rclass.feedllattr(exc_data, 'exc_type', + lltype.typeOf(etype)._defl()) + rclass.feedllattr(exc_data, 'exc_value', + lltype.typeOf(evalue)._defl()) from pypy.translator.c import exceptiontransform T = resultvar.concretetype errvalue = exceptiontransform.error_value(T) From mwh at codespeak.net Thu Sep 7 11:01:36 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Sep 2006 11:01:36 +0200 (CEST) Subject: [pypy-svn] r32039 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060907090136.932C810072@code0.codespeak.net> Author: mwh Date: Thu Sep 7 11:01:35 2006 New Revision: 32039 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py Log: trivial fix, testing new commit bot Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Thu Sep 7 11:01:35 2006 @@ -18,7 +18,7 @@ def __init__(self, TYPE): self.TYPE = TYPE def __repr__(self): - return ''%(self.TYPE,) def saferecursive(func, defl): From arigo at codespeak.net Thu Sep 7 11:06:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 11:06:58 +0200 (CEST) Subject: [pypy-svn] r32041 - pypy/dist/pypy/doc Message-ID: <20060907090658.2791410077@code0.codespeak.net> Author: arigo Date: Thu Sep 7 11:06:57 2006 New Revision: 32041 Modified: pypy/dist/pypy/doc/dev_method.txt Log: Realign columns. UTF8->iso-8859-1 for now. Modified: pypy/dist/pypy/doc/dev_method.txt ============================================================================== --- pypy/dist/pypy/doc/dev_method.txt (original) +++ pypy/dist/pypy/doc/dev_method.txt Thu Sep 7 11:06:57 2006 @@ -245,28 +245,28 @@ The PyPy team have been sprinting on the following occasions:: - * Hildesheim Feb 2003 - * Gothenburg May 2003 - * LovainLaNeuve June 2003 - * Berlin Sept 2003 - * Amsterdam Dec 2003 - * Europython /Gothenburg June 2004 - * Vilnius Nov 2004 - * Leysin Jan 2005 - * PyCon/Washington March 2005 - * Europython/Gothenburg June 2005 - * Hildesheim July 2005 + * Hildesheim Feb 2003 + * Gothenburg May 2003 + * Europython/Louvain-La-Neuve June 2003 + * Berlin Sept 2003 + * Amsterdam Dec 2003 + * Europython/Gothenburg June 2004 + * Vilnius Nov 2004 + * Leysin Jan 2005 + * PyCon/Washington March 2005 + * Europython/Gothenburg June 2005 + * Hildesheim July 2005 * Heidelberg Aug 2005 - * Paris Oct 2005 - * Gothenburg Dec 2005 - * Mallorca Jan 2006 - * PyCon/Dallas Feb 2006 - * LouvainLaNeuve March 2006 - * Leysin April 2006 - * Tokyo April 2006 - * D?sseldorf June 2006 - * Europython/Geneva July 2006 - * Limerick Aug 2006 + * Paris Oct 2005 + * Gothenburg Dec 2005 + * Mallorca Jan 2006 + * PyCon/Dallas Feb 2006 + * Louvain-La-Neuve March 2006 + * Leysin April 2006 + * Tokyo April 2006 + * D?sseldorf June 2006 + * Europython/Geneva July 2006 + * Limerick Aug 2006 People who have participated and contributed during our sprints and thus @@ -278,10 +278,10 @@ Samuele Pedroni Christian Tismer Laura Creighton - Jacob Hall??n + Jacob Hall?n Michael Hudson Richard Emslie - Anders Chrigstr??m + Anders Chrigstr?m Alex Martelli Ludovic Aubry Adrien DiMascio @@ -315,8 +315,8 @@ Alan McIntyre Lutz Paelike Michael Chermside - Beatrice D??ring - Boris Feigin + Beatrice D?ring + Boris Feigin Amaury Forgeot d'Arc Andrew Thompson Valentino Volonghi From fijal at codespeak.net Thu Sep 7 11:34:02 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 7 Sep 2006 11:34:02 +0200 (CEST) Subject: [pypy-svn] r32042 - pypy/dist/pypy/rpython Message-ID: <20060907093402.0AFAF10077@code0.codespeak.net> Author: fijal Date: Thu Sep 7 11:33:46 2006 New Revision: 32042 Modified: pypy/dist/pypy/rpython/nonconst.py pypy/dist/pypy/rpython/rexternalobj.py Log: is-true for external object. Fixed nonconst to appear in rtyped graphs as constant. Modified: pypy/dist/pypy/rpython/nonconst.py ============================================================================== --- pypy/dist/pypy/rpython/nonconst.py (original) +++ pypy/dist/pypy/rpython/nonconst.py Thu Sep 7 11:33:46 2006 @@ -5,6 +5,7 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation.bookkeeper import getbookkeeper from pypy.objspace.flow.model import Variable, Constant +from pypy.rpython.lltypesystem import lltype class NonConstant(object): def __init__(self, _constant): @@ -20,6 +21,9 @@ return arg def specialize_call(self, hop): - v = Variable() - v.concretetype = hop.r_result.lowleveltype - return v + #v = Variable() + #v.concretetype = hop.r_result.lowleveltype + hop.exception_is_here() + retval = Constant(hop.r_result.convert_const(hop.args_v[0].value)) + retval.concretetype = hop.r_result.lowleveltype + return retval Modified: pypy/dist/pypy/rpython/rexternalobj.py ============================================================================== --- pypy/dist/pypy/rpython/rexternalobj.py (original) +++ pypy/dist/pypy/rpython/rexternalobj.py Thu Sep 7 11:33:46 2006 @@ -63,6 +63,11 @@ hop.exception_is_here() return hop.genop('oosend', [Constant(name)] + vlist, resulttype=hop.r_result) + def rtype_is_true(self, hop): + vlist = hop.inputargs(self) + return hop.genop('is_true', vlist, resulttype=lltype.Bool) + + def __getattr__(self, attr): if attr.startswith("rtype_method_"): name = attr[len("rtype_method_"):] From fijal at codespeak.net Thu Sep 7 11:35:22 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 7 Sep 2006 11:35:22 +0200 (CEST) Subject: [pypy-svn] r32043 - in pypy/dist/pypy/translator/transformer: . test Message-ID: <20060907093522.9F2BB10079@code0.codespeak.net> Author: fijal Date: Thu Sep 7 11:35:05 2006 New Revision: 32043 Modified: pypy/dist/pypy/translator/transformer/basictransform.py pypy/dist/pypy/translator/transformer/test/test_basictransform.py Log: Added checkgraph and some tests. Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Thu Sep 7 11:35:05 2006 @@ -6,10 +6,10 @@ from pypy.translator.unsimplify import varoftype from pypy.annotation import model as annmodel from pypy.objspace.flow import model -#from pypy.translator.js.helper import main_exception_helper, ExceptionHelper from pypy.rpython.ootypesystem import ootype from pypy.rpython.ootypesystem import rclass from pypy.rpython.annlowlevel import MixLevelHelperAnnotator +from pypy.objspace.flow.model import checkgraph class BasicTransformer(object): """ This is basic transformer which applies after annotation level. @@ -64,7 +64,9 @@ bk = self.translator.annotator.bookkeeper for graph in self.translator.graphs: self.transform_graph(graph) + checkgraph(graph) self.translator.annotator.complete() + def get_const(self, arg): bk = self.bookkeeper Modified: pypy/dist/pypy/translator/transformer/test/test_basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_basictransform.py Thu Sep 7 11:35:05 2006 @@ -8,6 +8,7 @@ from pypy.rpython import llinterp from pypy.objspace.flow import model from pypy.translator.unsimplify import copyvar +from pypy.rpython.nonconst import NonConstant def transform_function(transformerclass, fun, annotation=[], specialize=True, type_system="ootype"): @@ -115,6 +116,31 @@ res = interp_fun(t, helper_call_fun) assert res == 11 +class A(object): + def __init__(self): + self.l = [] + + def add(self, item): + self.l.append(item) + +a = A() + +class EmptyTransformer(BasicTransformer): + def transform_graph(self, graph): + pass + +def test_list_buildup(): + def f(): + a.add(NonConstant("item2")) + + def wrapper(): + a.add("item") + f() + return a.l[2:] + + t = transform_function(EmptyTransformer, wrapper) + #res = interp_fun(t, wrapper) + #assert res._list == [] ##def test_transform(): ## def fun(i): From fijal at codespeak.net Thu Sep 7 11:37:19 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 7 Sep 2006 11:37:19 +0200 (CEST) Subject: [pypy-svn] r32044 - pypy/dist/pypy/translator/js Message-ID: <20060907093719.A275B10079@code0.codespeak.net> Author: fijal Date: Thu Sep 7 11:37:06 2006 New Revision: 32044 Modified: pypy/dist/pypy/translator/js/helper.py Log: Cut last line of traceback. Modified: pypy/dist/pypy/translator/js/helper.py ============================================================================== --- pypy/dist/pypy/translator/js/helper.py (original) +++ pypy/dist/pypy/translator/js/helper.py Thu Sep 7 11:37:06 2006 @@ -25,7 +25,7 @@ pre_div = get_document().createElement("pre") pre_div.style.color = "#FF0000" debug_div.appendChild(pre_div) - for tb_entry in tb: + for tb_entry in tb[1:]: # list of tuples... fun_name, args, filename, lineno = tb_entry # some source maybe? or so? From fijal at codespeak.net Thu Sep 7 12:34:16 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 7 Sep 2006 12:34:16 +0200 (CEST) Subject: [pypy-svn] r32045 - in pypy/dist/pypy: annotation rpython Message-ID: <20060907103416.90CD110077@code0.codespeak.net> Author: fijal Date: Thu Sep 7 12:34:00 2006 New Revision: 32045 Modified: pypy/dist/pypy/annotation/listdef.py pypy/dist/pypy/rpython/rlist.py Log: Changed *is* operator on list annotations to equality of elements definition. If this stuff breaks anything, please just revert it. Modified: pypy/dist/pypy/annotation/listdef.py ============================================================================== --- pypy/dist/pypy/annotation/listdef.py (original) +++ pypy/dist/pypy/annotation/listdef.py Thu Sep 7 12:34:00 2006 @@ -109,6 +109,15 @@ for position_key in self.read_locations: self.bookkeeper.annotator.reflowfromposition(position_key) return updated + + def __eq__(self, other): + return self.s_value is other.s_value or self.s_value == other.s_value + + def __ne__(self, other): + return self.s_value is not other.s_value and self.s_value != other.s_value + + def __hash__(self): + return hash(self.s_value) class ListDef: @@ -138,7 +147,7 @@ return self.listitem.s_value def same_as(self, other): - return self.listitem is other.listitem + return self.listitem == other.listitem def union(self, other): if (self.same_as(MOST_GENERAL_LISTDEF) or Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Sep 7 12:34:00 2006 @@ -242,7 +242,7 @@ def convert_from_to((r_lst1, r_lst2), v, llops): if r_lst1.listitem is None or r_lst2.listitem is None: return NotImplemented - if r_lst1.listitem is not r_lst2.listitem: + if r_lst1.listitem != r_lst2.listitem: return NotImplemented return v From pedronis at codespeak.net Thu Sep 7 13:21:51 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 7 Sep 2006 13:21:51 +0200 (CEST) Subject: [pypy-svn] r32046 - in pypy/dist/pypy: annotation rpython Message-ID: <20060907112151.BB76B10077@code0.codespeak.net> Author: pedronis Date: Thu Sep 7 13:21:49 2006 New Revision: 32046 Modified: pypy/dist/pypy/annotation/listdef.py pypy/dist/pypy/rpython/rlist.py Log: (arigo, pedronis) reverting checkin from outer-space: listitem are meant to be compared by identity, listdefs unify by sharing identical listitems. Modified: pypy/dist/pypy/annotation/listdef.py ============================================================================== --- pypy/dist/pypy/annotation/listdef.py (original) +++ pypy/dist/pypy/annotation/listdef.py Thu Sep 7 13:21:49 2006 @@ -109,15 +109,6 @@ for position_key in self.read_locations: self.bookkeeper.annotator.reflowfromposition(position_key) return updated - - def __eq__(self, other): - return self.s_value is other.s_value or self.s_value == other.s_value - - def __ne__(self, other): - return self.s_value is not other.s_value and self.s_value != other.s_value - - def __hash__(self): - return hash(self.s_value) class ListDef: @@ -147,7 +138,7 @@ return self.listitem.s_value def same_as(self, other): - return self.listitem == other.listitem + return self.listitem is other.listitem def union(self, other): if (self.same_as(MOST_GENERAL_LISTDEF) or Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Sep 7 13:21:49 2006 @@ -242,7 +242,7 @@ def convert_from_to((r_lst1, r_lst2), v, llops): if r_lst1.listitem is None or r_lst2.listitem is None: return NotImplemented - if r_lst1.listitem != r_lst2.listitem: + if r_lst1.listitem is not r_lst2.listitem: return NotImplemented return v From arigo at codespeak.net Thu Sep 7 14:25:46 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 14:25:46 +0200 (CEST) Subject: [pypy-svn] r32047 - in pypy/dist/pypy: rpython/lltypesystem translator/c Message-ID: <20060907122546.994CB10072@code0.codespeak.net> Author: arigo Date: Thu Sep 7 14:25:44 2006 New Revision: 32047 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/opimpl.py pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/translator/c/funcgen.py Log: A 'debug_assert' low-level operation for quick checks of conditions. It goes away in C code. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Thu Sep 7 14:25:44 2006 @@ -397,7 +397,8 @@ 'debug_view': LLOp(), 'debug_print': LLOp(), 'debug_pdb': LLOp(), - 'debug_log_exc': LLOp() + 'debug_log_exc': LLOp(), + 'debug_assert': LLOp(canfold=True), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/opimpl.py Thu Sep 7 14:25:44 2006 @@ -355,6 +355,15 @@ raise TypeError("cannot fold getfield on mutable array") return p[index] + +def op_debug_assert(expr, *ll_args): + if not isinstance(expr, str): + expr = ''.join(expr.chars) + names = ['v%d' % i for i in range(len(ll_args))] + d = dict(zip(names, ll_args)) + names = tuple(names) + assert eval(expr % names, d) + # ____________________________________________________________ def get_op_impl(opname): Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Thu Sep 7 14:25:44 2006 @@ -387,10 +387,14 @@ def ll_items(l): return l.items +from pypy.rpython.lltypesystem.lloperation import llop + def ll_getitem_fast(l, index): + llop.debug_assert(Void, "%s < %s.length # getitem out of bounds", index, l) return l.ll_items()[index] def ll_setitem_fast(l, index, item): + llop.debug_assert(Void, "%s < %s.length # setitem out of bounds", index, l) l.ll_items()[index] = item # fixed size versions Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Thu Sep 7 14:25:44 2006 @@ -720,4 +720,7 @@ exc_type = self.expr(op.args[0]) return 'RPY_LOG_EXC(%s);' % exc_type + def OP_DEBUG_ASSERT(self, op): + return '/* debug_assert removed */' + assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) From mwh at codespeak.net Thu Sep 7 14:35:42 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Sep 2006 14:35:42 +0200 (CEST) Subject: [pypy-svn] r32049 - pypy/branch/more-gckinds Message-ID: <20060907123542.5427410072@code0.codespeak.net> Author: mwh Date: Thu Sep 7 14:35:41 2006 New Revision: 32049 Added: pypy/branch/more-gckinds/ - copied from r32048, pypy/dist/ Log: a branch to clean up the gc model of lltype slightly, and maybe get rid of keepalives. From arigo at codespeak.net Thu Sep 7 14:37:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 14:37:36 +0200 (CEST) Subject: [pypy-svn] r32050 - in pypy/dist/pypy: rpython/lltypesystem translator/llvm Message-ID: <20060907123736.AB9FD10079@code0.codespeak.net> Author: arigo Date: Thu Sep 7 14:37:35 2006 New Revision: 32050 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/translator/llvm/opwriter.py Log: - debug_assert is actually not canfold. Need a new canrun flag... - implement debug_assert in genllvm too. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Thu Sep 7 14:37:35 2006 @@ -9,7 +9,7 @@ class LLOp(object): def __init__(self, sideeffects=True, canfold=False, canraise=(), - pyobj=False, canunwindgc=False): + pyobj=False, canunwindgc=False, canrun=False): # self.opname = ... (set afterwards) if canfold: @@ -39,6 +39,9 @@ Exception not in self.canraise): self.canraise += (StackException,) + # The operation can be run directly with __call__ + self.canrun = canrun or canfold + # __________ make the LLOp instances callable from LL helpers __________ __name__ = property(lambda self: 'llop_'+self.opname) @@ -58,7 +61,7 @@ def get_fold_impl(self): global lltype # <- lazy import hack, worth an XXX from pypy.rpython.lltypesystem import lltype - if self.canfold or self.opname in ('getfield', 'getarrayitem'): + if self.canrun: from pypy.rpython.lltypesystem.opimpl import get_op_impl op_impl = get_op_impl(self.opname) else: @@ -296,8 +299,8 @@ 'zero_malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), 'flavored_malloc': LLOp(canraise=(MemoryError,)), 'flavored_free': LLOp(), - 'getfield': LLOp(sideeffects=False), - 'getarrayitem': LLOp(sideeffects=False), + 'getfield': LLOp(sideeffects=False, canrun=True), + 'getarrayitem': LLOp(sideeffects=False, canrun=True), 'getarraysize': LLOp(canfold=True), 'getsubstruct': LLOp(canfold=True), 'getarraysubstruct': LLOp(canfold=True), @@ -398,7 +401,7 @@ 'debug_print': LLOp(), 'debug_pdb': LLOp(), 'debug_log_exc': LLOp(), - 'debug_assert': LLOp(canfold=True), + 'debug_assert': LLOp(canrun=True), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Thu Sep 7 14:37:35 2006 @@ -176,6 +176,9 @@ # XXX tmp pass + def debug_assert(self, opr): + pass + def int_pow(self, opr): self._generic_pow(opr, "1") uint_pow = int_pow From cfbolz at codespeak.net Thu Sep 7 15:05:54 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 15:05:54 +0200 (CEST) Subject: [pypy-svn] r32051 - pypy/branch/config-in-more-places Message-ID: <20060907130554.D41FC10077@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 15:05:53 2006 New Revision: 32051 Added: pypy/branch/config-in-more-places/ - copied from r32050, pypy/dist/ Log: Branch for adding more places that use the new configuration machinery. From arigo at codespeak.net Thu Sep 7 15:24:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 15:24:02 +0200 (CEST) Subject: [pypy-svn] r32052 - in pypy/dist/pypy: jit/timeshifter jit/timeshifter/test rpython/lltypesystem Message-ID: <20060907132402.35CD51007A@code0.codespeak.net> Author: arigo Date: Thu Sep 7 15:23:56 2006 New Revision: 32052 Modified: pypy/dist/pypy/jit/timeshifter/oop.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/test/test_exception.py pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/jit/timeshifter/vlist.py pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py Log: (pedronis, arigo) Implement IndexErrors caused by virtual list manipulations. Modified: pypy/dist/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/oop.py (original) +++ pypy/dist/pypy/jit/timeshifter/oop.py Thu Sep 7 15:23:56 2006 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import lltype +from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.timeshifter.rcontainer import cachedtype -from pypy.jit.timeshifter import rvalue +from pypy.jit.timeshifter import rvalue, rtimeshift class Index: @@ -12,6 +13,7 @@ __metaclass__ = cachedtype def __init__(self, hrtyper, fnobj): + ts = hrtyper.timeshifter ll_func = fnobj._callable FUNCTYPE = lltype.typeOf(fnobj) nb_args = len(FUNCTYPE.ARGS) @@ -40,6 +42,12 @@ self.args_gv = [None] * nb_args self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnobj._as_ptr()) self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT) + if FUNCTYPE.RESULT is lltype.Void: + self.errorbox = None + else: + error_value = ts.error_value(FUNCTYPE.RESULT) + self.errorbox = rvalue.redbox_from_prebuilt_value(RGenOp, + error_value) self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT) self.sigtoken = RGenOp.sigToken(FUNCTYPE) @@ -55,7 +63,6 @@ self.ll_handler = getattr(vmodule, method) # exception handling - ts = hrtyper.timeshifter graph = fnobj.graph self.can_raise = ts.etrafo.raise_analyzer.analyze_direct_call(graph) self.fetch_global_excdata = ts.fetch_global_excdata @@ -73,3 +80,36 @@ if self.can_raise: self.fetch_global_excdata(jitstate) return self.redboxbuilder(self.result_kind, gv_result) + + def residual_exception(self, jitstate, ExcCls): + ll_evalue = get_ll_instance_for_exccls(ExcCls) + ll_etype = ll_evalue.typeptr + etypebox = rvalue.ll_fromvalue(jitstate, ll_etype) + evaluebox = rvalue.ll_fromvalue(jitstate, ll_evalue) + rtimeshift.setexctypebox (jitstate, etypebox ) + rtimeshift.setexcvaluebox(jitstate, evaluebox) + return self.errorbox + residual_exception._annspecialcase_ = 'specialize:arg(2)' + + +def get_ll_instance_for_exccls(ExcCls): + raise NotImplementedError + +class Entry(ExtRegistryEntry): + _about_ = get_ll_instance_for_exccls + + def compute_result_annotation(self, s_exccls): + from pypy.annotation import model as annmodel + assert s_exccls.is_constant() + bk = self.bookkeeper + excdata = bk.annotator.policy.rtyper.exceptiondata + return annmodel.lltype_to_annotation(excdata.lltype_of_exception_value) + + def specialize_call(self, hop): + ExcCls = hop.args_s[0].const + rtyper = hop.rtyper + bk = rtyper.annotator.bookkeeper + clsdef = bk.getuniqueclassdef(ExcCls) + excdata = rtyper.exceptiondata + ll_evalue = excdata.get_standard_ll_exc_instance(rtyper, clsdef) + return hop.inputconst(hop.r_result, ll_evalue) Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Thu Sep 7 15:23:56 2006 @@ -238,6 +238,7 @@ return jitstate.exitindex def save_locals(jitstate, redboxes): + assert None not in redboxes jitstate.frame.local_boxes = redboxes def getlocalbox(jitstate, i): Modified: pypy/dist/pypy/jit/timeshifter/test/test_exception.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_exception.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_exception.py Thu Sep 7 15:23:56 2006 @@ -90,7 +90,6 @@ assert res == 34 def test_exception_from_virtual(self): - py.test.skip("in-progress... regress... sidewaysgress") def ll_function(n): lst = [] lst.append(5) Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Thu Sep 7 15:23:56 2006 @@ -12,6 +12,7 @@ from pypy.jit.timeshifter.rtyper import GreenRepr, RedRepr, HintLowLevelOpList from pypy.translator.unsimplify import varoftype, copyvar from pypy.translator.backendopt import support +from pypy.translator.c import exceptiontransform from pypy.jit.codegen import model as cgmodel # ___________________________________________________________ @@ -97,6 +98,9 @@ # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) + def error_value(self, TYPE): + return exceptiontransform.error_value(TYPE) + # creates and numbers reentry_block for block reached by link # argument: # Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Thu Sep 7 15:23:56 2006 @@ -146,13 +146,19 @@ def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) - return selfbox.content.item_boxes[index] + try: + return selfbox.content.item_boxes[index] + except IndexError: + return oopspecdesc.residual_exception(jitstate, IndexError) else: return oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) def oop_list_setitem(jitstate, oopspecdesc, selfbox, indexbox, itembox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) - selfbox.content.item_boxes[index] = itembox + try: + selfbox.content.item_boxes[index] = itembox + except IndexError: + oopspecdesc.residual_exception(jitstate, IndexError) else: oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) Modified: pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py Thu Sep 7 15:23:56 2006 @@ -49,9 +49,7 @@ is_standard = (cls.__module__ == 'exceptions' and not clsdef.attrs) if is_standard: - r_inst = rclass.getinstancerepr(rtyper, clsdef) - example = r_inst.get_reusable_prebuilt_instance() - example = rclass.ll_cast_to_object(example) + example = self.get_standard_ll_exc_instance(rtyper, clsdef) table[cls] = example #else: # assert cls.__module__ != 'exceptions', ( @@ -106,3 +104,9 @@ s_pyobj = annmodel.SomePtr(Ptr(PyObject)) helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj]) return helper_fn + + def get_standard_ll_exc_instance(self, rtyper, clsdef): + r_inst = rclass.getinstancerepr(rtyper, clsdef) + example = r_inst.get_reusable_prebuilt_instance() + example = rclass.ll_cast_to_object(example) + return example From cfbolz at codespeak.net Thu Sep 7 15:32:34 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 15:32:34 +0200 (CEST) Subject: [pypy-svn] r32054 - in pypy/branch/config-in-more-places/pypy/config: . test Message-ID: <20060907133234.2C36810077@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 15:32:32 2006 New Revision: 32054 Modified: pypy/branch/config-in-more-places/pypy/config/config.py pypy/branch/config-in-more-places/pypy/config/test/test_config.py Log: allow to prevent some options from being exposed on the cmdline Modified: pypy/branch/config-in-more-places/pypy/config/config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/config.py Thu Sep 7 15:32:32 2006 @@ -106,8 +106,12 @@ paths.append('.'.join(currpath + [attr])) return paths + +DEFAULT_OPTION_NAME = object() + + class Option(object): - def __init__(self, name, doc, cmdline=None): + def __init__(self, name, doc, cmdline=DEFAULT_OPTION_NAME): self._name = name self.doc = doc self.cmdline = cmdline @@ -131,7 +135,7 @@ raise NotImplemented('abstract base class') class ChoiceOption(Option): - def __init__(self, name, doc, values, default, cmdline=None): + def __init__(self, name, doc, values, default, cmdline=DEFAULT_OPTION_NAME): super(ChoiceOption, self).__init__(name, doc, cmdline) self.values = values self.default = default @@ -150,7 +154,7 @@ callback=_callback, *argnames) class BoolOption(ChoiceOption): - def __init__(self, name, doc, default=True, requires=None, cmdline=None): + def __init__(self, name, doc, default=True, requires=None, cmdline=DEFAULT_OPTION_NAME): super(BoolOption, self).__init__(name, doc, [True, False], default, cmdline=cmdline) self._requires = requires or [] @@ -173,7 +177,7 @@ callback=_callback, *argnames) class IntOption(Option): - def __init__(self, name, doc, default=0, cmdline=None): + def __init__(self, name, doc, default=0, cmdline=DEFAULT_OPTION_NAME): super(IntOption, self).__init__(name, doc, cmdline) self.default = default @@ -198,7 +202,7 @@ callback=_callback, *argnames) class FloatOption(Option): - def __init__(self, name, doc, default=0.0, cmdline=None): + def __init__(self, name, doc, default=0.0, cmdline=DEFAULT_OPTION_NAME): super(FloatOption, self).__init__(name, doc, cmdline) self.default = default @@ -223,7 +227,7 @@ callback=_callback, *argnames) class OptionDescription(object): - def __init__(self, name, children, cmdline=None): + def __init__(self, name, children, cmdline=DEFAULT_OPTION_NAME): self._name = name self._children = children self._build() @@ -274,8 +278,10 @@ else: subconf, name = config._get_by_path(path) option = getattr(subconf._descr, name) - if option.cmdline is None: + if option.cmdline is DEFAULT_OPTION_NAME: chunks = ('--%s' % (path.replace('.', '-'),),) + elif option.cmdline is None: + continue else: chunks = option.cmdline.split(' ') option.add_optparse_option(chunks, parser, subconf) Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_config.py Thu Sep 7 15:32:32 2006 @@ -4,7 +4,7 @@ def make_description(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) - objspaceoption = ChoiceOption('objspace', 'Object space', + objspaceoption = ChoiceOption('objspace', 'Object space', ['std', 'logic'], 'std') booloption = BoolOption('bool', 'Test boolean option') intoption = IntOption('int', 'Test int option') @@ -115,7 +115,7 @@ assert config.gc.name == 'ref' # XXX strange exception - py.test.raises(SystemExit, + py.test.raises(SystemExit, "(options, args) = parser.parse_args(args=['-g foobar'])") def test_to_optparse_number(): @@ -211,3 +211,14 @@ assert config.getpaths(), ['gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'int'] assert config.gc.getpaths(), ['name', 'dummy', 'float'] + +def test_none(): + dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None) + dummy2 = BoolOption('dummy2', 'doc dummy', default=False, cmdline='--dummy') + group = OptionDescription('group', [dummy1, dummy2]) + config = Config(group) + + parser = to_optparse(config, config.getpaths()) + py.test.raises(SystemExit, + "(options, args) = parser.parse_args(args=['--dummy1'])") + From cfbolz at codespeak.net Thu Sep 7 15:33:23 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 15:33:23 +0200 (CEST) Subject: [pypy-svn] r32055 - pypy/branch/config-in-more-places/pypy/config Message-ID: <20060907133323.BEEDB1007A@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 15:33:22 2006 New Revision: 32055 Modified: pypy/branch/config-in-more-places/pypy/config/pypyoption.py Log: don't expose the "translating" option on the cmdline Modified: pypy/branch/config-in-more-places/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/pypyoption.py (original) +++ pypy/branch/config-in-more-places/pypy/config/pypyoption.py Thu Sep 7 15:33:22 2006 @@ -86,7 +86,7 @@ ]), BoolOption("translating", "indicates whether we are translating currently", - default=False), + default=False, cmdline=None), ]) if __name__ == '__main__': From arigo at codespeak.net Thu Sep 7 15:49:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 15:49:51 +0200 (CEST) Subject: [pypy-svn] r32056 - in pypy/dist/pypy/jit: codegen timeshifter timeshifter/test Message-ID: <20060907134951.3D4991007A@code0.codespeak.net> Author: arigo Date: Thu Sep 7 15:49:48 2006 New Revision: 32056 Modified: pypy/dist/pypy/jit/codegen/model.py pypy/dist/pypy/jit/timeshifter/test/test_exception.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/timeshift.py Log: (pedronis, arigo) An unusual check-in: adding a new feature to the JIT - here re-raising exceptions from generated code - without having to change the whole world again. Modified: pypy/dist/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/dist/pypy/jit/codegen/model.py Thu Sep 7 15:49:48 2006 @@ -1,7 +1,11 @@ +from pypy.rpython.objectmodel import specialize class GenVarOrConst(object): - pass + + @specialize.arg(1) + def revealconst(self, T): + raise NotImplementedError class GenVar(GenVarOrConst): is_const = False Modified: pypy/dist/pypy/jit/timeshifter/test/test_exception.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_exception.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_exception.py Thu Sep 7 15:49:48 2006 @@ -107,3 +107,18 @@ # the next case degenerates anyway res = self.timeshift(ll_function, [2], [], policy=P_OOPSPEC) assert res == -11 + + def test_exception_escapes(self): + def ll_function(n): + if n < 0: + raise ValueError + return n * 3 + + res = self.timeshift(ll_function, [2], [], policy=P_OOPSPEC) + assert res == 6 + + py.test.raises(LLException, + "self.timeshift(ll_function, [-3], [], policy=P_OOPSPEC)") + + py.test.raises(LLException, + "self.timeshift(ll_function, [-3], [0], policy=P_OOPSPEC)") Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 7 15:49:48 2006 @@ -90,6 +90,7 @@ # make the timeshifted graphs htshift = HintTimeshift(ha, rtyper, self.RGenOp) fresh_jitstate = htshift.ll_fresh_jitstate + finish_jitstate = htshift.ll_finish_jitstate RESTYPE = htshift.originalconcretetype( ha.translator.graphs[0].getreturnvar()) htshift.timeshift() @@ -174,9 +175,7 @@ top_jitstate = fresh_jitstate(builder) top_jitstate = timeshifted_entrypoint(top_jitstate, *timeshifted_entrypoint_args) - returnbox = rtimeshift.getreturnbox(top_jitstate) - gv_ret = returnbox.getgenvar(top_jitstate.curbuilder) - top_jitstate.curbuilder.finish_and_return(sigtoken, gv_ret) + finish_jitstate(top_jitstate, sigtoken) gv_generated = rgenop.gencallableconst(sigtoken, "generated", entrypoint) Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Thu Sep 7 15:49:48 2006 @@ -1,5 +1,5 @@ import py, types -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.objspace.flow import model as flowmodel from pypy.annotation import model as annmodel from pypy.annotation import listdef, dictdef @@ -75,6 +75,10 @@ gv_rpyexc_clear = RGenOp.constPrebuiltGlobal(p) tok_clear = RGenOp.sigToken(lltype.typeOf(p).TO) + p = self.etrafo.rpyexc_raise_ptr.value + gv_rpyexc_raise = RGenOp.constPrebuiltGlobal(p) + tok_raise = RGenOp.sigToken(lltype.typeOf(p).TO) + def fetch_global_excdata(jitstate): builder = jitstate.curbuilder gv_etype = builder.genop_call(tok_fetch_type, @@ -88,12 +92,34 @@ rtimeshift.setexcvaluebox(jitstate, evaluebox) self.fetch_global_excdata = fetch_global_excdata + def store_global_excdata(jitstate): + builder = jitstate.curbuilder + etypebox = jitstate.exc_type_box + if etypebox.is_constant(): + ll_etype = rvalue.ll_getvalue(etypebox, llmemory.Address) + if not ll_etype: + return # we known there is no exception set + evaluebox = jitstate.exc_value_box + gv_etype = etypebox .getgenvar(builder) + gv_evalue = evaluebox.getgenvar(builder) + builder.genop_call(tok_raise, + gv_rpyexc_raise, [gv_etype, gv_evalue]) + self.store_global_excdata = store_global_excdata + def ll_fresh_jitstate(builder): return JITState(builder, None, null_exc_type_box, null_exc_value_box) self.ll_fresh_jitstate = ll_fresh_jitstate + def ll_finish_jitstate(jitstate, graphsigtoken): + returnbox = rtimeshift.getreturnbox(jitstate) + gv_ret = returnbox.getgenvar(jitstate.curbuilder) + store_global_excdata(jitstate) + jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret) + self.ll_finish_jitstate = ll_finish_jitstate + + def s_r_instanceof(self, cls, can_be_None=True): # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) From mwh at codespeak.net Thu Sep 7 15:55:15 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Sep 2006 15:55:15 +0200 (CEST) Subject: [pypy-svn] r32057 - in pypy/branch/more-gckinds/pypy: rpython rpython/lltypesystem translator/c Message-ID: <20060907135515.86B1D10080@code0.codespeak.net> Author: mwh Date: Thu Sep 7 15:55:14 2006 New Revision: 32057 Modified: pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Log: first steps: make functions have _gckind=='prebuilt'. not too many scary corners were illuminated doing this. Modified: pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py Thu Sep 7 15:55:14 2006 @@ -178,7 +178,7 @@ return Constant(p, lltype.typeOf(p)) def graph2delayed(self, graph): - FUNCTYPE = lltype.ForwardReference() + FUNCTYPE = lltype.FuncForwardReference() # obscure hack: embed the name of the function in the string, so # that the genc database can get it even before the delayedptr # is really computed Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Thu Sep 7 15:55:14 2006 @@ -411,7 +411,7 @@ class FuncType(ContainerType): - _gckind = 'raw' + _gckind = 'prebuilt' __name__ = 'func' def __init__(self, args, result): for arg in args: @@ -512,6 +512,9 @@ class PyForwardReference(ForwardReference): _gckind = 'cpy' +class FuncForwardReference(ForwardReference): + _gckind = 'prebuilt' + FORWARDREF_BY_FLAVOR = {'raw': ForwardReference, 'gc': GcForwardReference, 'cpy': PyForwardReference} Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/funcgen.py (original) +++ pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Thu Sep 7 15:55:14 2006 @@ -10,7 +10,7 @@ from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray -from pypy.rpython.lltypesystem.lltype import ForwardReference +from pypy.rpython.lltypesystem.lltype import FuncForwardReference from pypy.rpython.lltypesystem.llmemory import Address, WeakGcAddress from pypy.translator.backendopt.ssa import SSI_to_SSA @@ -58,7 +58,7 @@ T = getattr(v, 'concretetype', PyObjPtr) # obscure: skip forward references and hope for the best # (needed for delayed function pointers) - if isinstance(T, Ptr) and T.TO.__class__ == ForwardReference: + if isinstance(T, Ptr) and T.TO.__class__ == FuncForwardReference: continue db.gettype(T) # force the type to be considered by the database From arigo at codespeak.net Thu Sep 7 16:49:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 16:49:37 +0200 (CEST) Subject: [pypy-svn] r32058 - in pypy/dist/pypy: jit/codegen/i386/test jit/hintannotator jit/timeshifter/test translator translator/c Message-ID: <20060907144937.A64C010072@code0.codespeak.net> Author: arigo Date: Thu Sep 7 16:49:33 2006 New Revision: 32058 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py pypy/dist/pypy/jit/hintannotator/annotator.py pypy/dist/pypy/jit/timeshifter/test/test_exception.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/translator.py Log: (pedronis, arigo) Ported the test_exception to the asm back-end. This needed a way to test for exception-raising examples, and unification of the exceptiontransformer used by the JIT and by GenC. Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py Thu Sep 7 16:49:33 2006 @@ -80,7 +80,11 @@ os.write(1, SEPLINE) bench = Benchmark() while 1: - res = generated(*residualargs) + try: + res = generated(*residualargs) + except Exception, e: + os.write(1, 'EXCEPTION: %s\n' % (e,)) + return 0 if bench.stop(): break os.write(1, convert_result(res) + '\n') @@ -122,6 +126,11 @@ os.write(2, '{%s: %s\n' % (testname, lines.pop(1)[1:])) assert len(lines) == 2 lastline = lines[1] + if 'check_raises' in kwds: + exc_name = kwds['check_raises'].__name__ + assert lastline.startswith('EXCEPTION: ') # else DID NOT RAISE + assert exc_name in lastline + return True if hasattr(ll_function, 'convert_result'): return lastline else: Modified: pypy/dist/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/annotator.py Thu Sep 7 16:49:33 2006 @@ -3,19 +3,17 @@ from pypy.jit.hintannotator.bookkeeper import HintBookkeeper from pypy.rpython.lltypesystem import lltype -from pypy.translator.c.exceptiontransform import ExceptionTransformer - class HintAnnotator(RPythonAnnotator): - def __init__(self, translator=None, base_translator=None, policy=None): + def __init__(self, translator=None, base_translator=None, policy=None): bookkeeper = HintBookkeeper(self) RPythonAnnotator.__init__(self, translator, policy=policy, bookkeeper=bookkeeper) self.base_translator = base_translator assert base_translator is not None # None not supported any more - self.exceptiontransformer = ExceptionTransformer(base_translator) + self.exceptiontransformer = base_translator.getexceptiontransformer() def build_types(self, origgraph, input_args_hs): desc = self.bookkeeper.getdesc(origgraph) Modified: pypy/dist/pypy/jit/timeshifter/test/test_exception.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_exception.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_exception.py Thu Sep 7 16:49:33 2006 @@ -1,6 +1,5 @@ import py from pypy.rpython.lltypesystem import lltype -from pypy.rpython.llinterp import LLException from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC @@ -33,19 +32,20 @@ return res s.flag = 0 - res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL) - assert res == -1 + self.timeshift_raises(ValueError, + ll_function, [0], [], policy=P_NOVIRTUAL) assert s.flag == 0 s.flag = 0 - res = self.timeshift(ll_function, [0], [0], policy=P_NOVIRTUAL) - assert res == -1 + self.timeshift_raises(ValueError, + ll_function, [0], [0], policy=P_NOVIRTUAL) assert s.flag == 0 s.flag = 0 res = self.timeshift(ll_function, [17], [0], policy=P_NOVIRTUAL) assert res == 24 - assert s.flag == 1 + if self.__class__ is TestException: # no chance to work with genc + assert s.flag == 1 self.check_insns({'setfield': 1}) def test_catch(self): @@ -117,8 +117,8 @@ res = self.timeshift(ll_function, [2], [], policy=P_OOPSPEC) assert res == 6 - py.test.raises(LLException, - "self.timeshift(ll_function, [-3], [], policy=P_OOPSPEC)") + self.timeshift_raises(ValueError, + ll_function, [-3], [], policy=P_OOPSPEC) - py.test.raises(LLException, - "self.timeshift(ll_function, [-3], [0], policy=P_OOPSPEC)") + self.timeshift_raises(ValueError, + ll_function, [-3], [0], policy=P_OOPSPEC) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 7 16:49:33 2006 @@ -12,7 +12,7 @@ from pypy.rpython.annlowlevel import PseudoHighLevelCallable from pypy.rpython.module.support import LLSupport from pypy.annotation import model as annmodel -from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.objspace.flow.model import checkgraph from pypy.annotation.policy import AnnotatorPolicy from pypy.translator.backendopt.inline import auto_inlining @@ -65,7 +65,8 @@ del cls._cache del cls._cache_order - def timeshift_cached(self, ll_function, values, inline=None, policy=None): + def timeshift_cached(self, ll_function, values, inline=None, policy=None, + check_raises='ignored anyway'): # decode the 'values' if they are specified as strings if hasattr(ll_function, 'convert_arguments'): assert len(ll_function.convert_arguments) == len(values) @@ -268,7 +269,20 @@ if conftest.option.view: residual_graph.show() self.insns = summary(residual_graph) - res = llinterp.eval_graph(residual_graph, residualargs) + + if 'check_raises' not in kwds: + res = llinterp.eval_graph(residual_graph, residualargs) + else: + try: + llinterp.eval_graph(residual_graph, residualargs) + except LLException, e: + exc = kwds['check_raises'] + assert llinterp.find_exception(e) is exc, ( + "wrong exception type") + else: + raise AssertionError("DID NOT RAISE") + return True + if hasattr(ll_function, 'convert_result'): res = ll_function.convert_result(res) @@ -288,6 +302,11 @@ main() return res + def timeshift_raises(self, ExcCls, ll_function, values, opt_consts=[], + *args, **kwds): + kwds['check_raises'] = ExcCls + return self.timeshift(ll_function, values, opt_consts, *args, **kwds) + def check_insns(self, expected=None, **counts): if expected is not None: assert self.insns == expected Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Thu Sep 7 16:49:33 2006 @@ -14,7 +14,6 @@ from pypy.translator.c.support import cdecl, CNameManager, ErrorValue from pypy.translator.c.support import log from pypy.translator.c.extfunc import do_the_getting -from pypy.translator.c.exceptiontransform import ExceptionTransformer from pypy import conftest # ____________________________________________________________ @@ -68,7 +67,7 @@ if translator is None or translator.rtyper is None: self.exctransformer = None else: - self.exctransformer = ExceptionTransformer(translator) + self.exctransformer = translator.getexceptiontransformer() self.gcpolicy = gcpolicy(self, thread_enabled) if translator is not None: self.gctransformer = gcpolicy.transformerclass(translator) Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Thu Sep 7 16:49:33 2006 @@ -31,6 +31,7 @@ raise TypeError("unexpected keyword argument") self.annotator = None self.rtyper = None + self.exceptiontransformer = None self.graphs = [] # [graph] self.callgraph = {} # {opaque_tag: (caller-graph, callee-graph)} self._prebuilt_graphs = {} # only used by the pygame viewer @@ -84,6 +85,15 @@ type_system = type_system) return self.rtyper + def getexceptiontransformer(self): + if self.rtyper is None: + raise ValueError("no rtyper") + if self.exceptiontransformer is not None: + return self.exceptiontransformer + from pypy.translator.c.exceptiontransform import ExceptionTransformer + self.exceptiontransformer = ExceptionTransformer(self) + return self.exceptiontransformer + def checkgraphs(self): for graph in self.graphs: checkgraph(graph) From pedronis at codespeak.net Thu Sep 7 17:46:08 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 7 Sep 2006 17:46:08 +0200 (CEST) Subject: [pypy-svn] r32059 - pypy/dist/pypy/jit/timeshifter Message-ID: <20060907154608.CCED010077@code0.codespeak.net> Author: pedronis Date: Thu Sep 7 17:46:06 2006 New Revision: 32059 Modified: pypy/dist/pypy/jit/timeshifter/vlist.py Log: (arigo, pedronis) some more virtual list operations implemented (test pending). Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Thu Sep 7 17:46:06 2006 @@ -137,12 +137,44 @@ return oopspecdesc.typedesc.factory(length, itembox) return oopspecdesc.residual_call(jitstate, [lengthbox, itembox]) +def oop_list_len(jitstate, oopspecdesc, selfbox): + if isinstance(selfbox.content, VirtualList): + return rvalue.ll_fromvalue(jitstate, len(selfbox.content.item_boxes)) + else: + return oopspecdesc.residual_call(jitstate, [selfbox]) + def oop_list_append(jitstate, oopspecdesc, selfbox, itembox): if isinstance(selfbox.content, VirtualList): selfbox.content.item_boxes.append(itembox) else: oopspecdesc.residual_call(jitstate, [selfbox, itembox]) +def oop_list_insert(jitstate, oopspecdesc, selfbox, indexbox, itembox): + if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): + index = rvalue.ll_getvalue(indexbox, lltype.Signed) + selfbox.content.item_boxes[index].insert(index, itembox) + else: + oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) + +def oop_list_pop(jitstate, oopspecdesc, selfbox, indexbox=None): + if indexbox is None: + if isinstance(selfbox.content, VirtualList): + try: + return selfbox.content.item_boxes.pop() + except IndexError: + return oopspecdesc.residual_exception(jitstate, IndexError) + else: + return oopspecdesc.residual_call(jitstate, [selfbox]) + + if (isinstance(selfbox.content, VirtualList) and + indexbox.is_constant()): + index = rvalue.ll_getvalue(indexbox, lltype.Signed) + try: + return selfbox.content.item_boxes.pop(index) + except IndexError: + return oopspecdesc.residual_exception(jitstate, IndexError) + return oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) + def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) From cfbolz at codespeak.net Thu Sep 7 18:05:26 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 18:05:26 +0200 (CEST) Subject: [pypy-svn] r32060 - pypy/branch/config-in-more-places/pypy/config/test Message-ID: <20060907160526.2E63B10077@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 18:05:24 2006 New Revision: 32060 Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py Log: make test actually check something Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_config.py Thu Sep 7 18:05:24 2006 @@ -208,9 +208,10 @@ descr = make_description() config = Config(descr) - assert config.getpaths(), ['gc.name', 'gc.dummy', 'gc.float', 'bool', - 'objspace', 'wantref', 'int'] - assert config.gc.getpaths(), ['name', 'dummy', 'float'] + assert set(config.getpaths()) == set( + ['gc.name', 'gc.dummy', 'gc.float', 'bool', + 'objspace', 'wantref', 'int']) + assert set(config.gc.getpaths()) == set(['name', 'dummy', 'float']) def test_none(): dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None) From cfbolz at codespeak.net Thu Sep 7 18:15:03 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 18:15:03 +0200 (CEST) Subject: [pypy-svn] r32061 - in pypy/branch/config-in-more-places/pypy/config: . test Message-ID: <20060907161503.49D6F10077@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 18:15:02 2006 New Revision: 32061 Modified: pypy/branch/config-in-more-places/pypy/config/config.py pypy/branch/config-in-more-places/pypy/config/test/test_config.py Log: * have the paths returned by getpaths be in the right order * make it possible to include groups Modified: pypy/branch/config-in-more-places/pypy/config/config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/config.py Thu Sep 7 18:15:02 2006 @@ -87,7 +87,7 @@ result += substr return result - def getpaths(self, currpath=None): + def getpaths(self, include_groups=False, currpath=None): """returns a list of all paths in self, recursively currpath should not be provided (helps with recursion) @@ -95,12 +95,16 @@ if currpath is None: currpath = [] paths = [] - for attr, value in self.__dict__.iteritems(): + for option in self._descr._children: + attr = option._name if attr.startswith('_'): continue + value = getattr(self, attr) if isinstance(value, Config): + if include_groups: + paths.append('.'.join(currpath + [attr])) currpath.append(attr) - paths += value.getpaths(currpath) + paths += value.getpaths(currpath=currpath) currpath.pop() else: paths.append('.'.join(currpath + [attr])) @@ -263,12 +267,11 @@ callback=_callback, *argnames) -def to_optparse(config, useoptions, parser=None): +def to_optparse(config, parser=None): if parser is None: parser = optparse.OptionParser() for path in useoptions: - if path.endswith("*"): - assert path.endswith("*") + if path.endswith(".*"): path = path[:-2] subconf, name = config._get_by_path(path) children = [ Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_config.py Thu Sep 7 18:15:02 2006 @@ -208,10 +208,12 @@ descr = make_description() config = Config(descr) - assert set(config.getpaths()) == set( - ['gc.name', 'gc.dummy', 'gc.float', 'bool', - 'objspace', 'wantref', 'int']) - assert set(config.gc.getpaths()) == set(['name', 'dummy', 'float']) + assert config.getpaths() == ['gc.name', 'gc.dummy', 'gc.float', 'bool', + 'objspace', 'wantref', 'int'] + assert config.gc.getpaths() == ['name', 'dummy', 'float'] + assert config.getpaths(include_groups=True) == [ + 'gc', 'gc.name', 'gc.dummy', 'gc.float', + 'bool', 'objspace', 'wantref', 'int'] def test_none(): dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None) From cfbolz at codespeak.net Thu Sep 7 18:34:28 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 18:34:28 +0200 (CEST) Subject: [pypy-svn] r32062 - in pypy/branch/config-in-more-places/pypy/config: . test Message-ID: <20060907163428.872121007A@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 18:34:26 2006 New Revision: 32062 Modified: pypy/branch/config-in-more-places/pypy/config/config.py pypy/branch/config-in-more-places/pypy/config/test/test_config.py Log: if no paths are specified, all options are created Modified: pypy/branch/config-in-more-places/pypy/config/config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/config.py Thu Sep 7 18:34:26 2006 @@ -104,7 +104,8 @@ if include_groups: paths.append('.'.join(currpath + [attr])) currpath.append(attr) - paths += value.getpaths(currpath=currpath) + paths += value.getpaths(include_groups=include_groups, + currpath=currpath) currpath.pop() else: paths.append('.'.join(currpath + [attr])) @@ -267,9 +268,11 @@ callback=_callback, *argnames) -def to_optparse(config, parser=None): +def to_optparse(config, useoptions=None, parser=None): if parser is None: parser = optparse.OptionParser() + if useoptions is None: + useoptions = config.getpaths(include_groups=True) for path in useoptions: if path.endswith(".*"): path = path[:-2] @@ -287,6 +290,10 @@ continue else: chunks = option.cmdline.split(' ') - option.add_optparse_option(chunks, parser, subconf) + try: + option.add_optparse_option(chunks, parser, subconf) + except ValueError: + # an option group that does not only contain bool values + pass return parser Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_config.py Thu Sep 7 18:34:26 2006 @@ -221,7 +221,7 @@ group = OptionDescription('group', [dummy1, dummy2]) config = Config(group) - parser = to_optparse(config, config.getpaths()) + parser = to_optparse(config) py.test.raises(SystemExit, "(options, args) = parser.parse_args(args=['--dummy1'])") From cfbolz at codespeak.net Thu Sep 7 18:46:09 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 18:46:09 +0200 (CEST) Subject: [pypy-svn] r32063 - pypy/branch/config-in-more-places/pypy/config Message-ID: <20060907164609.6E6D11007A@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 18:46:06 2006 New Revision: 32063 Modified: pypy/branch/config-in-more-places/pypy/config/config.py Log: use option groups to split the option help up. Modified: pypy/branch/config-in-more-places/pypy/config/config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/config.py Thu Sep 7 18:46:06 2006 @@ -269,6 +269,18 @@ def to_optparse(config, useoptions=None, parser=None): + grps = {} + def get_group(name): + steps = name.split('.') + if len(steps) < 2: + return parser + grpname = steps[0] + grp = grps.get(grpname, None) + if grp is None: + print "groupname", grpname + grp = grps[grpname] = parser.add_option_group(grpname) + return grp + if parser is None: parser = optparse.OptionParser() if useoptions is None: @@ -291,7 +303,8 @@ else: chunks = option.cmdline.split(' ') try: - option.add_optparse_option(chunks, parser, subconf) + grp = get_group(path) + option.add_optparse_option(chunks, grp, subconf) except ValueError: # an option group that does not only contain bool values pass From pedronis at codespeak.net Thu Sep 7 18:52:50 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 7 Sep 2006 18:52:50 +0200 (CEST) Subject: [pypy-svn] r32064 - in pypy/dist/pypy/jit: codegen/i386 codegen/llgraph timeshifter timeshifter/test Message-ID: <20060907165250.6BDA11007E@code0.codespeak.net> Author: pedronis Date: Thu Sep 7 18:52:45 2006 New Revision: 32064 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: implemented timeshifting of setarrayitem. Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Thu Sep 7 18:52:45 2006 @@ -182,6 +182,22 @@ self.mc.MOV(edx, gv_ptr.operand(self)) return self.returnvar(mem(edx, lengthoffset)) + def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): + # XXX! only works for GcArray(Signed) for now!! + lengthoffset, startoffset, itemoffset = arraytoken + self.mc.MOV(eax, gv_value.operand(self)) + self.mc.MOV(edx, gv_ptr.operand(self)) + if isinstance(gv_index, IntConst): + startoffset += itemoffset * gv_index.value + op = mem(edx, startoffset) + elif itemoffset in SIZE2SHIFT: + self.mc.MOV(ecx, gv_index.operand(self)) + op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset) + else: + self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) + op = memSIB(edx, ecx, 0, startoffset) + self.mc.MOV(op, eax) + def genop_malloc_fixedsize(self, size): # XXX boehm only, no atomic/non atomic distinction for now self.push(imm(size)) @@ -363,29 +379,10 @@ self.mc.MOVZX(eax, al) return self.returnvar(eax) - def op_setarrayitem(self, hello_world): - # XXX! only works for GcArray(Signed) for now!! - XXX-fixme - A = DUMMY_A - lengthoffset, startoffset, itemoffset = self.rgenop.arrayToken(A) - self.mc.MOV(eax, gv_value.operand(self)) - self.mc.MOV(edx, gv_ptr.operand(self)) - if isinstance(gv_index, IntConst): - startoffset += itemoffset * gv_index.value - op = mem(edx, startoffset) - elif itemoffset in SIZE2SHIFT: - self.mc.MOV(ecx, gv_index.operand(self)) - op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset) - else: - self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - op = memSIB(edx, ecx, 0, startoffset) - self.mc.MOV(op, eax) - op_ptr_nonzero = op_int_is_true op_ptr_iszero = op_bool_not # for now -DUMMY_A = lltype.GcArray(lltype.Signed) SIZE2SHIFT = {1: 0, 2: 1, 4: 2, Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Thu Sep 7 18:52:45 2006 @@ -81,6 +81,11 @@ return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv, gv_ITEMTYPE.v)) + def genop_setarrayitem(self, gv_ITEMTYPE, gv_ptr, gv_index, gv_value): + vars_gv = [gv_ptr.v, gv_index.v, gv_value.v] + return LLVar(llimpl.genop(self.b, 'setarrayitem', vars_gv, + gv_Void.v)) + def genop_getarraysize(self, gv_ITEMTYPE, gv_ptr): return LLVar(llimpl.genop(self.b, 'getarraysize', [gv_ptr.v], llimpl.constTYPE(lltype.Signed))) Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Thu Sep 7 18:52:45 2006 @@ -126,6 +126,16 @@ return fielddesc.redboxcls(fielddesc.kind, genvar) +def ll_gensetarrayitem(jitstate, fielddesc, destbox, indexbox, valuebox): + genvar = jitstate.curbuilder.genop_setarrayitem( + fielddesc.arraytoken, + destbox.getgenvar(jitstate.curbuilder), + indexbox.getgenvar(jitstate.curbuilder), + valuebox.getgenvar(jitstate.curbuilder) + ) + + return fielddesc.redboxcls(fielddesc.kind, genvar) + def ll_gengetarraysize(jitstate, fielddesc, argbox): if argbox.is_constant(): array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE) Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 7 18:52:45 2006 @@ -105,6 +105,20 @@ def translate_op_hint(self, hop): # don't try to generate hint operations, just discard them + hints = hop.args_v[-1].value + if hints.get('forget', False): + T = originalconcretetype(hop.args_s[0]) + v_redbox = hop.inputarg(self.getredrepr(T), arg=0) + assert isinstance(hop.r_result, GreenRepr) + ts = self.timeshifter + c_T = hop.inputconst(lltype.Void, T) + s_T = ts.rtyper.annotator.bookkeeper.immutablevalue(T) + s_res = annmodel.lltype_to_annotation(T) + return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue, + [ts.s_RedBox, s_T], + [v_redbox, c_T], + s_res) + return hop.inputarg(hop.r_result, arg=0) def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc @@ -231,6 +245,22 @@ [v_jitstate, c_fielddesc, v_destbox, v_valuebox], annmodel.s_None) + def translate_op_setarrayitem(self, hop): + PTRTYPE = originalconcretetype(hop.args_s[0]) + VALUETYPE = PTRTYPE.TO.OF + ts = self.timeshifter + v_argbox, v_index, v_valuebox= hop.inputargs(self.getredrepr(PTRTYPE), + self.getredrepr(lltype.Signed), + self.getredrepr(VALUETYPE)) + fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE) + c_fielddesc = inputconst(lltype.Void, fielddesc) + s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(rtimeshift.ll_gensetarrayitem, + [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox, ts.s_RedBox], + [v_jitstate, c_fielddesc, v_argbox, v_index , v_valuebox ], + ts.s_RedBox) + def translate_op_getsubstruct(self, hop): ##if isinstance(hop.args_r[0], BlueRepr): ## return hop.args_r[0].timeshift_getsubstruct(hop) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 7 18:52:45 2006 @@ -541,6 +541,8 @@ assert res == 24 self.check_insns({}) + + def test_simple_struct_malloc(self): py.test.skip("blue containers: to be reimplemented") S = lltype.GcStruct('helloworld', ('hello', lltype.Signed), @@ -696,6 +698,33 @@ assert res == 42 self.check_insns({}) + + def test_setarrayitem(self): + A = lltype.GcArray(lltype.Signed) + a = lltype.malloc(A, 2, immortal=True) + def ll_function(): + a[0] = 1 + a[1] = 2 + return a[0]+a[1] + + res = self.timeshift(ll_function, [], [], policy=P_NOVIRTUAL) + assert res == 3 + +## def test_red_array(self): +## A = lltype.GcArray(lltype.Signed) +## def ll_function(x, y, n): +## a = lltype.malloc(A, 2) +## a[0] = x +## a[1] = y +## return a[n] + +## res = self.timeshift(ll_function, [42, -42, 0], [], policy=P_NOVIRTUAL) +## assert res == 42 + +## res = self.timeshift(ll_function, [42, -42, 1], [], policy=P_NOVIRTUAL) +## assert res == -42 + + def test_red_propagate(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) def ll_function(n, k): From arigo at codespeak.net Thu Sep 7 18:54:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 18:54:02 +0200 (CEST) Subject: [pypy-svn] r32065 - pypy/dist/pypy/rpython Message-ID: <20060907165402.1DF701007E@code0.codespeak.net> Author: arigo Date: Thu Sep 7 18:54:01 2006 New Revision: 32065 Modified: pypy/dist/pypy/rpython/rlist.py Log: Missing import. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Sep 7 18:54:01 2006 @@ -1,6 +1,7 @@ from pypy.annotation.pairtype import pairtype, pair from pypy.objspace.flow.model import Constant from pypy.annotation import model as annmodel +from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IteratorRepr, IntegerRepr, inputconst from pypy.rpython.rslice import AbstractSliceRepr from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool From arigo at codespeak.net Thu Sep 7 19:01:24 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 19:01:24 +0200 (CEST) Subject: [pypy-svn] r32066 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060907170124.5AFC210083@code0.codespeak.net> Author: arigo Date: Thu Sep 7 19:01:20 2006 New Revision: 32066 Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py pypy/dist/pypy/jit/timeshifter/vlist.py Log: Implemented all vlist operations that have an oopspec in rlist. Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py Thu Sep 7 19:01:20 2006 @@ -74,3 +74,32 @@ assert res == 12 res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC) assert res == 0 + + def test_oop_vlist(self): + def ll_function(): + lst = [3, 5] + five = lst.pop() # [3] + lst.append(len(lst)) # [3, 1] + lst2 = list(lst) + three = lst.pop(0) # [1] + lst.insert(0, 8) # [8, 1] + lst.insert(2, 7) # [8, 1, 7] + lst.append(not lst) # [8, 1, 7, 0] + lst.reverse() # [0, 7, 1, 8] + lst3 = lst2 + lst # [3, 1, 0, 7, 1, 8] + del lst3[1] # [3, 0, 7, 1, 8] + seven = lst3.pop(2) # [3, 0, 1, 8] + lst3[0] = 9 # [9, 0, 1, 8] + nine = lst3.pop(-4) # [0, 1, 8] + return (len(lst3) * 10000000 + + lst3[0] * 1000000 + + lst3[1] * 100000 + + lst3[-1] * 10000 + + five * 1000 + + three * 100 + + seven * 10 + + nine * 1) + assert ll_function() == 30185379 + res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC) + assert res == 30185379 + self.check_insns({}) Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Thu Sep 7 19:01:20 2006 @@ -133,16 +133,29 @@ def oop_newlist(jitstate, oopspecdesc, lengthbox, itembox=None): if lengthbox.is_constant(): length = rvalue.ll_getvalue(lengthbox, lltype.Signed) - if length == 0 or itembox is not None: - return oopspecdesc.typedesc.factory(length, itembox) + return oopspecdesc.typedesc.factory(length, itembox) return oopspecdesc.residual_call(jitstate, [lengthbox, itembox]) +def oop_list_copy(jitstate, oopspecdesc, selfbox): + if isinstance(selfbox.content, VirtualList): + copybox = oopspecdesc.typedesc.factory(0, None) + copybox.content.item_boxes.extend(selfbox.content.item_boxes) + return copybox + else: + return oopspecdesc.residual_call(jitstate, [selfbox]) + def oop_list_len(jitstate, oopspecdesc, selfbox): if isinstance(selfbox.content, VirtualList): return rvalue.ll_fromvalue(jitstate, len(selfbox.content.item_boxes)) else: return oopspecdesc.residual_call(jitstate, [selfbox]) +def oop_list_nonzero(jitstate, oopspecdesc, selfbox): + if isinstance(selfbox.content, VirtualList): + return rvalue.ll_fromvalue(jitstate, bool(selfbox.content.item_boxes)) + else: + return oopspecdesc.residual_call(jitstate, [selfbox]) + def oop_list_append(jitstate, oopspecdesc, selfbox, itembox): if isinstance(selfbox.content, VirtualList): selfbox.content.item_boxes.append(itembox) @@ -152,10 +165,23 @@ def oop_list_insert(jitstate, oopspecdesc, selfbox, indexbox, itembox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) - selfbox.content.item_boxes[index].insert(index, itembox) + # XXX what if the assert fails? + assert 0 <= index <= len(selfbox.content.item_boxes) + selfbox.content.item_boxes.insert(index, itembox) else: oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) +def oop_list_concat(jitstate, oopspecdesc, selfbox, otherbox): + if isinstance(selfbox.content, VirtualList): + assert isinstance(otherbox, rvalue.PtrRedBox) + if (otherbox.content is not None and + isinstance(otherbox.content, VirtualList)): + newbox = oopspecdesc.typedesc.factory(0, None) + newbox.content.item_boxes.extend(selfbox.content.item_boxes) + newbox.content.item_boxes.extend(otherbox.content.item_boxes) + return newbox + return oopspecdesc.residual_call(jitstate, [selfbox, otherbox]) + def oop_list_pop(jitstate, oopspecdesc, selfbox, indexbox=None): if indexbox is None: if isinstance(selfbox.content, VirtualList): @@ -175,6 +201,12 @@ return oopspecdesc.residual_exception(jitstate, IndexError) return oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) +def oop_list_reverse(jitstate, oopspecdesc, selfbox): + if isinstance(selfbox.content, VirtualList): + selfbox.content.item_boxes.reverse() + else: + oopspecdesc.residual_call(jitstate, [selfbox]) + def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox): if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) @@ -194,3 +226,13 @@ oopspecdesc.residual_exception(jitstate, IndexError) else: oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) + +def oop_list_delitem(jitstate, oopspecdesc, selfbox, indexbox): + if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): + index = rvalue.ll_getvalue(indexbox, lltype.Signed) + try: + del selfbox.content.item_boxes[index] + except IndexError: + oopspecdesc.residual_exception(jitstate, IndexError) + else: + oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) From mwh at codespeak.net Thu Sep 7 19:20:40 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Sep 2006 19:20:40 +0200 (CEST) Subject: [pypy-svn] r32067 - in pypy/branch/more-gckinds/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test translator/c Message-ID: <20060907172040.E39F810072@code0.codespeak.net> Author: mwh Date: Thu Sep 7 19:20:38 2006 New Revision: 32067 Modified: pypy/branch/more-gckinds/pypy/annotation/model.py pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Log: push lltype.py in one direction a fair bit. breaks lots and lots of tests, but i want to stop going in this direction for now... Modified: pypy/branch/more-gckinds/pypy/annotation/model.py ============================================================================== --- pypy/branch/more-gckinds/pypy/annotation/model.py (original) +++ pypy/branch/more-gckinds/pypy/annotation/model.py Thu Sep 7 19:20:38 2006 @@ -515,6 +515,13 @@ def can_be_none(self): return False +class SomeInteriorPtr(SomeObject): + immutable = True + def __init__(self, ll_parentptrtype, field): + assert isinstance(ll_ptrtype, lltype.Ptr) + self.ll_parentptrtype = ll_parentptrtype + self.field = field + class SomeLLADTMeth(SomeObject): immutable = True def __init__(self, ll_ptrtype, func): Modified: pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py Thu Sep 7 19:20:38 2006 @@ -178,7 +178,7 @@ return Constant(p, lltype.typeOf(p)) def graph2delayed(self, graph): - FUNCTYPE = lltype.FuncForwardReference() + FUNCTYPE = lltype.ForwardReference() # obscure hack: embed the name of the function in the string, so # that the genc database can get it even before the delayedptr # is really computed Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Thu Sep 7 19:20:38 2006 @@ -168,13 +168,14 @@ class Struct(ContainerType): - _gckind = 'raw' + _gckind = 'prebuilt' def __init__(self, name, *fields, **kwds): self._name = self.__name__ = name flds = {} names = [] self._arrayfld = None + firstfield = True for name, typ in fields: if name.startswith('_'): raise NameError, ("%s: field name %r should not start with " @@ -183,12 +184,19 @@ if name in flds: raise TypeError("%s: repeated field name" % self._name) flds[name] = typ - if isinstance(typ, ContainerType) and typ._gckind != 'raw': - if name == fields[0][0] and typ._gckind == self._gckind: + if isinstance(typ, ContainerType): + if firstfield and typ._gckind == self._gckind: pass # can inline a XxContainer as 1st field of XxStruct + elif self._gckind == 'prebuilt' and typ._gckind == 'prebuilt': + pass + elif typ._gckind == 'raw': + 1/0 + elif typ._gckind == 'gcinterior' and self._gckind in ('gcinterior', 'gc'): + pass else: raise TypeError("%s: cannot inline %s container %r" % ( self._name, typ._gckind, typ)) + firstfield = False # look if we have an inlined variable-sized array as the last field if fields: @@ -277,6 +285,12 @@ n = 1 return _struct(self, n, initialization='example') +class EmbeddedStruct(Struct): + _gckind = 'gcinterior' + +class RawStruct(Struct): + _gckind = 'raw' + class RttiStruct(Struct): _runtime_type_info = None @@ -316,12 +330,13 @@ raise TypeError("a PyStruct must have another PyStruct or " "PyObject as first field") -STRUCT_BY_FLAVOR = {'raw': Struct, +STRUCT_BY_FLAVOR = {'prebuilt': Struct, + 'gcinterior': EmbeddedStruct, 'gc': GcStruct, 'cpy': PyStruct} class Array(ContainerType): - _gckind = 'raw' + _gckind = 'prebuilt' __name__ = 'array' _anonym_struct = False @@ -329,11 +344,16 @@ if len(fields) == 1 and isinstance(fields[0], LowLevelType): self.OF = fields[0] else: - self.OF = Struct("", *fields) + self.OF = EmbeddedStruct("", *fields) self._anonym_struct = True - if isinstance(self.OF, ContainerType) and self.OF._gckind != 'raw': - raise TypeError("cannot have a %s container as array item type" - % (self.OF._gckind,)) + if isinstance(self.OF, ContainerType): + if self._gckind in ('gcinterior', 'gc') and self.OF._gckind == 'gcinterior': + pass + elif self._gckind == 'prebuilt' and self.OF._gckind == 'prebuilt': + pass + else: + raise TypeError("cannot have a %s container as array item type" + % (self.OF._gckind,)) self.OF._inline_is_varsize(False) self._install_extras(**kwds) @@ -373,6 +393,9 @@ def _container_example(self): return _array(self, 1, initialization='example') +class EmbeddedArray(Array): + _gckind = 'gcinterior' + class GcArray(Array): _gckind = 'gc' def _inline_is_varsize(self, last): @@ -389,9 +412,14 @@ **kwds) self.OF = OF self.length = length - if isinstance(self.OF, ContainerType) and self.OF._gckind != 'raw': - raise TypeError("cannot have a %s container as array item type" - % (self.OF._gckind,)) + if isinstance(self.OF, ContainerType): + if self._gckind in ('gcinterior', 'gc') and self.OF._gckind == 'gcinterior': + pass + elif self._gckind == 'prebuilt' and self.OF._gckind == 'prebuilt': + pass + else: + raise TypeError("cannot have a %s container as array item type" + % (self.OF._gckind,)) self.OF._inline_is_varsize(False) def _str_fields(self): @@ -409,6 +437,9 @@ self.OF._short_name(),) _short_name = saferecursive(_short_name, '...') +class EmbeddedFixedSizeArray(FixedSizeArray): + _gckind = 'gcinterior' + class FuncType(ContainerType): _gckind = 'prebuilt' @@ -445,7 +476,8 @@ class OpaqueType(ContainerType): - _gckind = 'raw' + _gckind = 'prebuilt' # XXX ? + _gckind = 'gcinterior' # XXX ? def __init__(self, tag): self.tag = tag @@ -492,7 +524,7 @@ PyObject = PyObjectType() class ForwardReference(ContainerType): - _gckind = 'raw' + _gckind = 'prebuilt' def become(self, realcontainertype): if not isinstance(realcontainertype, ContainerType): raise TypeError("ForwardReference can only be to a container, " @@ -512,12 +544,13 @@ class PyForwardReference(ForwardReference): _gckind = 'cpy' -class FuncForwardReference(ForwardReference): - _gckind = 'prebuilt' +class EmbeddedForwardReference(ForwardReference): + _gckind = 'gcinterior' -FORWARDREF_BY_FLAVOR = {'raw': ForwardReference, +FORWARDREF_BY_FLAVOR = {'prebuilt': ForwardReference, 'gc': GcForwardReference, - 'cpy': PyForwardReference} + 'cpy': PyForwardReference, + 'gcinterior': EmbeddedForwardReference} class Primitive(LowLevelType): @@ -593,7 +626,7 @@ def _needsgc(self): # XXX deprecated interface - return self.TO._gckind != 'raw' + return self.TO._gckind not in ('gcinterior', 'prebuilt') def __str__(self): return '* %s' % (self.TO, ) @@ -602,7 +635,7 @@ return 'Ptr %s' % (self.TO._short_name(), ) def _is_atomic(self): - return self.TO._gckind == 'raw' + return not self.TO._gckind not in ('gcinterior', 'prebuilt') def _defl(self, parent=None, parentindex=None): return _ptr(self, None) @@ -943,8 +976,7 @@ def _setobj(self, pointing_to, solid=False): if pointing_to is None: obj0 = None - elif (solid or self._T._gckind != 'raw' or - isinstance(self._T, FuncType)): + elif (solid or self._T._gckind != 'gcinterior'): obj0 = pointing_to else: self._set_weak(True) @@ -1589,9 +1621,7 @@ solid = immortal or not flavor.startswith('gc') # immortal or non-gc case return _ptr(Ptr(T), o, solid) -def free(p, flavor): - if flavor.startswith('gc'): - raise TypeError, "gc flavor free" +def free(p): T = typeOf(p) if not isinstance(T, Ptr) or p._togckind() != 'raw': raise TypeError, "free(): only for pointers to non-gc containers" Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py Thu Sep 7 19:20:38 2006 @@ -10,7 +10,7 @@ AbstractLLHelpers from pypy.rpython.lltypesystem import ll_str from pypy.rpython.lltypesystem.lltype import \ - GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \ + GcStruct, Signed, EmbeddedArray, Char, UniChar, Ptr, malloc, \ Bool, Void, GcArray, nullptr, pyobjectptr @@ -24,8 +24,8 @@ # } STR = GcStruct('rpy_string', ('hash', Signed), - ('chars', Array(Char, hints={'immutable': True, - 'isrpystring': True}))) + ('chars', EmbeddedArray(Char, hints={'immutable': True, + 'isrpystring': True}))) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py Thu Sep 7 19:20:38 2006 @@ -82,14 +82,14 @@ assert iwitem(l, 1).v == 3 # not allowed - S = Struct("s", ('v', Signed)) + S = EmbeddedStruct("s", ('v', Signed)) List_typ, iwnewlistzzz, iwappendzzz, iwitemzzz = define_list(S) # works but l = iwnewlistzzz() S1 = GcStruct("strange", ('s', S)) py.test.raises(TypeError, "iwappendzzz(l, malloc(S1).s)") def test_varsizestruct(): - S1 = GcStruct("s1", ('a', Signed), ('rest', Array(('v', Signed)))) + S1 = GcStruct("s1", ('a', Signed), ('rest', EmbeddedArray(('v', Signed)))) py.test.raises(TypeError, "malloc(S1)") s1 = malloc(S1, 4) s1.a = 0 @@ -114,8 +114,8 @@ py.test.raises(TypeError, "Struct('invalid', ('x', S1))") def test_substructure_ptr(): - S3 = Struct("s3", ('a', Signed)) - S2 = Struct("s2", ('s3', S3)) + S3 = EmbeddedStruct("s3", ('a', Signed)) + S2 = EmbeddedStruct("s2", ('s3', S3)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1) assert isweak(p1.sub1, S2) @@ -126,7 +126,7 @@ def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) - S2 = Struct("s3", ('a', Signed)) + S2 = EmbeddedStruct("s3", ('a', Signed)) S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2)) p1 = malloc(S0) assert typeOf(p1.sub1) == Ptr(S1) @@ -202,8 +202,8 @@ py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") def test_best_effort_gced_parent_detection(): - S2 = Struct("s2", ('a', Signed)) - S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) + S2 = EmbeddedStruct("s2", ('a', Signed)) + S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', EmbeddedArray(('e', Signed)))) p1 = malloc(S1, 1) p2 = p1.sub2 p3 = p1.tail @@ -229,7 +229,7 @@ def test_examples(): A1 = GcArray(('v', Signed)) S = GcStruct("s", ('v', Signed)) - St = GcStruct("st", ('v', Signed),('trail', Array(('v', Signed)))) + St = GcStruct("st", ('v', Signed),('trail', EmbeddedArray(('v', Signed)))) PA1 = Ptr(A1) PS = Ptr(S) @@ -263,6 +263,7 @@ assert Void not in F._trueargs() def test_inconsistent_gc_containers(): + # XXX write more here! A = GcArray(('y', Signed)) S = GcStruct('b', ('y', Signed)) py.test.raises(TypeError, "Struct('a', ('x', S))") @@ -333,12 +334,12 @@ S = GcStruct('s', ('x', Signed)) py.test.raises(TypeError, "Array(S)") py.test.raises(TypeError, "Array(As)") - S = Struct('s', ('x', Signed)) + S = EmbeddedStruct('s', ('x', Signed)) A = GcArray(S) a = malloc(A, 2) s = S._container_example() # should not happen anyway py.test.raises(TypeError, "a[0] = s") - S = Struct('s', ('last', Array(S))) + S = EmbeddedStruct('s', ('last', EmbeddedArray(S))) py.test.raises(TypeError, "Array(S)") def test_immortal_parent(): @@ -422,14 +423,13 @@ assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) def test_flavor_malloc(): - S = Struct('s', ('x', Signed)) - py.test.raises(TypeError, malloc, S) - p = malloc(S, flavor="raw") + S = RawStruct('s', ('x', Signed)) + p = malloc(S, flavor='raw') assert typeOf(p).TO == S assert not isweak(p, S) - free(p, flavor="raw") + free(p) T = GcStruct('T', ('y', Signed)) - p = malloc(T, flavor="gc") + p = malloc(T) assert typeOf(p).TO == T assert not isweak(p, T) Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/funcgen.py (original) +++ pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Thu Sep 7 19:20:38 2006 @@ -10,7 +10,7 @@ from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray -from pypy.rpython.lltypesystem.lltype import FuncForwardReference +from pypy.rpython.lltypesystem.lltype import ForwardReference from pypy.rpython.lltypesystem.llmemory import Address, WeakGcAddress from pypy.translator.backendopt.ssa import SSI_to_SSA @@ -58,7 +58,7 @@ T = getattr(v, 'concretetype', PyObjPtr) # obscure: skip forward references and hope for the best # (needed for delayed function pointers) - if isinstance(T, Ptr) and T.TO.__class__ == FuncForwardReference: + if isinstance(T, Ptr) and T.TO.__class__ == ForwardReference: continue db.gettype(T) # force the type to be considered by the database From mwh at codespeak.net Thu Sep 7 19:21:15 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Sep 2006 19:21:15 +0200 (CEST) Subject: [pypy-svn] r32068 - in pypy/branch/more-gckinds/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test translator/c Message-ID: <20060907172115.07B0B10072@code0.codespeak.net> Author: mwh Date: Thu Sep 7 19:21:14 2006 New Revision: 32068 Modified: pypy/branch/more-gckinds/pypy/annotation/model.py pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Log: revert 32067 again -- time to go in a different direction :-) Modified: pypy/branch/more-gckinds/pypy/annotation/model.py ============================================================================== --- pypy/branch/more-gckinds/pypy/annotation/model.py (original) +++ pypy/branch/more-gckinds/pypy/annotation/model.py Thu Sep 7 19:21:14 2006 @@ -515,13 +515,6 @@ def can_be_none(self): return False -class SomeInteriorPtr(SomeObject): - immutable = True - def __init__(self, ll_parentptrtype, field): - assert isinstance(ll_ptrtype, lltype.Ptr) - self.ll_parentptrtype = ll_parentptrtype - self.field = field - class SomeLLADTMeth(SomeObject): immutable = True def __init__(self, ll_ptrtype, func): Modified: pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py Thu Sep 7 19:21:14 2006 @@ -178,7 +178,7 @@ return Constant(p, lltype.typeOf(p)) def graph2delayed(self, graph): - FUNCTYPE = lltype.ForwardReference() + FUNCTYPE = lltype.FuncForwardReference() # obscure hack: embed the name of the function in the string, so # that the genc database can get it even before the delayedptr # is really computed Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Thu Sep 7 19:21:14 2006 @@ -168,14 +168,13 @@ class Struct(ContainerType): - _gckind = 'prebuilt' + _gckind = 'raw' def __init__(self, name, *fields, **kwds): self._name = self.__name__ = name flds = {} names = [] self._arrayfld = None - firstfield = True for name, typ in fields: if name.startswith('_'): raise NameError, ("%s: field name %r should not start with " @@ -184,19 +183,12 @@ if name in flds: raise TypeError("%s: repeated field name" % self._name) flds[name] = typ - if isinstance(typ, ContainerType): - if firstfield and typ._gckind == self._gckind: + if isinstance(typ, ContainerType) and typ._gckind != 'raw': + if name == fields[0][0] and typ._gckind == self._gckind: pass # can inline a XxContainer as 1st field of XxStruct - elif self._gckind == 'prebuilt' and typ._gckind == 'prebuilt': - pass - elif typ._gckind == 'raw': - 1/0 - elif typ._gckind == 'gcinterior' and self._gckind in ('gcinterior', 'gc'): - pass else: raise TypeError("%s: cannot inline %s container %r" % ( self._name, typ._gckind, typ)) - firstfield = False # look if we have an inlined variable-sized array as the last field if fields: @@ -285,12 +277,6 @@ n = 1 return _struct(self, n, initialization='example') -class EmbeddedStruct(Struct): - _gckind = 'gcinterior' - -class RawStruct(Struct): - _gckind = 'raw' - class RttiStruct(Struct): _runtime_type_info = None @@ -330,13 +316,12 @@ raise TypeError("a PyStruct must have another PyStruct or " "PyObject as first field") -STRUCT_BY_FLAVOR = {'prebuilt': Struct, - 'gcinterior': EmbeddedStruct, +STRUCT_BY_FLAVOR = {'raw': Struct, 'gc': GcStruct, 'cpy': PyStruct} class Array(ContainerType): - _gckind = 'prebuilt' + _gckind = 'raw' __name__ = 'array' _anonym_struct = False @@ -344,16 +329,11 @@ if len(fields) == 1 and isinstance(fields[0], LowLevelType): self.OF = fields[0] else: - self.OF = EmbeddedStruct("", *fields) + self.OF = Struct("", *fields) self._anonym_struct = True - if isinstance(self.OF, ContainerType): - if self._gckind in ('gcinterior', 'gc') and self.OF._gckind == 'gcinterior': - pass - elif self._gckind == 'prebuilt' and self.OF._gckind == 'prebuilt': - pass - else: - raise TypeError("cannot have a %s container as array item type" - % (self.OF._gckind,)) + if isinstance(self.OF, ContainerType) and self.OF._gckind != 'raw': + raise TypeError("cannot have a %s container as array item type" + % (self.OF._gckind,)) self.OF._inline_is_varsize(False) self._install_extras(**kwds) @@ -393,9 +373,6 @@ def _container_example(self): return _array(self, 1, initialization='example') -class EmbeddedArray(Array): - _gckind = 'gcinterior' - class GcArray(Array): _gckind = 'gc' def _inline_is_varsize(self, last): @@ -412,14 +389,9 @@ **kwds) self.OF = OF self.length = length - if isinstance(self.OF, ContainerType): - if self._gckind in ('gcinterior', 'gc') and self.OF._gckind == 'gcinterior': - pass - elif self._gckind == 'prebuilt' and self.OF._gckind == 'prebuilt': - pass - else: - raise TypeError("cannot have a %s container as array item type" - % (self.OF._gckind,)) + if isinstance(self.OF, ContainerType) and self.OF._gckind != 'raw': + raise TypeError("cannot have a %s container as array item type" + % (self.OF._gckind,)) self.OF._inline_is_varsize(False) def _str_fields(self): @@ -437,9 +409,6 @@ self.OF._short_name(),) _short_name = saferecursive(_short_name, '...') -class EmbeddedFixedSizeArray(FixedSizeArray): - _gckind = 'gcinterior' - class FuncType(ContainerType): _gckind = 'prebuilt' @@ -476,8 +445,7 @@ class OpaqueType(ContainerType): - _gckind = 'prebuilt' # XXX ? - _gckind = 'gcinterior' # XXX ? + _gckind = 'raw' def __init__(self, tag): self.tag = tag @@ -524,7 +492,7 @@ PyObject = PyObjectType() class ForwardReference(ContainerType): - _gckind = 'prebuilt' + _gckind = 'raw' def become(self, realcontainertype): if not isinstance(realcontainertype, ContainerType): raise TypeError("ForwardReference can only be to a container, " @@ -544,13 +512,12 @@ class PyForwardReference(ForwardReference): _gckind = 'cpy' -class EmbeddedForwardReference(ForwardReference): - _gckind = 'gcinterior' +class FuncForwardReference(ForwardReference): + _gckind = 'prebuilt' -FORWARDREF_BY_FLAVOR = {'prebuilt': ForwardReference, +FORWARDREF_BY_FLAVOR = {'raw': ForwardReference, 'gc': GcForwardReference, - 'cpy': PyForwardReference, - 'gcinterior': EmbeddedForwardReference} + 'cpy': PyForwardReference} class Primitive(LowLevelType): @@ -626,7 +593,7 @@ def _needsgc(self): # XXX deprecated interface - return self.TO._gckind not in ('gcinterior', 'prebuilt') + return self.TO._gckind != 'raw' def __str__(self): return '* %s' % (self.TO, ) @@ -635,7 +602,7 @@ return 'Ptr %s' % (self.TO._short_name(), ) def _is_atomic(self): - return not self.TO._gckind not in ('gcinterior', 'prebuilt') + return self.TO._gckind == 'raw' def _defl(self, parent=None, parentindex=None): return _ptr(self, None) @@ -976,7 +943,8 @@ def _setobj(self, pointing_to, solid=False): if pointing_to is None: obj0 = None - elif (solid or self._T._gckind != 'gcinterior'): + elif (solid or self._T._gckind != 'raw' or + isinstance(self._T, FuncType)): obj0 = pointing_to else: self._set_weak(True) @@ -1621,7 +1589,9 @@ solid = immortal or not flavor.startswith('gc') # immortal or non-gc case return _ptr(Ptr(T), o, solid) -def free(p): +def free(p, flavor): + if flavor.startswith('gc'): + raise TypeError, "gc flavor free" T = typeOf(p) if not isinstance(T, Ptr) or p._togckind() != 'raw': raise TypeError, "free(): only for pointers to non-gc containers" Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py Thu Sep 7 19:21:14 2006 @@ -10,7 +10,7 @@ AbstractLLHelpers from pypy.rpython.lltypesystem import ll_str from pypy.rpython.lltypesystem.lltype import \ - GcStruct, Signed, EmbeddedArray, Char, UniChar, Ptr, malloc, \ + GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \ Bool, Void, GcArray, nullptr, pyobjectptr @@ -24,8 +24,8 @@ # } STR = GcStruct('rpy_string', ('hash', Signed), - ('chars', EmbeddedArray(Char, hints={'immutable': True, - 'isrpystring': True}))) + ('chars', Array(Char, hints={'immutable': True, + 'isrpystring': True}))) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py Thu Sep 7 19:21:14 2006 @@ -82,14 +82,14 @@ assert iwitem(l, 1).v == 3 # not allowed - S = EmbeddedStruct("s", ('v', Signed)) + S = Struct("s", ('v', Signed)) List_typ, iwnewlistzzz, iwappendzzz, iwitemzzz = define_list(S) # works but l = iwnewlistzzz() S1 = GcStruct("strange", ('s', S)) py.test.raises(TypeError, "iwappendzzz(l, malloc(S1).s)") def test_varsizestruct(): - S1 = GcStruct("s1", ('a', Signed), ('rest', EmbeddedArray(('v', Signed)))) + S1 = GcStruct("s1", ('a', Signed), ('rest', Array(('v', Signed)))) py.test.raises(TypeError, "malloc(S1)") s1 = malloc(S1, 4) s1.a = 0 @@ -114,8 +114,8 @@ py.test.raises(TypeError, "Struct('invalid', ('x', S1))") def test_substructure_ptr(): - S3 = EmbeddedStruct("s3", ('a', Signed)) - S2 = EmbeddedStruct("s2", ('s3', S3)) + S3 = Struct("s3", ('a', Signed)) + S2 = Struct("s2", ('s3', S3)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1) assert isweak(p1.sub1, S2) @@ -126,7 +126,7 @@ def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) - S2 = EmbeddedStruct("s3", ('a', Signed)) + S2 = Struct("s3", ('a', Signed)) S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2)) p1 = malloc(S0) assert typeOf(p1.sub1) == Ptr(S1) @@ -202,8 +202,8 @@ py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") def test_best_effort_gced_parent_detection(): - S2 = EmbeddedStruct("s2", ('a', Signed)) - S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', EmbeddedArray(('e', Signed)))) + S2 = Struct("s2", ('a', Signed)) + S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) p1 = malloc(S1, 1) p2 = p1.sub2 p3 = p1.tail @@ -229,7 +229,7 @@ def test_examples(): A1 = GcArray(('v', Signed)) S = GcStruct("s", ('v', Signed)) - St = GcStruct("st", ('v', Signed),('trail', EmbeddedArray(('v', Signed)))) + St = GcStruct("st", ('v', Signed),('trail', Array(('v', Signed)))) PA1 = Ptr(A1) PS = Ptr(S) @@ -263,7 +263,6 @@ assert Void not in F._trueargs() def test_inconsistent_gc_containers(): - # XXX write more here! A = GcArray(('y', Signed)) S = GcStruct('b', ('y', Signed)) py.test.raises(TypeError, "Struct('a', ('x', S))") @@ -334,12 +333,12 @@ S = GcStruct('s', ('x', Signed)) py.test.raises(TypeError, "Array(S)") py.test.raises(TypeError, "Array(As)") - S = EmbeddedStruct('s', ('x', Signed)) + S = Struct('s', ('x', Signed)) A = GcArray(S) a = malloc(A, 2) s = S._container_example() # should not happen anyway py.test.raises(TypeError, "a[0] = s") - S = EmbeddedStruct('s', ('last', EmbeddedArray(S))) + S = Struct('s', ('last', Array(S))) py.test.raises(TypeError, "Array(S)") def test_immortal_parent(): @@ -423,13 +422,14 @@ assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) def test_flavor_malloc(): - S = RawStruct('s', ('x', Signed)) - p = malloc(S, flavor='raw') + S = Struct('s', ('x', Signed)) + py.test.raises(TypeError, malloc, S) + p = malloc(S, flavor="raw") assert typeOf(p).TO == S assert not isweak(p, S) - free(p) + free(p, flavor="raw") T = GcStruct('T', ('y', Signed)) - p = malloc(T) + p = malloc(T, flavor="gc") assert typeOf(p).TO == T assert not isweak(p, T) Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/funcgen.py (original) +++ pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Thu Sep 7 19:21:14 2006 @@ -10,7 +10,7 @@ from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray -from pypy.rpython.lltypesystem.lltype import ForwardReference +from pypy.rpython.lltypesystem.lltype import FuncForwardReference from pypy.rpython.lltypesystem.llmemory import Address, WeakGcAddress from pypy.translator.backendopt.ssa import SSI_to_SSA @@ -58,7 +58,7 @@ T = getattr(v, 'concretetype', PyObjPtr) # obscure: skip forward references and hope for the best # (needed for delayed function pointers) - if isinstance(T, Ptr) and T.TO.__class__ == ForwardReference: + if isinstance(T, Ptr) and T.TO.__class__ == FuncForwardReference: continue db.gettype(T) # force the type to be considered by the database From arigo at codespeak.net Thu Sep 7 19:28:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 19:28:04 +0200 (CEST) Subject: [pypy-svn] r32069 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20060907172804.EA9541007D@code0.codespeak.net> Author: arigo Date: Thu Sep 7 19:28:03 2006 New Revision: 32069 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py Log: Add cast_bool_to_int. Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Thu Sep 7 19:28:03 2006 @@ -379,6 +379,12 @@ self.mc.MOVZX(eax, al) return self.returnvar(eax) + def op_cast_bool_to_int(self, gv_x): + self.mc.CMP(gv_x.operand(self), imm8(0)) + self.mc.SETNE(al) + self.mc.MOVZX(eax, al) + return self.returnvar(eax) + op_ptr_nonzero = op_int_is_true op_ptr_iszero = op_bool_not # for now From arigo at codespeak.net Thu Sep 7 19:28:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 19:28:23 +0200 (CEST) Subject: [pypy-svn] r32070 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20060907172823.A6D4110080@code0.codespeak.net> Author: arigo Date: Thu Sep 7 19:28:22 2006 New Revision: 32070 Added: pypy/dist/pypy/jit/codegen/i386/test/test_genc_exception.py (contents, props changed) Log: (pedronis, arigo) Forgot to check this test in. Added: pypy/dist/pypy/jit/codegen/i386/test/test_genc_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_exception.py Thu Sep 7 19:28:22 2006 @@ -0,0 +1,12 @@ +import py +from pypy.jit.timeshifter.test import test_exception +from pypy.jit.codegen.i386.test.test_genc_ts import I386TimeshiftingTestMixin + + +class TestException(I386TimeshiftingTestMixin, + test_exception.TestException): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_exception.py + + pass From cfbolz at codespeak.net Thu Sep 7 19:41:34 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 19:41:34 +0200 (CEST) Subject: [pypy-svn] r32071 - pypy/branch/config-in-more-places/pypy/config Message-ID: <20060907174134.534011005A@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 19:41:32 2006 New Revision: 32071 Modified: pypy/branch/config-in-more-places/pypy/config/config.py Log: use py.compat.optparse Modified: pypy/branch/config-in-more-places/pypy/config/config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/config.py Thu Sep 7 19:41:32 2006 @@ -1,5 +1,5 @@ -import optparse +from py.compat import optparse class Config(object): _frozen = False From cfbolz at codespeak.net Thu Sep 7 20:09:59 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Sep 2006 20:09:59 +0200 (CEST) Subject: [pypy-svn] r32072 - pypy/branch/config-in-more-places/pypy/translator/goal Message-ID: <20060907180959.CA7AC1007C@code0.codespeak.net> Author: cfbolz Date: Thu Sep 7 20:09:57 2006 New Revision: 32072 Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Log: use config machinery to produce optparse options Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Thu Sep 7 20:09:57 2006 @@ -1,6 +1,6 @@ -import os, sys +import py -from pypy.tool.option import make_config +import os, sys # as of revision 27081, multimethod.py uses the InstallerVersion1 by default # because it is much faster both to initialize and run on top of CPython. @@ -16,6 +16,9 @@ from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy +from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.config import Config, to_optparse + try: this_dir = os.path.dirname(__file__) @@ -70,22 +73,25 @@ take_options = True -def opt_parser(): - import py - defl = {'thread': False, 'usemodules': ''} - parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", - add_help_option=False) - parser.set_defaults(**defl) - parser.add_option("--thread", action="store_true", dest="thread", - help="enable threading") - parser.add_option("--usemodules", action="store", type="string", - dest="usemodules", help=("list of mixed modules to " - "include, comma-separated")) - return parser +#def opt_parser(): +# import py +# defl = {'thread': False, 'usemodules': ''} +# parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", +# add_help_option=False) +# parser.set_defaults(**defl) +# parser.add_option("--thread", action="store_true", dest="thread", +# help="enable threading") +# parser.add_option("--usemodules", action="store", type="string", +# dest="usemodules", help=("list of mixed modules to " +# "include, comma-separated")) +# return parser def print_help(): - opt_parser().print_help() - + config = Config(pypy_optiondescription) + opt_parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", + add_help_option=False) + to_optparse(config, parser=opt_parser) + opt_parser.print_help() def call_finish(space): space.finish() @@ -95,15 +101,19 @@ def target(driver, args): + global config, opt_parser driver.exe_name = 'pypy-%(backend)s' options = driver.options - tgt_options, _ = opt_parser().parse_args(args) - - config = make_config(tgt_options) + config = Config(pypy_optiondescription) + opt_parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", + add_help_option=False) + to_optparse(config, parser=parser) translate.log_options(tgt_options, "target PyPy options in effect") + opt_parser().parse_args(args) + # expose the following variables to ease debugging global space, entry_point @@ -118,14 +128,6 @@ # disable translation of the whole of classobjinterp.py StdObjSpace.setup_old_style_classes = lambda self: None - usemodules = [] - if tgt_options.usemodules: - for modname in tgt_options.usemodules.split(","): - setattr(config.objspace.usemodules, modname, True) - if tgt_options.thread: - config.objspace.usemodules.thread = True - if options.stackless: - config.objspace.usemodules._stackless = True config.objspace.nofaking = True config.objspace.compiler = "ast" config.translating = True From arigo at codespeak.net Thu Sep 7 20:23:27 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Sep 2006 20:23:27 +0200 (CEST) Subject: [pypy-svn] r32073 - pypy/dist/pypy/objspace/flow/test Message-ID: <20060907182327.4C3D710068@code0.codespeak.net> Author: arigo Date: Thu Sep 7 20:23:26 2006 New Revision: 32073 Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py Log: A flow space test that is known to crash on Python 2.5. Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Thu Sep 7 20:23:26 2006 @@ -701,6 +701,16 @@ from pypy import this_does_not_exist py.test.raises(ImportError, 'self.codetest(f)') + def test_mergeable(self): + def myfunc(x): + if x: + from pypy.interpreter.error import OperationError + s = 12 + else: + s = x.abc + return x[s] + graph = self.codetest(myfunc) + class TestFlowObjSpaceDelay(Base): def setup_class(cls): From fijal at codespeak.net Fri Sep 8 12:51:27 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 8 Sep 2006 12:51:27 +0200 (CEST) Subject: [pypy-svn] r32077 - in pypy/dist/pypy: bin translator/js translator/js/modules/test translator/js/test Message-ID: <20060908105127.82BA61006E@code0.codespeak.net> Author: fijal Date: Fri Sep 8 12:50:55 2006 New Revision: 32077 Modified: pypy/dist/pypy/bin/jscompile.py pypy/dist/pypy/translator/js/helper.py pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/js/modules/test/test_dom.py pypy/dist/pypy/translator/js/test/runtest.py pypy/dist/pypy/translator/js/test/test_class.py Log: Added command line options to jscompile, fixed some typos, improved exception handlers. Modified: pypy/dist/pypy/bin/jscompile.py ============================================================================== --- pypy/dist/pypy/bin/jscompile.py (original) +++ pypy/dist/pypy/bin/jscompile.py Fri Sep 8 12:50:55 2006 @@ -1,6 +1,9 @@ #!/usr/bin/env python """ RPython to javascript compiler Usage: jscompiler module_to_compile [list of functions to export] + +- or - +jscompiler --help to show list of options """ import autopath @@ -8,5 +11,30 @@ from pypy.translator.js.main import rpython2javascript_main +from pypy.tool import option +import optparse +make_option = optparse.make_option + +class Options(option.Options): + pass + +def get_options(): + options = [] + + options.append(make_option( + '--view', action='store_true', dest='view', + help='View flow graphs')) + + options.append(make_option( + '-o', '--output', action='store', type='string', dest='output', + default='output.js', help='File to save results (default output.js)')) + + return options + +def process_options(argv): + return option.process_options(get_options(), Options, argv) + + if __name__ == '__main__': - rpython2javascript_main(sys.argv[1:]) + argv = process_options(sys.argv[1:]) + rpython2javascript_main(argv, Options) Modified: pypy/dist/pypy/translator/js/helper.py ============================================================================== --- pypy/dist/pypy/translator/js/helper.py (original) +++ pypy/dist/pypy/translator/js/helper.py Fri Sep 8 12:50:55 2006 @@ -16,7 +16,7 @@ get_document().childNodes[0].childNodes[1].appendChild(debug_div) return debug_div -def show_traceback(tb): +def show_traceback(tb, exc): debug_div = get_document().getElementById("debug_div") if not debug_div: # create div here @@ -25,10 +25,14 @@ pre_div = get_document().createElement("pre") pre_div.style.color = "#FF0000" debug_div.appendChild(pre_div) + txt = get_document().createTextNode("") + pre_div.appendChild(txt) for tb_entry in tb[1:]: # list of tuples... fun_name, args, filename, lineno = tb_entry # some source maybe? or so? line1 = escape("%s %s" % (fun_name, args)) line2 = escape(" %s: %s\n" % (filename, lineno)) - pre_div.innerHTML += line1 + '\n' + line2 + txt.nodeValue += line1 + '\n' + line2 + + txt.nodeValue += str(exc) Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Fri Sep 8 12:50:55 2006 @@ -12,6 +12,7 @@ from pypy.annotation.policy import AnnotatorPolicy import optparse import py +from pypy.tool.option import Options class FunctionNotFound(Exception): pass @@ -32,7 +33,7 @@ return ",".join(func_data.func_code.co_varnames\ [:func_data.func_code.co_argcount]) -def rpython2javascript_main(argv): +def rpython2javascript_main(argv, opts): if len(argv) < 1: print "usage: module " import sys @@ -42,7 +43,10 @@ module_name = module_name[:-3] function_names = argv[1:] mod = __import__(module_name, None, None, ["Module"]) - return rpython2javascript(mod, function_names) + source = rpython2javascript(mod, function_names, opts=opts) + if opts.output != '': + open(opts.output, "w").write(source) + print "Written file %s" % opts.output # some strange function source source_ssf_base = """ @@ -65,9 +69,9 @@ traceback_handler.enter(NonConst("entrypoint"), NonConst("()"), NonConst(""), NonConst(0)) %(module_name)s.%(fun_name)s(%(arg_names)s) traceback_handler.leave(NonConst("entrypoint")) - except: + except Exception, e: new_tb = traceback_handler.tb[:] - show_traceback(new_tb) + show_traceback(new_tb, str(e)) """ function_base = "%(module)s.%(fun_name)s(%(args)s)" @@ -94,7 +98,7 @@ print retval return retval -def rpython2javascript(mod, function_names, use_debug=True): +def rpython2javascript(mod, function_names, use_debug=True, opts=Options): module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: function_names.append('main') @@ -115,6 +119,8 @@ try: driver.setup(some_strange_function_which_will_never_be_called, [], policy = JsPolicy()) driver.proceed(["compile_js"]) + if getattr(opts, 'view', False): + driver.translator.view() return driver.gen.tmpfile.open().read() # XXX: Add some possibility to write down selected file except Exception, e: Modified: pypy/dist/pypy/translator/js/modules/test/test_dom.py ============================================================================== --- pypy/dist/pypy/translator/js/modules/test/test_dom.py (original) +++ pypy/dist/pypy/translator/js/modules/test/test_dom.py Fri Sep 8 12:50:55 2006 @@ -37,6 +37,8 @@ movers = [Mover("anim_img"), Mover("anim_img2")] movers[1].x = 20 +xml = XMLHttpRequest() + def move_it(): movers[0].move_it() #movers[1].move_it() @@ -52,7 +54,8 @@ #document.getElementById("dupa").setInnerHTML("

Fire!

") #return document.getElementById("dupa") - fn = compile_function(f, [], html = 'html/test.html') + fn = compile_function(f, [], html = str(py.path.local(__file__).\ + dirpath('html').join('test.html'))) assert fn() == '[object HTMLHeadingElement]' def test_anim_f(self): @@ -71,13 +74,11 @@ fn = compile_function(anim_fun, [], html = 'html/anim.html') assert fn() == '3px' - xml = XMLHttpRequest() - def t_xml_fun(self): if xml.readyState == 4: alert('Wow!') - def test_xmlhttp(self): + def DONTtest_xmlhttp(self): """ Low level XMLHttpRequest test """ def xml_fun(): Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Fri Sep 8 12:50:55 2006 @@ -41,8 +41,6 @@ DebugTransformer(t).transform_all() t.buildrtyper(type_system="ootype").specialize() - #backend_optimizations(t, raisingop2direct_call_all=True, inline_threshold=0, mallocs=False) - #backend_optimizations(t) if view or option.view: t.view() #self.js = JS(t, [function, callback_function], stackless) @@ -59,8 +57,6 @@ return self.js.tmpfile.open().read() def _conv(self, v): - #if isinstance(v, str): - # return "{hash:0, chars:'%s'}" % v if isinstance(v, str): return repr(v) return str(v).lower() Modified: pypy/dist/pypy/translator/js/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_class.py (original) +++ pypy/dist/pypy/translator/js/test/test_class.py Fri Sep 8 12:50:55 2006 @@ -140,7 +140,7 @@ def test_instance_ret(): def instance_ret(): - return C() + return str(C()) fn = compile_function(instance_ret, []) assert fn() == '' From fijal at codespeak.net Fri Sep 8 12:54:22 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 8 Sep 2006 12:54:22 +0200 (CEST) Subject: [pypy-svn] r32078 - pypy/dist/pypy/doc/discussion Message-ID: <20060908105422.7F81910074@code0.codespeak.net> Author: fijal Date: Fri Sep 8 12:54:07 2006 New Revision: 32078 Added: pypy/dist/pypy/doc/discussion/distribution.txt (contents, props changed) Log: How I do see that. Added: pypy/dist/pypy/doc/discussion/distribution.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/distribution.txt Fri Sep 8 12:54:07 2006 @@ -0,0 +1,34 @@ +=================================================== +(Semi)-transparent distribution of RPython programs +=================================================== + +Some (rough) ideas how I see distribution +----------------------------------------- + +The main point about it, is to behave very much like JIT - not +to perform distribution on Python source code level, but instead +perform distribution of RPython source, and eventually perform +distribution of interpreter at the end. + +This attempt gives same advantages as off-line JIT (any RPython based +interpreter, etc.) and gives nice field to play with different +distribution heuristics. This also makes eventually nice possibility +of integrating JIT with distribution, thus allowing distribution +heuristics to have more information that they might have otherwise and +as well with specializing different nodes in performing different tasks. + +Flow graph level +---------------- + +Probably the best place to perform distribution attempt is to insert +special graph distributing operations into low-level graphs (either lltype +or ootype based), which will allow distribution heuristic to decide +on entrypoint to block/graph/some other structure??? what variables/functions +are accessed inside some part and if it's worth transferring it over wire. + +Backend level +------------- + +Backends will need explicit support for distribution of any kind. Basically +it should be possible for backend to remotely call block/graph/structure +in any manner (it should strongly depend on backend possibilities). From fijal at codespeak.net Fri Sep 8 12:56:24 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 8 Sep 2006 12:56:24 +0200 (CEST) Subject: [pypy-svn] r32079 - pypy/dist/pypy/doc Message-ID: <20060908105624.BA18110077@code0.codespeak.net> Author: fijal Date: Fri Sep 8 12:56:07 2006 New Revision: 32079 Modified: pypy/dist/pypy/doc/index.txt Log: Added JS link. Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Fri Sep 8 12:56:07 2006 @@ -76,6 +76,9 @@ to write modules in PyPy's style and compile them into regular CPython extension modules. +`JavaScript backend`_ describes how to use JavaScript backend to create +AJAX-based web pages. + `EU reports`_ is a page that contains links to the preliminary reports that we submitted to the European Union. @@ -128,6 +131,7 @@ .. _`translation aspects`: translation-aspects.html .. _`coding guide`: coding-guide.html .. _`architecture`: architecture.html +.. _`JavaScript backend` : js/using.html .. _`getting started`: getting-started.html .. _`theory`: theory.html .. _`bytecode interpreter`: interpreter.html From fijal at codespeak.net Fri Sep 8 13:09:56 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 8 Sep 2006 13:09:56 +0200 (CEST) Subject: [pypy-svn] r32080 - pypy/dist/pypy/translator/js/test Message-ID: <20060908110956.60D751007A@code0.codespeak.net> Author: fijal Date: Fri Sep 8 13:09:44 2006 New Revision: 32080 Modified: pypy/dist/pypy/translator/js/test/test_transformer.py Log: Added a test. Modified: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_transformer.py (original) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Fri Sep 8 13:09:44 2006 @@ -5,6 +5,7 @@ from pypy.translator.js.main import rpython2javascript from pypy.translator.js.test.runtest import compile_function from pypy.translator.transformer.debug import traceback_handler +from pypy.rpython.nonconst import NonConstant as NonConst def check_tb(tb_entry_str, callname, args, func, relline): tb_entry = tb_entry_str.split(":") @@ -88,3 +89,19 @@ check_tb(lst[2], "f", "(3, 'dupa'", g, 1) # XXX: indirect call test as well + +def test_annotation(): + def f(): + raise TypeError() + + def wrapper(): + try: + traceback_handler.enter(NonConst("entrypoint"), NonConst("()"), NonConst(""), NonConst(0)) + f() + except: + return "|".join(["%s:%s:%s:%s" % k for k in traceback_handler.tb[1:]]) + + fn = compile_function(wrapper, [], debug_transform=True) + retval = fn() + lst = retval.split("|") + check_tb(lst[0], "f", "()", wrapper, 3) From mwh at codespeak.net Fri Sep 8 13:45:05 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Sep 2006 13:45:05 +0200 (CEST) Subject: [pypy-svn] r32081 - in pypy/branch/more-gckinds/pypy: annotation rpython rpython/lltypesystem Message-ID: <20060908114505.53C711007E@code0.codespeak.net> Author: mwh Date: Fri Sep 8 13:45:02 2006 New Revision: 32081 Modified: pypy/branch/more-gckinds/pypy/annotation/model.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py pypy/branch/more-gckinds/pypy/rpython/rptr.py Log: add annotation and lltype support for special handling of interior pointers. no rtyping support at all yet, so lots of tests fail. Modified: pypy/branch/more-gckinds/pypy/annotation/model.py ============================================================================== --- pypy/branch/more-gckinds/pypy/annotation/model.py (original) +++ pypy/branch/more-gckinds/pypy/annotation/model.py Fri Sep 8 13:45:02 2006 @@ -515,6 +515,11 @@ def can_be_none(self): return False +class SomeInteriorPtr(SomePtr): + def __init__(self, ll_ptrtype): + assert isinstance(ll_ptrtype, lltype.InteriorPtr) + self.ll_ptrtype = ll_ptrtype + class SomeLLADTMeth(SomeObject): immutable = True def __init__(self, ll_ptrtype, func): @@ -596,6 +601,8 @@ return SomeOOClass(ootype.ROOT) elif isinstance(T, ExternalType): return SomeExternalBuiltin(T) + elif isinstance(T, lltype.InteriorPtr): + return SomeInteriorPtr(T) else: return SomePtr(T) else: Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Fri Sep 8 13:45:02 2006 @@ -619,6 +619,23 @@ o = self.TO._container_example() return _ptr(self, o, solid=True) +class InteriorPtr(LowLevelType): + def __init__(self, PARENTTYPE, TO, offsets): + self.PARENTTYPE = PARENTTYPE + self.TO = TO + self.offsets = tuple(offsets) + def __str__(self): + return '%s (%s).%s'%(self.__class__.__name__, + self.PARENTTYPE._short_name(), + '.'.join(map(str, self.offsets))) + def _example(self): + ob = self.PARENTTYPE._container_example() + for o in self.offsets: + if isinstance(o, str): + ob = ob._getattr(o) + else: + ob = ob.getitem(0) + return ob # ____________________________________________________________ @@ -824,13 +841,6 @@ parent, base = parentlink(ptr._obj) return _subarray._makeptr(parent, base + n, ptr._solid) -def _expose(val, solid=False): - """XXX A nice docstring here""" - T = typeOf(val) - if isinstance(T, ContainerType): - val = _ptr(Ptr(T), val, solid=solid) - return val - def parentlink(container): parent = container._parentstructure() if parent is not None: @@ -877,26 +887,14 @@ class UninitializedMemoryAccess(Exception): pass -class _ptr(object): - __slots__ = ('_TYPE', '_T', - '_weak', '_solid', - '_obj0', '__weakref__') +class _abstract_ptr(object): + __slots__ = ('_T',) - def _set_TYPE(self, TYPE): - _ptr._TYPE.__set__(self, TYPE) + # assumes one can access _TYPE, _expose and _obj def _set_T(self, T): _ptr._T.__set__(self, T) - def _set_weak(self, weak): - _ptr._weak.__set__(self, weak) - - def _set_solid(self, solid): - _ptr._solid.__set__(self, solid) - - def _set_obj0(self, obj): - _ptr._obj0.__set__(self, obj) - def _togckind(self): return self._T._gckind @@ -904,19 +902,8 @@ # XXX deprecated interface return self._TYPE._needsgc() # xxx other rules? - def __init__(self, TYPE, pointing_to, solid=False): - self._set_TYPE(TYPE) - self._set_T(TYPE.TO) - self._set_weak(False) - self._setobj(pointing_to, solid) - - def _become(self, other): - assert self._TYPE == other._TYPE - assert not self._weak - self._setobj(other._obj, other._solid) - def __eq__(self, other): - if not isinstance(other, _ptr): + if type(self) is not type(other): raise TypeError("comparing pointer with %r object" % ( type(other).__name__,)) if self._TYPE != other._TYPE: @@ -938,40 +925,11 @@ except DelayedPointer: return True # assume it's not a delayed null - # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, - # use _obj if necessary instead ! - def _setobj(self, pointing_to, solid=False): - if pointing_to is None: - obj0 = None - elif (solid or self._T._gckind != 'raw' or - isinstance(self._T, FuncType)): - obj0 = pointing_to - else: - self._set_weak(True) - obj0 = pickleable_weakref(pointing_to) - self._set_solid(solid) - self._set_obj0(obj0) - - def _getobj(self): - obj = self._obj0 - if obj is not None: - if self._weak: - obj = obj() - if obj is None: - raise RuntimeError("accessing already garbage collected %r" - % (self._T,)) - if isinstance(obj, _container): - obj._check() - elif isinstance(obj, str) and obj.startswith("delayed!"): - raise DelayedPointer - return obj - _obj = property(_getobj) - def __getattr__(self, field_name): # ! can only return basic or ptr ! if isinstance(self._T, Struct): if field_name in self._T._flds: o = self._obj._getattr(field_name) - return _expose(o, self._solid) + return self._expose(field_name, o) if isinstance(self._T, ContainerType): try: adtmeth = self._T._adtmeths[field_name] @@ -987,20 +945,6 @@ raise AttributeError("%r instance has no field %r" % (self._T, field_name)) - #def _setfirst(self, p): - # if isinstance(self._T, Struct) and self._T._names: - # if not isinstance(p, _ptr) or not isinstance(p._obj, _struct): - # raise InvalidCast(typeOf(p), typeOf(self)) - # field_name = self._T._names[0] - # T1 = self._T._flds[field_name] - # T2 = typeOf(p._obj) - # if T1 != T2: - # raise InvalidCast(typeOf(p), typeOf(self)) - # setattr(self._obj, field_name, p._obj) - # p._obj._setparentstructure(self._obj, 0) - # return - # raise TypeError("%r instance has no first field" % (self._T,)) - def __setattr__(self, field_name, val): if isinstance(self._T, Struct): if field_name in self._T._flds: @@ -1024,7 +968,7 @@ raise TypeError("array slicing not supported") raise IndexError("array index out of bounds") o = self._obj.getitem(i) - return _expose(o, self._solid) + return self._expose(i, o) raise TypeError("%r instance is not an array" % (self._T,)) def __setitem__(self, i, val): @@ -1087,6 +1031,64 @@ __getstate__ = getstate_with_slots __setstate__ = setstate_with_slots +class _ptr(_abstract_ptr): + __slots__ = ('_TYPE', + '_weak', '_solid', + '_obj0', '__weakref__') + + def _set_TYPE(self, TYPE): + _ptr._TYPE.__set__(self, TYPE) + + def _set_weak(self, weak): + _ptr._weak.__set__(self, weak) + + def _set_solid(self, solid): + _ptr._solid.__set__(self, solid) + + def _set_obj0(self, obj): + _ptr._obj0.__set__(self, obj) + + def __init__(self, TYPE, pointing_to, solid=False): + self._set_TYPE(TYPE) + self._set_T(TYPE.TO) + self._set_weak(False) + self._setobj(pointing_to, solid) + + def _become(self, other): + assert self._TYPE == other._TYPE + assert not self._weak + self._setobj(other._obj, other._solid) + + + # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, + # use _obj if necessary instead ! + def _setobj(self, pointing_to, solid=False): + if pointing_to is None: + obj0 = None + elif (solid or self._T._gckind != 'raw' or + isinstance(self._T, FuncType)): + obj0 = pointing_to + else: + self._set_weak(True) + obj0 = pickleable_weakref(pointing_to) + self._set_solid(solid) + self._set_obj0(obj0) + + def _getobj(self): + obj = self._obj0 + if obj is not None: + if self._weak: + obj = obj() + if obj is None: + raise RuntimeError("accessing already garbage collected %r" + % (self._T,)) + if isinstance(obj, _container): + obj._check() + elif isinstance(obj, str) and obj.startswith("delayed!"): + raise DelayedPointer + return obj + _obj = property(_getobj) + def _cast_to(self, PTRTYPE): CURTYPE = self._TYPE down_or_up = castable(PTRTYPE, CURTYPE) @@ -1148,8 +1150,66 @@ def _as_obj(self): return self._obj + def _expose(self, offset, val): + """XXX A nice docstring here""" + T = typeOf(val) + if isinstance(T, ContainerType): + if T._gckind == 'raw': + val = _interior_ptr(T, self._obj, [offset]) + else: + val = _ptr(Ptr(T), val, solid=self._solid) + return val + assert not '__dict__' in dir(_ptr) +class _interior_ptr(_abstract_ptr): + __slots__ = ('_parent', '_offsets') + def _set_parent(self, _parent): + _interior_ptr._parent.__set__(self, _parent) + def _set_offsets(self, _offsets): + _interior_ptr._offsets.__set__(self, _offsets) + + def __init__(self, _T, _parent, _offsets): + self._set_T(_T) + #self._set_parent(weakref.ref(_parent)) + self._set_parent(_parent) + self._set_offsets(_offsets) + + def _get_obj(self): + ob = self._parent + if ob is None: + raise RuntimeError + for o in self._offsets: + if isinstance(o, int): + ob = ob.getitem(o) + elif isinstance(o, str): + ob = ob._getattr(o) + else: + 1/0 + return ob + _obj = property(_get_obj) + + def _get_TYPE(self): + ob = self._parent + if ob is None: + raise RuntimeError + return InteriorPtr(typeOf(ob), self._T, self._offsets) + _TYPE = property(_get_TYPE) + + def _expose(self, offset, val): + """XXX A nice docstring here""" + T = typeOf(val) + if isinstance(T, ContainerType): + if T._gckind == 'raw': + val = _interior_ptr(T, self._parent, self._offsets + [offset]) + else: + 1/0 + return val + + + +assert not '__dict__' in dir(_interior_ptr) + class _container(object): __slots__ = () def _parentstructure(self): Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py Fri Sep 8 13:45:02 2006 @@ -55,11 +55,11 @@ # # there's also a nongcobject -OBJECT_VTABLE = lltype.ForwardReference() +OBJECT_VTABLE = lltype.GcForwardReference() CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE)) OBJECTPTR = Ptr(OBJECT) -OBJECT_VTABLE.become(Struct('object_vtable', +OBJECT_VTABLE.become(GcStruct('object_vtable', ('parenttypeptr', CLASSTYPE), ('subclassrange_min', Signed), ('subclassrange_max', Signed), @@ -100,7 +100,7 @@ # 'object' root type self.vtable_type = OBJECT_VTABLE else: - self.vtable_type = lltype.ForwardReference() + self.vtable_type = lltype.GcForwardReference() self.lowleveltype = Ptr(self.vtable_type) def _setup_repr(self): @@ -139,7 +139,7 @@ self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) self.rbase.setup() kwds = {'hints': {'immutable': True}} - vtable_type = Struct('%s_vtable' % self.classdef.name, + vtable_type = GcStruct('%s_vtable' % self.classdef.name, ('super', self.rbase.vtable_type), *llfields, **kwds) self.vtable_type.become(vtable_type) Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Fri Sep 8 13:45:02 2006 @@ -19,6 +19,12 @@ ## else: return self.__class__, self.ll_ptrtype +class __extend__(annmodel.SomeInteriorPtr): + def rtyper_makerepr(self, rtyper): +## if self.is_constant() and not self.const: # constant NULL +## return nullptr_repr +## else: + return InteriorPtrRepr(self.ll_ptrtype) class PtrRepr(Repr): From mwh at codespeak.net Fri Sep 8 14:10:39 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Sep 2006 14:10:39 +0200 (CEST) Subject: [pypy-svn] r32082 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem Message-ID: <20060908121039.088C010079@code0.codespeak.net> Author: mwh Date: Fri Sep 8 14:10:37 2006 New Revision: 32082 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py Log: address some comments from arigo & pedronis Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Fri Sep 8 14:10:37 2006 @@ -919,12 +919,6 @@ def __hash__(self): raise TypeError("pointer objects are not hashable") - def __nonzero__(self): - try: - return self._obj is not None - except DelayedPointer: - return True # assume it's not a delayed null - def __getattr__(self, field_name): # ! can only return basic or ptr ! if isinstance(self._T, Struct): if field_name in self._T._flds: @@ -1059,6 +1053,11 @@ assert not self._weak self._setobj(other._obj, other._solid) + def __nonzero__(self): + try: + return self._obj is not None + except DelayedPointer: + return True # assume it's not a delayed null # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, # use _obj if necessary instead ! @@ -1154,7 +1153,7 @@ """XXX A nice docstring here""" T = typeOf(val) if isinstance(T, ContainerType): - if T._gckind == 'raw': + if self._T._gckind == 'gc' and T._gckind == 'raw': val = _interior_ptr(T, self._obj, [offset]) else: val = _ptr(Ptr(T), val, solid=self._solid) @@ -1175,6 +1174,9 @@ self._set_parent(_parent) self._set_offsets(_offsets) + def __nonzero__(self): + raise RuntimeError, "do not test an interior pointer for nullity" + def _get_obj(self): ob = self._parent if ob is None: Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rclass.py Fri Sep 8 14:10:37 2006 @@ -55,11 +55,11 @@ # # there's also a nongcobject -OBJECT_VTABLE = lltype.GcForwardReference() +OBJECT_VTABLE = lltype.ForwardReference() CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE)) OBJECTPTR = Ptr(OBJECT) -OBJECT_VTABLE.become(GcStruct('object_vtable', +OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', CLASSTYPE), ('subclassrange_min', Signed), ('subclassrange_max', Signed), @@ -100,7 +100,7 @@ # 'object' root type self.vtable_type = OBJECT_VTABLE else: - self.vtable_type = lltype.GcForwardReference() + self.vtable_type = lltype.ForwardReference() self.lowleveltype = Ptr(self.vtable_type) def _setup_repr(self): @@ -139,7 +139,7 @@ self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) self.rbase.setup() kwds = {'hints': {'immutable': True}} - vtable_type = GcStruct('%s_vtable' % self.classdef.name, + vtable_type = Struct('%s_vtable' % self.classdef.name, ('super', self.rbase.vtable_type), *llfields, **kwds) self.vtable_type.become(vtable_type) From mwh at codespeak.net Fri Sep 8 14:17:41 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Sep 2006 14:17:41 +0200 (CEST) Subject: [pypy-svn] r32083 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem Message-ID: <20060908121741.C3BBD1007C@code0.codespeak.net> Author: mwh Date: Fri Sep 8 14:17:41 2006 New Revision: 32083 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Log: so InteriorPtr._example wasn't right Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Fri Sep 8 14:17:41 2006 @@ -629,12 +629,12 @@ self.PARENTTYPE._short_name(), '.'.join(map(str, self.offsets))) def _example(self): - ob = self.PARENTTYPE._container_example() + ob = Ptr(self.PARENTTYPE)._example() for o in self.offsets: if isinstance(o, str): - ob = ob._getattr(o) + ob = getattr(ob, o) else: - ob = ob.getitem(0) + ob = ob[0] return ob # ____________________________________________________________ From mwh at codespeak.net Fri Sep 8 16:06:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Sep 2006 16:06:32 +0200 (CEST) Subject: [pypy-svn] r32085 - in pypy/branch/more-gckinds/pypy/rpython: . test Message-ID: <20060908140632.2949D1006F@code0.codespeak.net> Author: mwh Date: Fri Sep 8 16:06:29 2006 New Revision: 32085 Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Log: beginnings of rtyping support for interior pointers and a test which fails because of conflicting opinions about the lowleveltype of the result of a getsubstructure. Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Fri Sep 8 16:06:29 2006 @@ -2,7 +2,8 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow import model as flowmodel from pypy.rpython.lltypesystem.lltype import \ - Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray + Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray, \ + InteriorPtr from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr @@ -21,9 +22,6 @@ class __extend__(annmodel.SomeInteriorPtr): def rtyper_makerepr(self, rtyper): -## if self.is_constant() and not self.const: # constant NULL -## return nullptr_repr -## else: return InteriorPtrRepr(self.ll_ptrtype) class PtrRepr(Repr): @@ -187,4 +185,26 @@ return v return NotImplemented +class InteriorPtrRepr(Repr): + def __init__(self, ptrtype): + assert isinstance(ptrtype, InteriorPtr) + assert len(ptrtype.offsets) == 1 + offset, = ptrtype.offsets + assert isinstance(offset, str) + self.lowleveltype = Ptr(ptrtype.PARENTTYPE) + self.coffset = flowmodel.Constant(offset, Void) + self.resulttype = Ptr(ptrtype.TO) + + def access(self, hop): + assert hop.args_r[0] is self + return hop.genop('getsubstruct', [hop.args_v[0], self.coffset], + resulttype=self.resulttype) + def rtype_getattr(self, hop): + hop2 = hop.copy() + v_ptr = self.access(hop2) + hop2.r_s_popfirstarg() + hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.resulttype)) + return hop2.dispatch() + + rtype_setattr = rtype_getattr Modified: pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Fri Sep 8 16:06:29 2006 @@ -204,3 +204,16 @@ fptr(*(x,y)) py.test.raises(TypeError, "interpret(wrong, [1, 2])") + + +def test_interior_ptr(): + S = Struct("S", ('x', Signed)) + T = GcStruct("T", ('s', S)) + def g(s): + s.x = 1 + def f(): + t = malloc(T) + g(t.s) + return t.s.x + res = interpret(f, []) + assert res == 1 From mwh at codespeak.net Fri Sep 8 17:01:49 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Sep 2006 17:01:49 +0200 (CEST) Subject: [pypy-svn] r32086 - in pypy/branch/more-gckinds/pypy/rpython: . lltypesystem Message-ID: <20060908150149.0C92F10072@code0.codespeak.net> Author: mwh Date: Fri Sep 8 17:01:47 2006 New Revision: 32086 Modified: pypy/branch/more-gckinds/pypy/rpython/llinterp.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py pypy/branch/more-gckinds/pypy/rpython/rptr.py Log: get that test in test_rptr.py working. opimpl.op_getinteriorfield is a little bit strange... Modified: pypy/branch/more-gckinds/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/llinterp.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/llinterp.py Fri Sep 8 17:01:47 2006 @@ -486,6 +486,18 @@ op_bare_setfield = op_setfield + def op_setinteriorfield(self, obj, *fieldnamesval): + prefields, finalfield, fieldvalue = fieldnamesval[:-2], fieldnamesval[-2], fieldnamesval[-1] + for o in prefields: + if isinstance(o, str): + obj = getattr(obj, o) + else: + obj = obj[o] + if isinstance(finalfield, str): + setattr(obj, finalfield, fieldvalue) + else: + obj[finalfield] = fieldvalue + def op_getarrayitem(self, array, index): return array[index] Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py Fri Sep 8 17:01:47 2006 @@ -300,8 +300,10 @@ 'getarrayitem': LLOp(sideeffects=False), 'getarraysize': LLOp(canfold=True), 'getsubstruct': LLOp(canfold=True), + 'getinteriorfield': LLOp(canfold=True), # XXX not sure about the foldability... 'getarraysubstruct': LLOp(canfold=True), 'setfield': LLOp(), + 'setinteriorfield': LLOp(), 'bare_setfield': LLOp(), 'setarrayitem': LLOp(), 'cast_pointer': LLOp(canfold=True), Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py Fri Sep 8 17:01:47 2006 @@ -126,6 +126,20 @@ lltype.ContainerType) return getattr(obj, field) +def op_getinteriorfield(obj, *offsets): + checkptr(obj) + ob = obj + for o in offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + #1/0 + ob = ob[o] + if isinstance(ob, lltype._interior_ptr): + return obj + else: + return ob + def op_getarraysubstruct(array, index): checkptr(array) result = array[index] Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Fri Sep 8 17:01:47 2006 @@ -36,7 +36,10 @@ return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): - newopname = 'getsubstruct' + if self.lowleveltype.TO._gckind == 'gc' and FIELD_TYPE._gckind == 'raw': + newopname = 'getinteriorfield' + else: + newopname = 'getsubstruct' else: newopname = 'getfield' vlist = hop.inputargs(self, Void) @@ -192,19 +195,19 @@ offset, = ptrtype.offsets assert isinstance(offset, str) self.lowleveltype = Ptr(ptrtype.PARENTTYPE) - self.coffset = flowmodel.Constant(offset, Void) + self.v_offsets = [flowmodel.Constant(offset, Void)] self.resulttype = Ptr(ptrtype.TO) - def access(self, hop): - assert hop.args_r[0] is self - return hop.genop('getsubstruct', [hop.args_v[0], self.coffset], - resulttype=self.resulttype) - def rtype_getattr(self, hop): - hop2 = hop.copy() - v_ptr = self.access(hop2) - hop2.r_s_popfirstarg() - hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.resulttype)) - return hop2.dispatch() - - rtype_setattr = rtype_getattr + vlist = [hop.inputarg(hop.args_r[0], 0)] + self.v_offsets + vlist.append(hop.inputarg(Void, 1)) + return hop.genop('getinteriorfield', vlist, + resulttype=hop.r_result.lowleveltype) + + def rtype_setattr(self, hop): + vlist = [hop.inputarg(hop.args_r[0], 0)] + self.v_offsets + vlist.append(hop.inputarg(Void, 1)) + vlist.append(hop.inputarg(hop.args_r[2], 2)) + + return hop.genop('setinteriorfield', vlist, + resulttype=hop.r_result.lowleveltype) From ale at codespeak.net Fri Sep 8 18:00:14 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 8 Sep 2006 18:00:14 +0200 (CEST) Subject: [pypy-svn] r32087 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060908160014.7E0C71006F@code0.codespeak.net> Author: ale Date: Fri Sep 8 18:00:09 2006 New Revision: 32087 Added: pypy/dist/pypy/lib/pyontology/sparql_grammar.py pypy/dist/pypy/lib/pyontology/test/test_sparql.py Log: The beginning of a SPARQL query engine. Grammar copied and modified from rdflib. Requires pyparsing Added: pypy/dist/pypy/lib/pyontology/sparql_grammar.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/sparql_grammar.py Fri Sep 8 18:00:09 2006 @@ -0,0 +1,582 @@ + +from pyparsing import CaselessLiteral, Word, Upcase, delimitedList, Optional, \ + Combine, Dict, Group, alphas, nums, alphanums, ParseException, Forward, oneOf, \ + ZeroOrMore, restOfLine, Keyword, srange, OneOrMore, sglQuotedString, dblQuotedString, quotedString, \ + TokenConverter, Empty, Suppress, NoMatch, CharsNotIn, ParseResults + +from pyparsing import Literal as ppLiteral # name Literal assigned by grammar + +DEBUG = 0 + +def punctuation(lit, d=False): + o = ppLiteral(lit).setName(lit).setResultsName(lit, listAllMatches=True) + if DEBUG or d: o.setDebug() + return o + +def keyword(lit, d=False): + o = Keyword(lit, caseless=True).setResultsName(lit, listAllMatches=True).setName(lit) + if DEBUG or d: o.setDebug() + return o + +def production(lit, d=False): + o = Forward().setResultsName(lit, listAllMatches=True).setName(lit) + if DEBUG or d: o.setDebug() + return o + + +class SPARQLGrammar(object): + + # All productions are declared Forward(). This is primarily + # because the SPARQL spec defines the EBNF grammar in this way and + # I have stuck rigedly to the spec order. Paul McGuire (author of + # pyparsing) has recommended that I reverse the grammar + # definitions for clarity and performance as Forward()s incur an + # inderection performance hit. + # + # For now I want to keep it this way because SPARQL is still in + # flux, but as the language stabilizes it will make sense to + # reverse this grammar into something more "pythonic". + + dot = punctuation(".") + at = punctuation("@") + dash = punctuation("-") + qmark = punctuation("?") + dollar = punctuation("$") + colon = punctuation(":") + semi = punctuation(";") + lt = punctuation("<") + gt = punctuation(">") + typ = punctuation("^^") + lparen = punctuation("(") + rparen = punctuation(")") + bang = punctuation("!") + star = punctuation("*") + slash = punctuation("/") + plus = punctuation("+") + minus = punctuation("-") + lte = punctuation("<=") + gte = punctuation(">=") + eq = punctuation("=") + noteq = punctuation("!=") + lbrack = punctuation("[") + rbrack = punctuation("]") + lcbrack = punctuation("{") + rcbrack = punctuation("}") + leq = punctuation('eq') + lne = punctuation('ne') + bnode = punctuation('_:') + comma = punctuation(',') + lor = punctuation('||') + land = punctuation('&&') + + # keywords + + _select = keyword('select') + _distinct = keyword('distinct') + _construct = keyword('construct') + _describe = keyword('describe') + _ask = keyword('ask') + _from = keyword('from') + _where = keyword('where') + _optional = keyword('optional') + _prefix = keyword('prefix') + _limit = keyword('limit') + _base = keyword('base') + _named = keyword('named') + _offset = keyword('offset') + _a = keyword('a') + _str = keyword('str') + _true = keyword('true') + _false = keyword('false') + _order = keyword('order') + _by = keyword('by') + _asc = keyword('asc') + _desc = keyword('desc') + _graph = keyword('graph') + _union = keyword('union') + _filter = keyword('filter') + _lang = keyword('lang') + _datatype = keyword('datatype') + _bound = keyword('bound') + _isuri = keyword('isuri') + _isblank = keyword('isblank') + _isliteral = keyword('isliteral') + _regex = keyword('regex') + + # productions + + Query = production('Query') + Prolog = production('Prolog') + BaseDecl = production('BaseDecl') + PrefixDecl = production('PrefixDecl') + SelectQuery = production('SelectQuery') + ConstructQuery = production('ConstructQuery') + DescribeQuery = production('DescribeQuery') + AskQuery = production('AskQuery') + DatasetClause = production('DatasetClause') + DefaultGraphClause = production('DefaultGraphClause') + NamedGraphClause = production('NamedGraphClause') + SourceSelector = production('SourceSelector') + WhereClause = production('WhereClause') + SolutionModifier = production('SolutionModifier') + OrderClause = production('OrderClause') + OrderCondition = production('OrderCondition') + LimitClause = production('LimitClause') + OffsetClause = production('OffsetClause') + GroupGraphPattern = production('GroupGraphPattern') + GraphPattern = production('GraphPattern') + GraphPatternNotTriples = production('GraphPatternNotTriples') + OptionalGraphPattern = production('OptionalGraphPattern') + GraphGraphPattern = production('GraphGraphPattern') + GroupOrUnionGraphPattern = production('GroupOrUnionGraphPattern') + Constraint = production('Constraint') + ConstructTemplate = production('ConstructTemplate') + Triples = production('Triples') + Triples1 = production('Triples1') + PropertyList = production('PropertyList') + PropertyListNotEmpty = production('PropertyListNotEmpty') + ObjectList = production('ObjectList') + Verb = production('Verb') + Object = production('Object') + TriplesNode = production('TriplesNode') + BlankNodePropertyList = production('BlankNodePropertyList') + Collection = production('BlankNodePropertyList') + GraphNode = production('GraphNode') + VarOrTerm = production('VarOrTerm') + VarOrIRIref = production('VarOrIRIref') + VarOrBlankNodeOrIRIref = production('VarOrBlankNodeOrIRIref') + Var = production('Var') + GraphTerm = production('GraphTerm') + Expression = production('Expression') + ConditionalOrExpression = production('ConditionalOrExpression') + ConditionalAndExpression = production('ConditionalAndExpression') + ValueLogical = production('ValueLogical') + RelationalExpression = production('RelationalExpression') + NumericExpression = production('NumericExpression') + AdditiveExpression = production('AdditiveExpression') + MultiplicativeExpression = production('MultiplicativeExpression') + UnaryExpression = production('UnaryExpression') + CallExpression = production('CallExpression') + RegexExpression = production('RegexExpression') + FunctionCall = production('FunctionCall') + ArgList = production('ArgList') + BrackettedExpression = production('BrackettedExpression') + PrimaryExpression = production('PrimaryExpression') + RDFTerm = production('RDFTerm') + NumericLiteral = production('NumericLiteral') + RDFLiteral = production('RDFLiteral') + BooleanLiteral = production('BooleanLiteral') + String = production('String') + IRIref = production('IRIref') + QName = production('QName') + BlankNode = production('BlankNode') + QuotedIRIref = production('QuotedIRIref') + QNAME_NS = production('QNAME_NS') + QNAME = production('QNAME') + BNODE_LABEL = production('BNODE_LABEL') + VAR1 = production('VAR1') + VAR2 = production('VAR2') + LANGTAG = production('LANGTAG') + INTEGER = production('INTEGER') + DECIMAL = production('DECIMAL') + FLOATING_POINT = production('FLOATING_POINT') + EXPONENT = production('EXPONENT') + STRING_LITERAL1 = production('STRING_LITERAL1') + STRING_LITERAL2 = production('STRING_LITERAL2') + STRING_LITERAL_LONG1 = production('STRING_LITERAL_LONG1') + STRING_LITERAL_LONG2 = production('STRING_LITERAL_LONG2') + NCCHAR1 = production('NCCHAR1') + VARNAME = production('VARNAME') + NCCHAR = production('NCCHAR') + NCNAME_PREFIX = production('NCNAME_PREFIX') + NCNAME = production('NCNAME') + + _comment = '#' + restOfLine + + # BEGIN PRODUCTIONS + + # Query ::= Prolog + # ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery ) + + Query << Group(Prolog + (SelectQuery | ConstructQuery | DescribeQuery | AskQuery)).ignore(_comment) + + + # Prolog ::= BaseDecl? PrefixDecl* + + Prolog << ( Optional(BaseDecl) + ZeroOrMore(PrefixDecl)) + + # BaseDecl ::= 'BASE' QuotedIRIref + + BaseDecl << _base + QuotedIRIref + + member = Forward() + member << Group(Optional(NCNAME_PREFIX) + Suppress(':') + QuotedIRIref) + # PrefixDecl ::= 'PREFIX' QNAME_NS QuotedIRIref + + PrefixDecl << (_prefix.suppress() + Dict(delimitedList(member,':'))).setResultsName('PrefixDecl') + + # SelectQuery ::= 'SELECT' 'DISTINCT'? ( Var+ | '*' ) DatasetClause* WhereClause SolutionModifier + + SelectQuery << Group(_select + Optional(_distinct) + (OneOrMore(Var) | star) + + ZeroOrMore(DatasetClause) + WhereClause + SolutionModifier) + + # ConstructQuery ::= 'CONSTRUCT' ConstructTemplate DatasetClause* WhereClause SolutionModifier + + ConstructQuery << _construct + ConstructTemplate + ZeroOrMore(DatasetClause) + WhereClause + SolutionModifier + + # DescribeQuery ::= 'DESCRIBE' ( VarOrIRIref+ | '*' ) DatasetClause* WhereClause? SolutionModifier + + DescribeQuery << (_describe + (OneOrMore(VarOrIRIref) | star) + + ZeroOrMore(DatasetClause) + Optional(WhereClause) + SolutionModifier) + + # AskQuery ::= 'ASK' DatasetClause* WhereClause + + AskQuery << _ask + ZeroOrMore(DatasetClause) + WhereClause + + # DatasetClause ::= 'FROM' ( DefaultGraphClause | NamedGraphClause ) + + DatasetClause << _from + (DefaultGraphClause | NamedGraphClause) + + # DefaultGraphClause ::= SourceSelector + + DefaultGraphClause << SourceSelector + + # NamedGraphClause ::= 'NAMED' SourceSelector + + NamedGraphClause << _named + SourceSelector + + # SourceSelector ::= IRIref + + SourceSelector << IRIref + + # WhereClause ::= 'WHERE'? GroupGraphPattern + + WhereClause << Group(Optional(_where).suppress() + GroupGraphPattern) + + # SolutionModifier ::= OrderClause? LimitClause? OffsetClause? + + SolutionModifier << Optional(OrderClause) + Optional(LimitClause) + Optional(OffsetClause) + + # OrderClause ::= 'ORDER' 'BY' OrderCondition+ + + OrderClause << _order + _by + OneOrMore(OrderCondition) + + # OrderCondition ::= ( ( 'ASC' | 'DESC' ) BrackettedExpression ) + # | ( FunctionCall | Var | BrackettedExpression ) + + OrderCondition << (((_asc | _desc) + BrackettedExpression) | (FunctionCall | Var | BrackettedExpression)) + + # LimitClause ::= 'LIMIT' INTEGER + + LimitClause << _limit + INTEGER + + # OffsetClause ::= 'OFFSET' INTEGER + + OffsetClause << _offset + INTEGER + + # GroupGraphPattern ::= '{' GraphPattern '}' + + GroupGraphPattern << Group(lcbrack.suppress() + GraphPattern + rcbrack.suppress()) + + # GraphPattern ::= ( Triples '.'? )? ( GraphPatternNotTriples '.'? GraphPattern )? + + GraphPattern << Group(Optional(Triples + Optional(dot.suppress())) + Optional(GraphPatternNotTriples + Optional(dot.suppress()) + GraphPattern)) + + # GraphPatternNotTriples ::= OptionalGraphPattern | GroupOrUnionGraphPattern | GraphGraphPattern | Constraint + + GraphPatternNotTriples << (OptionalGraphPattern | GroupOrUnionGraphPattern | GraphGraphPattern | Constraint) + + # OptionalGraphPattern ::= 'OPTIONAL' GroupGraphPattern + + OptionalGraphPattern << _optional + GroupGraphPattern + + # GraphGraphPattern ::= 'GRAPH' VarOrBlankNodeOrIRIref GroupGraphPattern + + GraphGraphPattern << _graph + VarOrBlankNodeOrIRIref + GroupGraphPattern + + # GroupOrUnionGraphPattern ::= GroupGraphPattern ( 'UNION' GroupGraphPattern )* + + GroupOrUnionGraphPattern << GroupGraphPattern + ZeroOrMore(_union + GroupGraphPattern) + + # Constraint ::= 'FILTER' ( BrackettedExpression | CallExpression ) + + Constraint << ( _filter.suppress() + (BrackettedExpression | CallExpression)) + + # ConstructTemplate ::= '{' Triples? '.'? '}' + + ConstructTemplate << lcbrack.suppress() + Optional(Triples) + Optional(dot.suppress()) + rcbrack.suppress() + + # Triples ::= Triples1 ( '.' Triples )? + + Triples << Triples1 + Optional(dot.suppress() + Triples) + + # Triples1 ::= VarOrTerm PropertyListNotEmpty | TriplesNode PropertyList + + Triples1 << Group(VarOrTerm + PropertyListNotEmpty | TriplesNode + PropertyList).setResultsName('Triple', True) + + # PropertyList ::= PropertyListNotEmpty? + + PropertyList << Optional(PropertyListNotEmpty) + + # PropertyListNotEmpty ::= Verb ObjectList ( ';' PropertyList )? + + PropertyListNotEmpty << Verb + ObjectList + Optional(semi + PropertyList) + + # ObjectList ::= Object ( ',' ObjectList )? + + ObjectList << Group(Object + Optional(comma + ObjectList)) + + # Verb ::= VarOrBlankNodeOrIRIref | 'a' + + Verb << VarOrBlankNodeOrIRIref | _a + + # Object ::= VarOrTerm | TriplesNode + + Object << (VarOrTerm | TriplesNode) + + # TriplesNode ::= Collection | BlankNodePropertyList + + TriplesNode << (Collection | BlankNodePropertyList) + + # BlankNodePropertyList ::= '[' PropertyListNotEmpty ']' + + BlankNodePropertyList << lbrack.suppress() + PropertyListNotEmpty + rbrack.suppress() + + # Collection ::= '(' GraphNode+ ')' + + Collection << lparen.suppress() + OneOrMore(GraphNode) + rparen.suppress() + + # GraphNode ::= VarOrTerm | TriplesNode + + GraphNode << (VarOrTerm | TriplesNode) + + # VarOrTerm ::= Var | GraphTerm + + VarOrTerm << (Var | GraphTerm) + + # VarOrIRIref ::= Var | IRIref + + VarOrIRIref << (Var | IRIref) + + # VarOrBlankNodeOrIRIref ::= Var | BlankNode | IRIref + + VarOrBlankNodeOrIRIref << (Var | BlankNode | IRIref) + + # Var ::= VAR1 | VAR2 + + Var << (VAR1 | VAR2) + + # GraphTerm ::= RDFTerm | '(' ')' + + GraphTerm << (RDFTerm | lparen.suppress() + rparen.suppress()) + + # Expression ::= ConditionalOrExpression + + Expression << ConditionalOrExpression + + # ConditionalOrExpression ::= ConditionalAndExpression ( '||' ConditionalAndExpression )* + + ConditionalOrExpression << ConditionalAndExpression + ZeroOrMore( lor + ConditionalAndExpression) + + # ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )* + + ConditionalAndExpression << ValueLogical + ZeroOrMore(land + ValueLogical) + + # ValueLogical ::= RelationalExpression + + ValueLogical << RelationalExpression + + # RelationalExpression ::= NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression )? + + RelationalExpression << (NumericExpression + + Optional(eq.setResultsName('equals') + NumericExpression | + noteq.setResultsName('notequals') + NumericExpression | + lt.setResultsName('lessthan') + NumericExpression | + gt.setResultsName('greaterthan') + NumericExpression | + lte.setResultsName('lessthanorequal') + NumericExpression | + gte.setResultsName('greaterthanorequal') + NumericExpression)) + + # NumericExpression ::= AdditiveExpression + + NumericExpression << AdditiveExpression + + # AdditiveExpression ::= MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression )* + + AdditiveExpression << (MultiplicativeExpression + ZeroOrMore(plus + MultiplicativeExpression | + minus + MultiplicativeExpression)) + + # MultiplicativeExpression ::= UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )* + + MultiplicativeExpression << UnaryExpression + ZeroOrMore(star + UnaryExpression | slash + UnaryExpression) + + # UnaryExpression ::= '!' PrimaryExpression + # | '+' PrimaryExpression + # | '-' PrimaryExpression + # | PrimaryExpression + + UnaryExpression << (bang + PrimaryExpression | plus + PrimaryExpression | + minus + PrimaryExpression | PrimaryExpression) + + # CallExpression ::= 'STR' '(' Expression ')' + # | 'LANG' '(' Expression ')' + # | 'DATATYPE' '(' Expression ')' + # | 'BOUND' '(' Var ')' + # | 'isURI' '(' Expression ')' + # | 'isBLANK' '(' Expression ')' + # | 'isLITERAL' '(' Expression ')' + # | RegexExpression + # | FunctionCall + + CallExpression << Combine(_str + lparen.suppress() + Expression + rparen.suppress() | + _lang + lparen.suppress() + Expression + rparen.suppress() | + _datatype + lparen.suppress() + Expression + rparen.suppress() | + _bound + lparen.suppress() + Var + rparen.suppress() | + _isuri + lparen.suppress() + Expression + rparen.suppress() | + _isblank + lparen.suppress() + Expression + rparen.suppress() | + _isliteral + lparen.suppress() + Expression + rparen.suppress() | + RegexExpression | + FunctionCall) + + # RegexExpression ::= 'REGEX' '(' Expression ',' Expression ( ',' Expression )? ')' + + RegexExpression << _regex + lparen.suppress() + Expression + comma + Expression + Optional(comma + Expression) + rparen.suppress() + + # FunctionCall ::= IRIref ArgList + + FunctionCall << IRIref + ArgList + + # ArgList ::= ( '(' ')' | '(' Expression ( ',' Expression )* ')' ) + + ArgList << ((lparen.suppress() + rparen.suppress()) | lparen.suppress() + Expression + ZeroOrMore(comma + Expression) + rparen.suppress()) + + # BrackettedExpression ::= '(' Expression ')' + + BrackettedExpression << lparen.suppress() + Combine(Expression) + rparen.suppress() + + # PrimaryExpression ::= BrackettedExpression | CallExpression | Var | RDFTerm + + PrimaryExpression << (BrackettedExpression | CallExpression | Var | RDFTerm) + + # RDFTerm ::= IRIref | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode + + RDFTerm << (IRIref | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode) + + # NumericLiteral ::= INTEGER | FLOATING_POINT + + NumericLiteral << (INTEGER | FLOATING_POINT) + + # RDFLiteral ::= String ( LANGTAG | ( '^^' IRIref ) )? + + RDFLiteral << String + Optional( LANGTAG | ( typ.suppress() + IRIref)) + + # BooleanLiteral ::= 'true' | 'false' + + BooleanLiteral << (_true | _false) + + # String ::= STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 + + String << (STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2) + + # IRIref ::= QuotedIRIref | QName + + IRIref << (QuotedIRIref | QName) + + + # QName ::= QNAME | QNAME_NS + + QName << (QNAME | QNAME_NS) + + # BlankNode ::= BNODE_LABEL | '[' ']' + + BlankNode << (BNODE_LABEL | rbrack.suppress() + lbrack.suppress()) + + # QuotedIRIref ::= '<' ([^> ])* '>' /* An IRI reference : RFC 3987 */ + + QuotedIRIref << lt.suppress() + ZeroOrMore(CharsNotIn('> ')) + gt.suppress() + + # QNAME_NS ::= NCNAME_PREFIX? ':' + + QNAME_NS << Optional(NCNAME_PREFIX) + colon.suppress() + + # QNAME ::= NCNAME_PREFIX? ':' NCNAME? + + QNAME << Group(Optional(NCNAME_PREFIX) + colon.suppress() + Optional(NCNAME)) + + # BNODE_LABEL ::= '_:' NCNAME + + BNODE_LABEL << bnode + NCNAME + + # VAR1 ::= '?' VARNAME + + VAR1 << qmark.suppress() + (VARNAME) #.setResultsName('VARNAME') + + # VAR2 ::= '$' VARNAME + + VAR2 << dollar.suppress() + VARNAME + + # LANGTAG ::= '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* + + LANGTAG << at + Word(alphas) + ZeroOrMore(dash + Word(alphas + nums)) + + # INTEGER ::= [0-9]+ + + INTEGER << Word(nums) + + # DECIMAL ::= [0-9]+ '.' [0-9]* | '.' [0-9]+ + + DECIMAL << Word(nums) + dot + ZeroOrMore(nums) + + # FLOATING_POINT ::= [0-9]+ '.' [0-9]* EXPONENT? | '.' ([0-9])+ EXPONENT? | ([0-9])+ EXPONENT + + FLOATING_POINT << (OneOrMore(nums) + dot + ZeroOrMore(nums) + Optional(EXPONENT) | + dot + OneOrMore(nums) + Optional(EXPONENT) | OneOrMore(nums) + EXPONENT) + + # EXPONENT ::= [eE] [+-]? [0-9]+ + + EXPONENT << oneOf('e E') + Optional(oneOf('+ -')) + OneOrMore(nums) + + # STRING_LITERAL1 ::= "'" ( ([^#x27#x5C#xA#xD]) | ('\' [^#xD#xA]) )* "'" + + STRING_LITERAL1 << sglQuotedString + + # STRING_LITERAL2 ::= '"' ( ([^#x22#x5C#xA#xD]) | ('\' [^#xD#xA]) )* '"' + + STRING_LITERAL2 << dblQuotedString + + # STRING_LITERAL_LONG1 ::= "'''" ( [^'\] | ('\' [^#xD#xA]) | ("'" [^']) | ("''" [^']) )* "'''" + + # STRING_LITERAL_LONG2 ::= '"""' ( [^"\] | ('\' [^#xD#xA]) | ('"' [^"]) | ('""' [^"]) )* '"""' + + # NCCHAR1 ::= [A-Z] + # | [a-z] + # | [#x00C0-#x00D6] + # | [#x00D8-#x00F6] + # | [#x00F8-#x02FF] + # | [#x0370-#x037D] + # | [#x037F-#x1FFF] + # | [#x200C-#x200D] + # | [#x2070-#x218F] + # | [#x2C00-#x2FEF] + # | [#x3001-#xD7FF] + # | [#xF900-#xFDCF] + # | [#xFDF0-#xFFFD] + # | [#x10000-#xEFFFF] + + NCCHAR1 << Word(alphas) + + # VARNAME ::= ( NCCHAR1 | [0-9] ) ( NCCHAR1 | "_" | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )* + + VARNAME << Group(Word(alphas+nums, alphas+nums+"_")) + + # NCCHAR ::= NCCHAR1 | '_' | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] + + NCCHAR << (NCCHAR1 | "_" | "-" | Word(nums)) + + # NCNAME_PREFIX ::= NCCHAR1 ((NCCHAR|".")* NCCHAR)? + + NCNAME_PREFIX << NCCHAR1 + Optional(ZeroOrMore(NCCHAR | ".") + NCCHAR) + + # NCNAME ::= ( "_" | NCCHAR1 ) ((NCCHAR|".")* NCCHAR)? + + NCNAME << ("_" | NCCHAR1) + Added: pypy/dist/pypy/lib/pyontology/test/test_sparql.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/test/test_sparql.py Fri Sep 8 18:00:09 2006 @@ -0,0 +1,88 @@ +from pypy.lib.pyontology.sparql_grammar import SPARQLGrammar as SP + + +qt = """ + PREFIX ns : + SELECT ?x ?y + WHERE { + ?x ns:p 123 . + ?y ns:q 'a123' . + FILTER ( ?x < 2 ) + } + """ + +def test_simple(): + query = SP.Query.parseString(qt)[0] + assert query.PrefixDecl[0].ns == 'http://example.org/ns#' + where = query.SelectQuery[0].WhereClause[0] + + assert len(where) == 1 + triples = where.GroupGraphPattern[0].Triples + assert len(triples) == 2 + assert triples[0][0].getName() == 'VAR1' + assert triples[1][0].getName() == 'VAR1' + assert triples[1][0][0] == 'x' + assert triples[0][0][0] == 'y' + assert triples[1][1].asList() == ['ns', 'p'] + assert triples[0][1].asList() == ['ns', 'q'] + assert triples[1][2][0] == '123' + assert triples[1][2].getName() == 'Object' + vars = query.SelectQuery[0].VARNAME + assert len(vars) == 2 + assert 'x' in vars[0][0] + assert 'y' in vars[1][0] + +class notest: + + def sparql(self, query): + qe = SP.Query.parseString(query)[0] + + prefixes = qe.PrefixDecl[0] + + resvars = [] + for v in qe.SelectQuery[0].VARNAME: + resvars.append(v[0]) + + where = qe.SelectQuery[0].WhereClause[0] + + triples = where.GroupGraphPattern[0].Triples + new = [] + for trip in triples: + newtrip = [] + for item in trip: + if item.NCNAME_PREFIX: + uri = prefixes[item.NCNAME_PREFIX[0]] + item.NCNAME[0] + newtrip.append(uri) + elif item.getName() == 'VAR1': + newtrip.append(item[0]) + else: + newtrip.append(item) + new.append(newtrip) + constrain = where.GroupGraphPattern[0].Constraint + return new, prefixes, resvars, constrain + +def test_sparql(): + n = notest() + result = n.sparql(qt) + res = result[0] + assert len(res) == 2 + assert len(res[0]) == len(res[1]) == 3 + assert res[0][1] in ['http://example.org/ns#p', 'http://example.org/ns#q'] + assert res[1][1] in ['http://example.org/ns#p', 'http://example.org/ns#q'] + assert result[3][0] == 'x<2' + +# There are 8 ways of having the triples in the query, if predicate is not a builtin owl predicate +# +# s p o +# +# bound bound bound ; Check if this triple entails +# var bound bound ; add a hasvalue constraint +# bound var bound ; for all p's return p if p[0]==s and p[1]==o +# bound bound var ; search for s in p +# var var bound ; for all p's return p[0] if p[1]==o +# var bound var ; return the values of p +# bound var var ; for all p's return p[1] if p[0]==s +# var var var ; for all p's return p.getvalues +# +# If p is a builtin owl property + From arigo at codespeak.net Fri Sep 8 19:52:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Sep 2006 19:52:04 +0200 (CEST) Subject: [pypy-svn] r32088 - in pypy/dist/pypy: annotation annotation/test interpreter objspace/std rpython rpython/lltypesystem/test rpython/test translator/c/test Message-ID: <20060908175204.749D91006F@code0.codespeak.net> Author: arigo Date: Fri Sep 8 19:51:59 2006 New Revision: 32088 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py pypy/dist/pypy/rpython/objectmodel.py pypy/dist/pypy/rpython/test/test_objectmodel.py pypy/dist/pypy/translator/c/test/test_rtagged.py Log: Add support for optional __slots__ in the annotator. If an attribute appears on a class, but is not in the __slots__ of that class, then there is probably a problem: the annotator moved the attribute up to a common base class when you were not expecting it. (Just to make sure this is clear, our usage of __slots__ is not about what attributes *should* appear, and certainly not about giving type hints. The annotator doesn't mind if a program doesn't seem to be using all the attributes specified in the __slots__. Such attributes won't appear in compiled programs anyway. And you couldn't tell the difference anyway :-) (And don't go adding __slots__ everywhere please! It's for abstract base classes kind of usage.) Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Fri Sep 8 19:51:59 2006 @@ -72,13 +72,14 @@ self.bookkeeper = bookkeeper self.s_value = s_ImpossibleValue self.readonly = True + self.slot_allowed = True self.read_locations = {} def add_constant_source(self, classdef, source): s_value = source.s_get_value(classdef, self.name) if source.instance_level: # a prebuilt instance source forces readonly=False, see above - self.readonly = False + self.modified(classdef) s_new_value = unionof(self.s_value, s_value) if isdegenerated(s_new_value): self.bookkeeper.ondegenerated("source %r attr %s" % (source, self.name), @@ -90,18 +91,16 @@ # Same as 'self.s_value' for historical reasons. return self.s_value - def merge(self, other, classdef=None): + def merge(self, other, classdef='?'): assert self.name == other.name s_new_value = unionof(self.s_value, other.s_value) if isdegenerated(s_new_value): - if classdef is None: - what = "? attr %s" % self.name - else: - what = "%r attr %s" % (classdef, self.name) + what = "%s attr %s" % (classdef, self.name) self.bookkeeper.ondegenerated(what, s_new_value) - self.s_value = s_new_value - self.readonly = self.readonly and other.readonly + self.s_value = s_new_value + if not other.readonly: + self.modified(classdef) self.read_locations.update(other.read_locations) def mutated(self, homedef): # reflow from attr read positions @@ -119,6 +118,17 @@ self.bookkeeper.warning("demoting method %s to base class %s" % (self.name, homedef)) + # check for attributes forbidden by slots + if homedef.classdesc.allslots is not None: + if self.name not in homedef.classdesc.allslots: + self.slot_allowed = False + if not self.readonly: + raise NoSuchSlotError(homedef, self.name) + + def modified(self, classdef='?'): + self.readonly = False + if not self.slot_allowed: + raise NoSuchSlotError(classdef, self.name) class ClassDef: @@ -401,6 +411,9 @@ self.obj.__dict__[name]) return s_value +class NoSuchSlotError(Exception): + "Raised when an attribute is found on a class where __slots__ forbits it." + # ____________________________________________________________ FORCE_ATTRIBUTES_INTO_CLASSES = { Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Fri Sep 8 19:51:59 2006 @@ -344,6 +344,7 @@ class ClassDesc(Desc): knowntype = type instance_level = False + allslots = None # or a set def __init__(self, bookkeeper, pyobj=None, name=None, basedesc=None, classdict=None, @@ -393,6 +394,18 @@ if base is not object: self.basedesc = bookkeeper.getdesc(base) + if '__slots__' in cls.__dict__: + slots = cls.__dict__['__slots__'] + if isinstance(slots, str): + slots = (slots,) + slots = dict.fromkeys(slots) + if self.basedesc is not None: + if self.basedesc.allslots is None: + raise Exception("%r has slots, but not its base class" + % (pyobj,)) + slots.update(self.basedesc.allslots) + self.allslots = slots + def add_source_attribute(self, name, value, mixin=False): if isinstance(value, types.FunctionType): # for debugging @@ -451,7 +464,7 @@ if cls in FORCE_ATTRIBUTES_INTO_CLASSES: for name, s_value in FORCE_ATTRIBUTES_INTO_CLASSES[cls].items(): classdef.generalize_attr(name, s_value) - classdef.find_attribute(name).readonly = False + classdef.find_attribute(name).modified(classdef) # register all class attributes as coming from this ClassDesc # (as opposed to prebuilt instances) Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Fri Sep 8 19:51:59 2006 @@ -2118,9 +2118,9 @@ def test_unboxed_value(self): class A(object): - pass + __slots__ = () class C(A, objectmodel.UnboxedValue): - __slots__ = 'smallint' + __slots__ = unboxedattrname = 'smallint' def f(n): return C(n).smallint @@ -2334,6 +2334,33 @@ assert not s.nonneg py.test.raises(Exception, a.build_types, fun, [s_nonneg, int]) + def test_slots_check(self): + class Base(object): + __slots__ = 'x' + class A(Base): + __slots__ = 'y' + def m(self): + return 65 + class C(Base): + __slots__ = 'z' + def m(self): + return 67 + for attrname, works in [('x', True), + ('y', False), + ('z', False), + ('t', False)]: + def fun(n): + if n: o = A() + else: o = C() + setattr(o, attrname, 12) + return o.m() + a = self.RPythonAnnotator() + if works: + a.build_types(fun, [int]) + else: + from pypy.annotation.classdef import NoSuchSlotError + py.test.raises(NoSuchSlotError, a.build_types, fun, [int]) + def g(n): return [0,1,2,n] Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Fri Sep 8 19:51:59 2006 @@ -523,7 +523,7 @@ # find the (possibly parent) class where this attr is defined clsdef = ins.classdef.locate_attribute(attr) attrdef = clsdef.attrs[attr] - attrdef.readonly = False + attrdef.modified(clsdef) # if the attrdef is new, this must fail if attrdef.getvalue().contains(s_value): Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Sep 8 19:51:59 2006 @@ -13,6 +13,8 @@ class W_Root(object): """This is the abstract root class of all wrapped objects that live in a 'normal' object space like StdObjSpace.""" + __slots__ = () + def getdict(self): return None Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Fri Sep 8 19:51:59 2006 @@ -212,6 +212,7 @@ "Parent base class for wrapped objects provided by the StdObjSpace." # Note that not all wrapped objects in the interpreter inherit from # W_Object. (They inherit from W_Root.) + __slots__ = () def __repr__(self): s = '%s(%s)' % ( Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Fri Sep 8 19:51:59 2006 @@ -9,6 +9,7 @@ class A(object): + __slots__ = () def meth(self, x): raise NotImplementedError Modified: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/objectmodel.py (original) +++ pypy/dist/pypy/rpython/objectmodel.py Fri Sep 8 19:51:59 2006 @@ -211,10 +211,10 @@ # this funtion is annotated but not included in the translated program int_as_pointer = value * 2 + 1 # XXX for now if -sys.maxint-1 <= int_as_pointer <= sys.maxint: - if isinstance(self.__slots__, str): - setattr(self, self.__slots__, value) + if isinstance(self.__class__.__slots__, str): + setattr(self, self.__class__.__slots__, value) else: - setattr(self, self.__slots__[0], value) + setattr(self, self.__class__.__slots__[0], value) else: raise OverflowError("UnboxedValue: argument out of range") @@ -222,10 +222,10 @@ return '' % (self.getvalue(),) def getvalue(self): # helper, equivalent to reading the custom field - if isinstance(self.__slots__, str): - return getattr(self, self.__slots__) + if isinstance(self.__class__.__slots__, str): + return getattr(self, self.__class__.__slots__) else: - return getattr(self, self.__slots__[0]) + return getattr(self, self.__class__.__slots__[0]) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_objectmodel.py (original) +++ pypy/dist/pypy/rpython/test/test_objectmodel.py Fri Sep 8 19:51:59 2006 @@ -118,7 +118,7 @@ def test_unboxed_value(): class Base(object): - pass + __slots__ = () class C(Base, UnboxedValue): __slots__ = 'smallint' Modified: pypy/dist/pypy/translator/c/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_rtagged.py (original) +++ pypy/dist/pypy/translator/c/test/test_rtagged.py Fri Sep 8 19:51:59 2006 @@ -3,6 +3,7 @@ class A(object): + __slots__ = () def meth(self, x): raise NotImplementedError From pedronis at codespeak.net Fri Sep 8 20:53:52 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 8 Sep 2006 20:53:52 +0200 (CEST) Subject: [pypy-svn] r32089 - in pypy/dist/pypy/jit: codegen/i386 codegen/i386/test codegen/llgraph timeshifter timeshifter/test Message-ID: <20060908185352.BA36110077@code0.codespeak.net> Author: pedronis Date: Fri Sep 8 20:53:40 2006 New Revision: 32089 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (arigo, pedronis) Timeshifter and backends support for malloc_varsize. Some refactorings. Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Fri Sep 8 20:53:40 2006 @@ -162,19 +162,24 @@ self.mc.LEA(eax, mem(edx, offset)) return self.returnvar(eax) - def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): - # XXX! only works for GcArray(Signed) for now!! + def itemaddr(self, base, arraytoken, gv_index): + # uses ecx lengthoffset, startoffset, itemoffset = arraytoken - self.mc.MOV(edx, gv_ptr.operand(self)) if isinstance(gv_index, IntConst): startoffset += itemoffset * gv_index.value - op = mem(edx, startoffset) + op = mem(base, startoffset) elif itemoffset in SIZE2SHIFT: self.mc.MOV(ecx, gv_index.operand(self)) - op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset) + op = memSIB(base, ecx, SIZE2SHIFT[itemoffset], startoffset) else: self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - op = memSIB(edx, ecx, 0, startoffset) + op = memSIB(base, ecx, 0, startoffset) + return op + + def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): + # XXX! only works for GcArray(Signed) for now!! + self.mc.MOV(edx, gv_ptr.operand(self)) + op = self.itemaddr(edx, arraytoken, gv_index) return self.returnvar(op) def genop_getarraysize(self, arraytoken, gv_ptr): @@ -184,19 +189,10 @@ def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): # XXX! only works for GcArray(Signed) for now!! - lengthoffset, startoffset, itemoffset = arraytoken self.mc.MOV(eax, gv_value.operand(self)) self.mc.MOV(edx, gv_ptr.operand(self)) - if isinstance(gv_index, IntConst): - startoffset += itemoffset * gv_index.value - op = mem(edx, startoffset) - elif itemoffset in SIZE2SHIFT: - self.mc.MOV(ecx, gv_index.operand(self)) - op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset) - else: - self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - op = memSIB(edx, ecx, 0, startoffset) - self.mc.MOV(op, eax) + destop = self.itemaddr(edx, arraytoken, gv_index) + self.mc.MOV(destop, eax) def genop_malloc_fixedsize(self, size): # XXX boehm only, no atomic/non atomic distinction for now @@ -205,6 +201,19 @@ self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr))) return self.returnvar(eax) + def genop_malloc_varsize(self, varsizealloctoken, gv_size): + # XXX boehm only, no atomic/non atomic distinction for now + # XXX no overflow checking for now + op_size = self.itemaddr(None, varsizealloctoken, gv_size) + self.mc.LEA(edx, op_size) + self.push(edx) + gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) + self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr))) + lengthoffset, _, _ = varsizealloctoken + self.mc.MOV(ecx, gv_size.operand(self)) + self.mc.MOV(mem(eax, lengthoffset), ecx) + return self.returnvar(eax) + def genop_call(self, sigtoken, gv_fnptr, args_gv): for i in range(len(args_gv)-1, -1, -1): gv_arg = args_gv[i] @@ -523,6 +532,20 @@ return llmemory.sizeof(T) @staticmethod + @specialize.memo() + def varsizeAllocToken(T): + if isinstance(T, lltype.Array): + return RI386GenOp.arrayToken(T) + subfield = T._arrayfld + SUBFIELD = getattr(T, subfield) + subtoken = RI386GenOp.varsizeAllocToken(SUBFIELD) + length_offset, items_offset, item_size = subtoken + subfield_offset = llmemory.offsetof(T, subfield) + return (subfield_offset+length_offset, + subfield_offset+items_offset, + item_size) + + @staticmethod @specialize.memo() def arrayToken(A): return (llmemory.ArrayLengthOffset(A), Modified: pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py Fri Sep 8 20:53:40 2006 @@ -28,6 +28,8 @@ def allocToken(T): return len(T._names) + varsizeAllocToken = arrayToken + @staticmethod @specialize.memo() def constFieldName(T, name): Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Fri Sep 8 20:53:40 2006 @@ -185,6 +185,8 @@ return (LLConst(llimpl.constTYPE(TYPE)), LLConst(llimpl.constTYPE(lltype.Ptr(TYPE)))) + varsizeAllocToken = allocToken + @staticmethod @specialize.memo() def arrayToken(A): Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Fri Sep 8 20:53:40 2006 @@ -37,7 +37,9 @@ class StructTypeDesc(object): __metaclass__ = cachedtype firstsubstructdesc = None - + arrayfielddesc = None + varsizealloctoken = None + def __init__(self, RGenOp, TYPE): self.TYPE = TYPE self.PTRTYPE = lltype.Ptr(TYPE) @@ -50,6 +52,10 @@ for name in self.TYPE._names: FIELDTYPE = getattr(self.TYPE, name) if isinstance(FIELDTYPE, lltype.ContainerType): + if isinstance(FIELDTYPE, lltype.Array): + self.arrayfielddesc = ArrayFieldDesc(RGenOp, FIELDTYPE) + self.varsizealloctoken = RGenOp.varsizeAllocToken(TYPE) + continue substructdesc = StructTypeDesc(RGenOp, FIELDTYPE) assert name == self.TYPE._names[0], ( "unsupported: inlined substructures not as first field") @@ -129,10 +135,11 @@ self.defaultbox = self.redboxcls(self.kind, self.gv_default) class ArrayFieldDesc(FieldDesc): - def __init__(self, RGenOp, PTRTYPE): - assert isinstance(PTRTYPE.TO, lltype.Array) - FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF) - self.arraytoken = RGenOp.arrayToken(PTRTYPE.TO) + def __init__(self, RGenOp, TYPE): + assert isinstance(TYPE, lltype.Array) + FieldDesc.__init__(self, RGenOp, lltype.Ptr(TYPE), TYPE.OF) + self.arraytoken = RGenOp.arrayToken(TYPE) + self.varsizealloctoken = RGenOp.varsizeAllocToken(TYPE) self.indexkind = RGenOp.kindToken(lltype.Signed) # ____________________________________________________________ Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Fri Sep 8 20:53:40 2006 @@ -81,6 +81,12 @@ genvar = jitstate.curbuilder.genop2(opdesc.opname, gv_arg0, gv_arg1) return opdesc.redboxcls(opdesc.result_kind, genvar) +def ll_genmalloc_varsize(jitstate, contdesc, sizebox): + gv_size = sizebox.getgenvar(jitstate.curbuilder) + alloctoken = contdesc.varsizealloctoken + genvar = jitstate.curbuilder.genop_malloc_varsize(alloctoken, gv_size) + return rvalue.PtrRedBox(contdesc.ptrkind, genvar) + def ll_gengetfield(jitstate, fielddesc, argbox): if fielddesc.immutable and argbox.is_constant(): res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE), Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Fri Sep 8 20:53:40 2006 @@ -178,7 +178,7 @@ ts = self.timeshifter v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed)) - fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE) + fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() @@ -197,7 +197,7 @@ ts = self.timeshifter [v_argbox] = hop.inputargs(self.getredrepr(PTRTYPE)) - fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE) + fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() @@ -252,7 +252,7 @@ v_argbox, v_index, v_valuebox= hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed), self.getredrepr(VALUETYPE)) - fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE) + fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() @@ -287,6 +287,25 @@ r_result = hop.r_result return r_result.create(hop) + def translate_op_malloc_varsize(self, hop): + # XXX no array support for now + ts = self.timeshifter + assert isinstance(hop.r_result, RedRepr) + PTRTYPE = originalconcretetype(hop.s_result) + TYPE = PTRTYPE.TO + if isinstance(TYPE, lltype.Struct): + contdesc = rcontainer.StructTypeDesc(self.RGenOp, TYPE) + else: + contdesc = rcontainer.ArrayFieldDesc(self.RGenOp, TYPE) + c_contdesc = inputconst(lltype.Void, contdesc) + s_contdesc = ts.rtyper.annotator.bookkeeper.immutablevalue(contdesc) + v_jitstate = hop.llops.getjitstate() + v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=1) + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genmalloc_varsize, + [ts.s_JITState, s_contdesc, ts.s_RedBox], + [v_jitstate, c_contdesc, v_size ], ts.s_RedBox) + + def translate_op_ptr_nonzero(self, hop, reverse=False): ts = self.timeshifter PTRTYPE = originalconcretetype(hop.args_s[0]) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Fri Sep 8 20:53:40 2006 @@ -710,20 +710,27 @@ res = self.timeshift(ll_function, [], [], policy=P_NOVIRTUAL) assert res == 3 -## def test_red_array(self): -## A = lltype.GcArray(lltype.Signed) -## def ll_function(x, y, n): -## a = lltype.malloc(A, 2) -## a[0] = x -## a[1] = y -## return a[n] - -## res = self.timeshift(ll_function, [42, -42, 0], [], policy=P_NOVIRTUAL) -## assert res == 42 - -## res = self.timeshift(ll_function, [42, -42, 1], [], policy=P_NOVIRTUAL) -## assert res == -42 - + def test_red_array(self): + A = lltype.GcArray(lltype.Signed) + def ll_function(x, y, n): + a = lltype.malloc(A, 2) + a[0] = x + a[1] = y + return a[n]*len(a) + + res = self.timeshift(ll_function, [21, -21, 0], [], + policy=P_NOVIRTUAL) + assert res == 42 + self.check_insns({'malloc_varsize': 1, 'ptr_iszero': 1, + 'setarrayitem': 2, 'getarrayitem': 1, + 'getarraysize': 1, 'int_mul': 1}) + + res = self.timeshift(ll_function, [21, -21, 1], [], + policy=P_NOVIRTUAL) + assert res == -42 + self.check_insns({'malloc_varsize': 1, 'ptr_iszero': 1, + 'setarrayitem': 2, 'getarrayitem': 1, + 'getarraysize': 1, 'int_mul': 1}) def test_red_propagate(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) From arigo at codespeak.net Sat Sep 9 01:36:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Sep 2006 01:36:55 +0200 (CEST) Subject: [pypy-svn] r32091 - in pypy/dist/pypy: jit/codegen jit/codegen/i386 jit/codegen/i386/test jit/timeshifter jit/timeshifter/test jit/tl/test rpython/memory Message-ID: <20060908233655.842751006F@code0.codespeak.net> Author: arigo Date: Sat Sep 9 01:36:48 2006 New Revision: 32091 Added: pypy/dist/pypy/jit/codegen/graph2rgenop.py (contents, props changed) pypy/dist/pypy/jit/codegen/i386/test/test_genc_tl.py - copied, changed from r32080, pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlr.py pypy/dist/pypy/jit/codegen/i386/test/test_operation.py (contents, props changed) Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/i386/ri386setup.py pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/test/test_tl.py pypy/dist/pypy/jit/timeshifter/test/test_tlr.py pypy/dist/pypy/jit/tl/test/test_tl.py pypy/dist/pypy/jit/tl/test/test_tlr.py pypy/dist/pypy/rpython/memory/lltypelayout.py Log: (pedronis, arigo) The TL tests pass! - a bit more about malloc_varsize - benchmarking at various levels - graph2rgenop: for testing back-ends, turns a simple ll graph into a sequence of rgenop calls that builds the same code - more tests and more operations for ri386genop Added: pypy/dist/pypy/jit/codegen/graph2rgenop.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/graph2rgenop.py Sat Sep 9 01:36:48 2006 @@ -0,0 +1,77 @@ +""" +For testing purposes. Turns *simple enough* low-level graphs +into machine code by calling the rgenop interface. +""" +from pypy.rpython.lltypesystem import lltype +from pypy.objspace.flow import model as flowmodel + + +def compile_graph(rgenop, graph): + FUNC = lltype.FuncType([v.concretetype for v in graph.getargs()], + graph.getreturnvar().concretetype) + sigtoken = rgenop.sigToken(FUNC) + builder, entrypoint, args_gv = rgenop.newgraph(sigtoken) + + pending_blocks = {graph.startblock: (builder, args_gv)} + seen_blocks = {} + + def varkind(v): + return rgenop.kindToken(v.concretetype) + + def var2gv(v): + if isinstance(v, flowmodel.Variable): + return varmap[v] + else: + return rgenop.genconst(v.value) + + for block in graph.iterblocks(): + builder, args_gv = pending_blocks.pop(block) + assert len(args_gv) == len(block.inputargs) + label = builder.enter_next_block(map(varkind, block.inputargs), + args_gv) + seen_blocks[block] = label + varmap = dict(zip(block.inputargs, args_gv)) + + if not block.exits: + [retvar] = block.inputargs + builder.finish_and_return(sigtoken, varmap[retvar]) + continue + + for op in block.operations: + # XXX only supports some operations for now + if op.opname == 'malloc': + token = rgenop.allocToken(op.args[0].value) + gv_result = builder.genop_malloc_fixedsize(token) + elif op.opname == 'malloc_varsize': + token = rgenop.varsizeAllocToken(op.args[0].value) + gv_result = builder.genop_malloc_varsize(token, + var2gv(op.args[1])) + elif op.opname == 'getarrayitem': + token = rgenop.arrayToken(op.args[0].concretetype.TO) + gv_result = builder.genop_getarrayitem(token, + var2gv(op.args[0]), + var2gv(op.args[1])) + elif op.opname == 'setarrayitem': + token = rgenop.arrayToken(op.args[0].concretetype.TO) + gv_result = builder.genop_setarrayitem(token, + var2gv(op.args[0]), + var2gv(op.args[1]), + var2gv(op.args[2])) + elif len(op.args) == 1: + gv_result = builder.genop1(op.opname, var2gv(op.args[0])) + elif len(op.args) == 2: + gv_result = builder.genop2(op.opname, var2gv(op.args[0]), + var2gv(op.args[1])) + else: + raise NotImplementedError(op.opname) + varmap[op.result] = gv_result + + if block.exitswitch is not None: + raise NotImplementedError("XXX exitswitch") + else: + [link] = block.exits + args_gv = [var2gv(v) for v in link.args] + pending_blocks[link.target] = builder, args_gv + + return rgenop.gencallableconst(sigtoken, "compiled_%s" % (graph.name,), + entrypoint) Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Sat Sep 9 01:36:48 2006 @@ -76,8 +76,10 @@ return lltype.cast_primitive(T, self.value) def __repr__(self): - return "const=%s" % (imm(self.value).assembler(),) - + try: + return "const=%s" % (imm(self.value).assembler(),) + except TypeError: # from Symbolics + return "const=%r" % (self.value,) ##class FnPtrConst(IntConst): @@ -165,21 +167,29 @@ def itemaddr(self, base, arraytoken, gv_index): # uses ecx lengthoffset, startoffset, itemoffset = arraytoken + if itemoffset == 1: + memSIBx = memSIB8 + else: + memSIBx = memSIB if isinstance(gv_index, IntConst): startoffset += itemoffset * gv_index.value - op = mem(base, startoffset) + op = memSIBx(base, None, 0, startoffset) elif itemoffset in SIZE2SHIFT: self.mc.MOV(ecx, gv_index.operand(self)) - op = memSIB(base, ecx, SIZE2SHIFT[itemoffset], startoffset) + op = memSIBx(base, ecx, SIZE2SHIFT[itemoffset], startoffset) else: self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset)) - op = memSIB(base, ecx, 0, startoffset) + op = memSIBx(base, ecx, 0, startoffset) return op def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): - # XXX! only works for GcArray(Signed) for now!! self.mc.MOV(edx, gv_ptr.operand(self)) op = self.itemaddr(edx, arraytoken, gv_index) + _, _, itemsize = arraytoken + if itemsize != WORD: + assert itemsize == 1 or itemsize == 2 + self.mc.MOVZX(eax, op) + op = eax return self.returnvar(op) def genop_getarraysize(self, arraytoken, gv_ptr): @@ -188,17 +198,24 @@ return self.returnvar(mem(edx, lengthoffset)) def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): - # XXX! only works for GcArray(Signed) for now!! self.mc.MOV(eax, gv_value.operand(self)) self.mc.MOV(edx, gv_ptr.operand(self)) destop = self.itemaddr(edx, arraytoken, gv_index) + _, _, itemsize = arraytoken + if itemsize != WORD: + if itemsize == 1: + self.mc.MOV(destop, al) + return + elif itemsize == 2: + self.mc.o16() # followed by the MOV below + else: + raise AssertionError self.mc.MOV(destop, eax) def genop_malloc_fixedsize(self, size): # XXX boehm only, no atomic/non atomic distinction for now self.push(imm(size)) - gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) - self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr))) + self.mc.CALL(rel32(gc_malloc_fnaddr())) return self.returnvar(eax) def genop_malloc_varsize(self, varsizealloctoken, gv_size): @@ -207,8 +224,7 @@ op_size = self.itemaddr(None, varsizealloctoken, gv_size) self.mc.LEA(edx, op_size) self.push(edx) - gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) - self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr))) + self.mc.CALL(rel32(gc_malloc_fnaddr())) lengthoffset, _, _ = varsizealloctoken self.mc.MOV(ecx, gv_size.operand(self)) self.mc.MOV(mem(eax, lengthoffset), ecx) @@ -283,9 +299,12 @@ self.push(op) return res - def op_int_is_true(self, gv_x): + @staticmethod + def identity(gv_x): return gv_x + op_int_is_true = identity + def op_int_add(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.ADD(eax, gv_y.operand(self)) @@ -370,6 +389,11 @@ self.mc.NEG(eax) return self.returnvar(eax) + def op_int_invert(self, gv_x): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.NOT(eax) + return self.returnvar(eax) + def op_int_lshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.MOV(ecx, gv_y.operand(self)) @@ -394,6 +418,9 @@ self.mc.MOVZX(eax, al) return self.returnvar(eax) + op_cast_char_to_int = identity + op_cast_unichar_to_int = identity + op_ptr_nonzero = op_int_is_true op_ptr_iszero = op_bool_not # for now @@ -409,6 +436,27 @@ from pypy.rpython.lltypesystem.lloperation import llop return llop.call_boehm_gc_alloc(llmemory.Address, size) +def gc_malloc_fnaddr(): + """Returns the address of the Boehm 'malloc' function.""" + if objectmodel.we_are_translated(): + gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) + return lltype.cast_ptr_to_int(gc_malloc_ptr) + else: + # don't do this at home + try: + from ctypes import cast, c_void_p + from pypy.rpython.rctypes.tool import util + path = util.find_library('gc') + if path is None: + raise ImportError("Boehm (libgc) not found") + boehmlib = util.load_library(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 + # ____________________________________________________________ def remap_stack_layout(builder, outputargs_gv, targetblock): @@ -536,14 +584,16 @@ def varsizeAllocToken(T): if isinstance(T, lltype.Array): return RI386GenOp.arrayToken(T) - subfield = T._arrayfld - SUBFIELD = getattr(T, subfield) - subtoken = RI386GenOp.varsizeAllocToken(SUBFIELD) - length_offset, items_offset, item_size = subtoken - subfield_offset = llmemory.offsetof(T, subfield) - return (subfield_offset+length_offset, - subfield_offset+items_offset, - item_size) + else: + # var-sized structs + arrayfield = T._arrayfld + ARRAYFIELD = getattr(T, arrayfield) + arraytoken = RI386GenOp.arrayToken(ARRAYFIELD) + length_offset, items_offset, item_size = arraytoken + arrayfield_offset = llmemory.offsetof(T, arrayfield) + return (arrayfield_offset+length_offset, + arrayfield_offset+items_offset, + item_size) @staticmethod @specialize.memo() Modified: pypy/dist/pypy/jit/codegen/i386/ri386setup.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386setup.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386setup.py Sat Sep 9 01:36:48 2006 @@ -350,6 +350,8 @@ MOVZX = Instruction() MOVZX.mode2(REG, MODRM8, ['\x0F\xB6', register(1,8), modrm(2,'b')]) +MOVZX.mode2(REG, MODRM, ['\x0F\xB7', register(1,8), modrm(2)]) +# ^^^ but this only reads the 16 lower bits of the source MOVZX.as_all_suffixes = 1 MOVZX.as_alias = "MOVZ" @@ -404,6 +406,9 @@ BREAKPOINT.mode0(['\xCC']) BREAKPOINT.as_alias = "INT3" +o16 = Instruction() # 16-bits instruction prefix (name from 'nasm') +o16.mode0(['\x66']) + Conditions = { 'O': 0, Modified: pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py Sat Sep 9 01:36:48 2006 @@ -1,8 +1,8 @@ import os -from pypy.rpython.objectmodel import specialize from pypy.annotation import model as annmodel from pypy.jit.timeshifter.test import test_timeshift from pypy.jit.codegen.i386.ri386genop import RI386GenOp, IntConst +from pypy.jit.codegen.i386.test.test_operation import RGenOpPacked class Whatever(object): @@ -10,30 +10,9 @@ return True class I386LLInterpTimeshiftingTestMixin(object): - class RGenOp(RI386GenOp): - from pypy.jit.codegen.i386.codebuf import LLTypeMachineCodeBlock as MachineCodeBlock - - @staticmethod - @specialize.memo() - def fieldToken(T, name): - return list(T._names).index(name) - - @staticmethod - @specialize.memo() - def arrayToken(A): - return 0, 1, 1 - - @staticmethod - @specialize.memo() - def allocToken(T): - return len(T._names) - - varsizeAllocToken = arrayToken - - @staticmethod - @specialize.memo() - def constFieldName(T, name): - return IntConst(list(T._names).index(name)) + class RGenOp(RGenOpPacked): + from pypy.jit.codegen.i386.codebuf import LLTypeMachineCodeBlock \ + as MachineCodeBlock def timeshift(self, ll_function, values, opt_consts=[], *args, **kwds): values = self.timeshift_cached(ll_function, values, *args, **kwds) Added: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Sat Sep 9 01:36:48 2006 @@ -0,0 +1,118 @@ +import py +from pypy.rpython.objectmodel import specialize +from pypy.annotation import model as annmodel +from pypy.rpython.lltypesystem import lltype +from pypy.translator.translator import TranslationContext, graphof +from pypy.jit.codegen import graph2rgenop +from pypy.jit.codegen.i386.ri386genop import RI386GenOp +from pypy.rpython.memory.lltypelayout import convert_offset_to_int +from ctypes import cast, c_void_p, CFUNCTYPE, c_int + + +class RGenOpPacked(RI386GenOp): + """Like RI386GenOp, but produces concrete offsets in the tokens + instead of llmemory.offsets. These numbers may not agree with + your C compiler's. + """ + + @staticmethod + @specialize.memo() + def fieldToken(T, name): + return convert_offset_to_int(RI386GenOp.fieldToken(T, name)) + + @staticmethod + @specialize.memo() + def arrayToken(A): + return tuple(map(convert_offset_to_int, RI386GenOp.arrayToken(A))) + + @staticmethod + @specialize.memo() + def allocToken(T): + return convert_offset_to_int(RI386GenOp.allocToken(T)) + + @staticmethod + @specialize.memo() + def varsizeAllocToken(A): + return tuple(map(convert_offset_to_int, + RI386GenOp.varsizeAllocToken(A))) + + +class TestBasic: + + def rgen(self, ll_function, argtypes): + t = TranslationContext() + t.buildannotator().build_types(ll_function, argtypes) + t.buildrtyper().specialize() + graph = graphof(t, ll_function) + rgenop = RGenOpPacked() + self.rgenop = rgenop # keep this alive! + gv_generated = graph2rgenop.compile_graph(rgenop, graph) + ctypestypes = [c_int] * len(argtypes) # for now + fp = cast(c_void_p(gv_generated.value), CFUNCTYPE(c_int, *ctypestypes)) + return fp + + def test_arithmetic(self): + for fn in [lambda x, y: x + y, + lambda x, y: x - y, + lambda x, y: x * y, + lambda x, y: x // y, + lambda x, y: x << y, + lambda x, y: x >> y, + lambda x, y: x ^ y, + lambda x, y: x & y, + lambda x, y: x | y, + lambda x, y: -y, + lambda x, y: ~y, + ]: + fp = self.rgen(fn, [int, int]) + assert fp(40, 2) == fn(40, 2) + + def test_comparison(self): + for fn in [lambda x, y: int(x < y), + lambda x, y: int(x <= y), + lambda x, y: int(x == y), + lambda x, y: int(x != y), + lambda x, y: int(x > y), + lambda x, y: int(x >= y) + ]: + fp = self.rgen(fn, [int, int]) + assert fp(12, 11) == fn(12, 11) + assert fp(12, 12) == fn(12, 12) + assert fp(12, 13) == fn(12, 13) + assert fp(-12, 11) == fn(-12, 11) + assert fp(-12, 12) == fn(-12, 12) + assert fp(-12, 13) == fn(-12, 13) + assert fp(12, -11) == fn(12, -11) + assert fp(12, -12) == fn(12, -12) + assert fp(12, -13) == fn(12, -13) + assert fp(-12, -11) == fn(-12, -11) + assert fp(-12, -12) == fn(-12, -12) + assert fp(-12, -13) == fn(-12, -13) + + def test_char_array(self): + A = lltype.GcArray(lltype.Char) + def fn(n): + a = lltype.malloc(A, 5) + a[4] = 'H' + a[3] = 'e' + a[2] = 'l' + a[1] = 'l' + a[0] = 'o' + return ord(a[n]) + fp = self.rgen(fn, [int]) + for i in range(5): + assert fp(i) == fn(i) + + def test_unichar_array(self): + A = lltype.GcArray(lltype.UniChar) + def fn(n): + a = lltype.malloc(A, 5) + a[4] = u'H' + a[3] = u'e' + a[2] = u'l' + a[1] = u'l' + a[0] = u'o' + return ord(a[n]) + fp = self.rgen(fn, [int]) + for i in range(5): + assert fp(i) == fn(i) Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Sat Sep 9 01:36:48 2006 @@ -38,15 +38,16 @@ __metaclass__ = cachedtype firstsubstructdesc = None arrayfielddesc = None + alloctoken = None varsizealloctoken = None def __init__(self, RGenOp, TYPE): self.TYPE = TYPE self.PTRTYPE = lltype.Ptr(TYPE) - self.alloctoken = RGenOp.allocToken(self.TYPE) self.ptrkind = RGenOp.kindToken(self.PTRTYPE) innermostdesc = self - + if not TYPE._is_varsize(): + self.alloctoken = RGenOp.allocToken(TYPE) fielddescs = [] fielddesc_by_name = {} for name in self.TYPE._names: Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sat Sep 9 01:36:48 2006 @@ -288,7 +288,6 @@ return r_result.create(hop) def translate_op_malloc_varsize(self, hop): - # XXX no array support for now ts = self.timeshifter assert isinstance(hop.r_result, RedRepr) PTRTYPE = originalconcretetype(hop.s_result) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Sat Sep 9 01:36:48 2006 @@ -732,6 +732,26 @@ 'setarrayitem': 2, 'getarrayitem': 1, 'getarraysize': 1, 'int_mul': 1}) + def test_red_varsized_struct(self): + A = lltype.Array(lltype.Signed) + S = lltype.GcStruct('S', ('foo', lltype.Signed), ('a', A)) + def ll_function(x, y, n): + s = lltype.malloc(S, 3) + s.foo = len(s.a)-1 + s.a[0] = x + s.a[1] = y + return s.a[n]*s.foo + + res = self.timeshift(ll_function, [21, -21, 0], [], + policy=P_NOVIRTUAL) + assert res == 42 + self.check_insns(malloc_varsize=1) + + res = self.timeshift(ll_function, [21, -21, 1], [], + policy=P_NOVIRTUAL) + assert res == -42 + self.check_insns(malloc_varsize=1) + def test_red_propagate(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) def ll_function(n, k): Modified: pypy/dist/pypy/jit/timeshifter/test/test_tl.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_tl.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_tl.py Sat Sep 9 01:36:48 2006 @@ -1,6 +1,8 @@ -from pypy.rpython.lltypesystem.rstr import string_repr +from pypy.rpython.module.support import LLSupport from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC +from pypy.tool.sourcetools import func_with_new_name +from pypy.jit.conftest import Benchmark from pypy.jit.tl import tl from pypy.jit.tl.test.test_tl import FACTORIAL_SOURCE @@ -9,9 +11,22 @@ class TestTL(TimeshiftingTests): def test_tl(self): - import py; py.test.skip("in-progress") code = tl.compile(FACTORIAL_SOURCE) - ll_code = string_repr.convert_const(code) - res = self.timeshift(tl.interp_without_call, [ll_code, 0, 5], [0, 1], - policy=P_OOPSPEC) - assert res == 120 + bytecode = ','.join([str(ord(c)) for c in code]) + tl_interp_without_call = func_with_new_name( + tl.interp_without_call, "tl_interp_without_call") + # to stick attributes on the new function object, not on tl.interp_wit* + def build_bytecode(s): + result = ''.join([chr(int(t)) for t in s.split(',')]) + return LLSupport.to_rstr(result) + tl_interp_without_call.convert_arguments = [build_bytecode, int, int] + + if Benchmark.ENABLED: + n = 2500 + expected = 0 # far too many powers of 2 to be anything else + else: + n = 5 + expected = 120 + res = self.timeshift(tl_interp_without_call, [bytecode, 0, n], + [0, 1], policy=P_OOPSPEC) + assert res == expected Modified: pypy/dist/pypy/jit/timeshifter/test/test_tlr.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_tlr.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_tlr.py Sat Sep 9 01:36:48 2006 @@ -1,4 +1,3 @@ -from pypy.rpython.lltypesystem.rstr import string_repr from pypy.rpython.module.support import LLSupport from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC Modified: pypy/dist/pypy/jit/tl/test/test_tl.py ============================================================================== --- pypy/dist/pypy/jit/tl/test/test_tl.py (original) +++ pypy/dist/pypy/jit/tl/test/test_tl.py Sat Sep 9 01:36:48 2006 @@ -2,6 +2,7 @@ import operator from pypy.jit.tl.tl import interp, compile from pypy.jit.tl.opcode import * +from pypy.jit.conftest import Benchmark from pypy.translator.translator import TranslationContext from pypy.annotation import policy @@ -255,3 +256,18 @@ code = compile(FACTORIAL_SOURCE) res = interp(code, 0, 6) assert res == 720 + +def test_translate_factorial(): + # use py.test --benchmark to do the benchmarking + code = compile(FACTORIAL_SOURCE) + def driver(): + bench = Benchmark() + while 1: + res = interp(code, 0, 2500) + if bench.stop(): + break + return res + + fn = translate(driver, []) + res = fn() + assert res == 0 # too many powers of 2 to be anything else Modified: pypy/dist/pypy/jit/tl/test/test_tlr.py ============================================================================== --- pypy/dist/pypy/jit/tl/test/test_tlr.py (original) +++ pypy/dist/pypy/jit/tl/test/test_tlr.py Sat Sep 9 01:36:48 2006 @@ -1,7 +1,22 @@ from pypy.jit.tl import tlr +from pypy.jit.tl.test.test_tl import translate +from pypy.jit.conftest import Benchmark def test_square(): assert tlr.interpret(tlr.SQUARE, 1) == 1 assert tlr.interpret(tlr.SQUARE, 7) == 49 assert tlr.interpret(tlr.SQUARE, 9) == 81 + +def test_translate(): + def driver(): + bench = Benchmark() + while 1: + res = tlr.interpret(tlr.SQUARE, 1764) + if bench.stop(): + break + return res + + fn = translate(driver, []) + res = fn() + assert res == 1764 * 1764 Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lltypelayout.py (original) +++ pypy/dist/pypy/rpython/memory/lltypelayout.py Sat Sep 9 01:36:48 2006 @@ -5,6 +5,7 @@ primitive_to_fmt = {lltype.Signed: "l", lltype.Unsigned: "L", lltype.Char: "c", + lltype.UniChar: "H", # maybe lltype.Bool: "B", lltype.Float: "d", llmemory.Address: "P", @@ -103,6 +104,8 @@ return get_fixed_size(lltype.Signed) elif isinstance(offset, llmemory.GCHeaderOffset): return sizeof(offset.gcheaderbuilder.HDR) + elif isinstance(offset, llmemory.ArrayLengthOffset): + return 0 else: raise Exception("unknown offset type %r"%offset) From fijal at codespeak.net Sat Sep 9 09:13:30 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 Sep 2006 09:13:30 +0200 (CEST) Subject: [pypy-svn] r32104 - in pypy/dist/pypy: bin translator/js translator/js/test translator/transformer Message-ID: <20060909071330.2366E1007B@code0.codespeak.net> Author: fijal Date: Sat Sep 9 09:13:05 2006 New Revision: 32104 Modified: pypy/dist/pypy/bin/jscompile.py pypy/dist/pypy/translator/js/helper.py pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/js/test/test_transformer.py pypy/dist/pypy/translator/transformer/basictransform.py pypy/dist/pypy/translator/transformer/debug.py Log: jscompile needs to specify manually that we need debug transform. Fix list issues with debug transform (actually fix *in* transform instead of hacking annotator), probably need to track more stuff which track position_key. Some minor improvements in js, now show_traceback is standart (not using innerHTML any more). Need to rewrite as well distributed py.test. Modified: pypy/dist/pypy/bin/jscompile.py ============================================================================== --- pypy/dist/pypy/bin/jscompile.py (original) +++ pypy/dist/pypy/bin/jscompile.py Sat Sep 9 09:13:05 2006 @@ -9,15 +9,12 @@ import autopath import sys -from pypy.translator.js.main import rpython2javascript_main +from pypy.translator.js.main import rpython2javascript_main, Options from pypy.tool import option import optparse make_option = optparse.make_option -class Options(option.Options): - pass - def get_options(): options = [] @@ -27,13 +24,17 @@ options.append(make_option( '-o', '--output', action='store', type='string', dest='output', - default='output.js', help='File to save results (default output.js)')) + help='File to save results (default output.js)')) + + options.append(make_option( + '-d', '--debug', action='store_true', dest='debug_transform', + help="Use !EXPERIMENTAL! debug transform to produce tracebacks" + )) return options def process_options(argv): return option.process_options(get_options(), Options, argv) - if __name__ == '__main__': argv = process_options(sys.argv[1:]) Modified: pypy/dist/pypy/translator/js/helper.py ============================================================================== --- pypy/dist/pypy/translator/js/helper.py (original) +++ pypy/dist/pypy/translator/js/helper.py Sat Sep 9 09:13:05 2006 @@ -16,7 +16,7 @@ get_document().childNodes[0].childNodes[1].appendChild(debug_div) return debug_div -def show_traceback(tb, exc): +def __show_traceback(tb, exc): debug_div = get_document().getElementById("debug_div") if not debug_div: # create div here @@ -36,3 +36,5 @@ txt.nodeValue += line1 + '\n' + line2 txt.nodeValue += str(exc) + +__show_traceback.explicit_traceback = True Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Sat Sep 9 09:13:05 2006 @@ -12,7 +12,12 @@ from pypy.annotation.policy import AnnotatorPolicy import optparse import py -from pypy.tool.option import Options +from pypy.tool import option + +class Options(option.Options): + view = False + output = 'output.js' + debug_transform = False class FunctionNotFound(Exception): pass @@ -52,7 +57,7 @@ source_ssf_base = """ import %(module_name)s -from pypy.translator.js.helper import show_traceback +from pypy.translator.js.helper import __show_traceback from pypy.translator.transformer.debug import traceback_handler from pypy.rpython.nonconst import NonConstant as NonConst @@ -71,10 +76,12 @@ traceback_handler.leave(NonConst("entrypoint")) except Exception, e: new_tb = traceback_handler.tb[:] - show_traceback(new_tb, str(e)) + __show_traceback(new_tb, str(e)) + +%(fun_name)s.explicit_traceback = True """ -function_base = "%(module)s.%(fun_name)s(%(args)s)" +function_base = "%(module_name)s.%(fun_name)s(%(args)s)" wrapped_function_base = "%(fun_name)s(%(args)s)" def get_source_ssf(mod, module_name, function_names, use_debug=True): @@ -98,7 +105,7 @@ print retval return retval -def rpython2javascript(mod, function_names, use_debug=True, opts=Options): +def rpython2javascript(mod, function_names, opts=Options): module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: function_names.append('main') @@ -109,17 +116,18 @@ if func_code.func_code.co_argcount > 0 and func_code.func_code. \ co_argcount != len(func_code.func_defaults): raise BadSignature("Function %s does not have default arguments" % func_name) - source_ssf = get_source_ssf(mod, module_name, function_names, use_debug) + source_ssf = get_source_ssf(mod, module_name, function_names, opts.debug_transform) exec(source_ssf) in globals() # now we gonna just cut off not needed function # XXX: Really do that options = optparse.Values(defaults=DEFAULT_OPTIONS) - options.debug_transform = use_debug + options.debug_transform = opts.debug_transform + # XXX: This makes no sense (copying options) driver = TranslationDriver(options=options) try: driver.setup(some_strange_function_which_will_never_be_called, [], policy = JsPolicy()) driver.proceed(["compile_js"]) - if getattr(opts, 'view', False): + if opts.view: driver.translator.view() return driver.gen.tmpfile.open().read() # XXX: Add some possibility to write down selected file Modified: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_transformer.py (original) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Sat Sep 9 09:13:05 2006 @@ -105,3 +105,29 @@ retval = fn() lst = retval.split("|") check_tb(lst[0], "f", "()", wrapper, 3) + +def test_list_ann(): + def z(): + return 3 + + def f(i,x): + l = [i, x, z()] + return l + + def g(i, x): + l = f(i, x) + l.append(3) + + def wrapper(a, b): + try: + traceback_handler.enter(NonConst("entrypoint"), NonConst("()"), NonConst(""), NonConst(0)) + g(a, b) + except: + return "|".join(["%s:%s:%s:%s" % k for k in traceback_handler.tb[1:]]) + return "" + + fn = compile_function(wrapper, [int, int], debug_transform=True) + retval = fn() + lst = retval.split("|") + assert len(lst) == 1 + assert lst[0] == '' Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Sat Sep 9 09:13:05 2006 @@ -43,15 +43,13 @@ retval = model.Variable() return model.SpaceOperation(name, real_args, retval), retval + def clear_block(self, graph, block): + pass + def add_block(self, graph, block): - ann = self.annotator - args_s = [ann.bindings[v] for v in block.inputargs] - try: - del ann.annotated[block] - except KeyError: - pass - ann.addpendingblock(graph, block, args_s) - + assert self.annotator.annotated[block] + self.annotator.reflowpendingblock(graph, block) + def flow_method(self, _class, func_name, args): ann = self.annotator bk = self.bookkeeper @@ -66,7 +64,6 @@ self.transform_graph(graph) checkgraph(graph) self.translator.annotator.complete() - def get_const(self, arg): bk = self.bookkeeper Modified: pypy/dist/pypy/translator/transformer/debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/debug.py (original) +++ pypy/dist/pypy/translator/transformer/debug.py Sat Sep 9 09:13:05 2006 @@ -45,16 +45,16 @@ concretetype=bk.immutablevalue(traceback_handler)) def register_helpers(self): - return None for func_name, func_args in [("traceback", []), ("enter", ["aa", "aa", "aa", 3]), ("leave", ["aa"])]: graph = self.flow_method(TracebackHandler, func_name, func_args) graph.explicit_traceback = True def transform_block(self, graph, block): + self.clear_block(graph, block) next = [] changed = False - for op in block.operations: + for num, op in enumerate(block.operations): # XXX: We need to support indirect calls as well, but # just need to do it somehow differently if op.opname == 'simple_call' and \ @@ -71,6 +71,13 @@ next += [opg, opc, op, opgl, oplc] changed = True #next.append(op) + elif op.opname == 'newlist': + # move listdef position key + bk = self.bookkeeper + listdef = bk.listdefs[(graph, block, num)] + del bk.listdefs[(graph, block, num)] + bk.listdefs[(graph, block, len(next))] = listdef + next.append(op) else: next.append(op) block.operations = next @@ -92,7 +99,8 @@ return call_str, filename, lineno def transform_graph(self, graph): - if getattr(graph, 'explicit_traceback', None): + if getattr(graph, 'explicit_traceback', None) or\ + getattr(graph.func, 'explicit_traceback', None): return for block in graph.iterblocks(): From fijal at codespeak.net Sat Sep 9 11:51:51 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 Sep 2006 11:51:51 +0200 (CEST) Subject: [pypy-svn] r32105 - in pypy/dist/pypy/translator: js/test transformer transformer/test Message-ID: <20060909095151.36C9A10079@code0.codespeak.net> Author: fijal Date: Sat Sep 9 11:51:32 2006 New Revision: 32105 Modified: pypy/dist/pypy/translator/js/test/test_transformer.py pypy/dist/pypy/translator/transformer/basictransform.py pypy/dist/pypy/translator/transformer/debug.py pypy/dist/pypy/translator/transformer/test/test_debug.py Log: Fixed dictdef dictionary. Modified: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_transformer.py (original) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Sat Sep 9 11:51:32 2006 @@ -131,3 +131,30 @@ lst = retval.split("|") assert len(lst) == 1 assert lst[0] == '' + +def test_dict_ann(): + def z(): + return 3 + + def f(i,x): + b = z() + l = {x:b, i:z()} + return l + + def g(i, x): + l = f(i, x) + l[x] = 3 + + def wrapper(a, b): + try: + traceback_handler.enter(NonConst("entrypoint"), NonConst("()"), NonConst(""), NonConst(0)) + g(a, b) + except: + return "|".join(["%s:%s:%s:%s" % k for k in traceback_handler.tb[1:]]) + return "" + + fn = compile_function(wrapper, [int, int], debug_transform=True) + retval = fn() + lst = retval.split("|") + assert len(lst) == 1 + assert lst[0] == '' Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Sat Sep 9 11:51:32 2006 @@ -43,12 +43,14 @@ retval = model.Variable() return model.SpaceOperation(name, real_args, retval), retval - def clear_block(self, graph, block): - pass - def add_block(self, graph, block): - assert self.annotator.annotated[block] - self.annotator.reflowpendingblock(graph, block) + #assert self.annotator.annotated[block] + try: + self.annotator.reflowpendingblock(graph, block) + except: + ann = self.annotator + args_s = [ann.bindings[v] for v in block.inputargs] + ann.addpendingblock(graph, block, args_s) def flow_method(self, _class, func_name, args): ann = self.annotator Modified: pypy/dist/pypy/translator/transformer/debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/debug.py (original) +++ pypy/dist/pypy/translator/transformer/debug.py Sat Sep 9 11:51:32 2006 @@ -51,7 +51,6 @@ graph.explicit_traceback = True def transform_block(self, graph, block): - self.clear_block(graph, block) next = [] changed = False for num, op in enumerate(block.operations): @@ -78,6 +77,13 @@ del bk.listdefs[(graph, block, num)] bk.listdefs[(graph, block, len(next))] = listdef next.append(op) + elif op.opname == 'newdict': + # move listdef position key + bk = self.bookkeeper + dictdef = bk.dictdefs[(graph, block, num)] + del bk.dictdefs[(graph, block, num)] + bk.dictdefs[(graph, block, len(next))] = dictdef + next.append(op) else: next.append(op) block.operations = next Modified: pypy/dist/pypy/translator/transformer/test/test_debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_debug.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_debug.py Sat Sep 9 11:51:32 2006 @@ -14,7 +14,7 @@ from pypy.translator.unsimplify import copyvar import py -py.test.skip("llinterp does not like my transformations") +#py.test.skip("llinterp does not like my transformations") def g(): pass @@ -56,7 +56,7 @@ assert len(real_res) == 3 def test_debug_double_raising(): - py.test.skip("strange llinterp stuff") + py.test.skip("llinterp does not like my graph transformations") def aaa(i): if i: raise TypeError() From arigo at codespeak.net Sat Sep 9 14:10:24 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Sep 2006 14:10:24 +0200 (CEST) Subject: [pypy-svn] r32106 - in pypy/dist/pypy/jit/codegen/i386: . test Message-ID: <20060909121024.0300610050@code0.codespeak.net> Author: arigo Date: Sat Sep 9 14:10:23 2006 New Revision: 32106 Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Log: Some more operations. All "simple" operations listed in the lloperation table are implemented. Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Sat Sep 9 14:10:23 2006 @@ -29,6 +29,9 @@ def operand(self, builder): return builder.stack_access(self.stackpos) + def nonimmoperand(self, builder, tmpregister): + return self.operand(builder) + def __repr__(self): return 'var@%d' % (self.stackpos,) @@ -66,6 +69,10 @@ def operand(self, builder): return imm(self.value) + def nonimmoperand(self, builder, tmpregister): + builder.mc.MOV(tmpregister, self.operand(builder)) + return tmpregister + @specialize.arg(1) def revealconst(self, T): if isinstance(T, lltype.Ptr): @@ -96,6 +103,10 @@ def operand(self, builder): return imm(llmemory.cast_adr_to_int(self.addr)) + def nonimmoperand(self, builder, tmpregister): + builder.mc.MOV(tmpregister, self.operand(builder)) + return tmpregister + @specialize.arg(1) def revealconst(self, T): if T is llmemory.Address: @@ -246,6 +257,9 @@ else: return gv_x + def genop_debug_pdb(self): # may take an args_gv later + self.mc.BREAKPOINT() + def enter_next_block(self, kinds, args_gv): arg_positions = [] seen = {} @@ -323,10 +337,15 @@ def op_int_floordiv(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.CDQ() - self.mc.MOV(ecx, gv_y.operand(self)) - self.mc.IDIV(ecx) + self.mc.IDIV(gv_y.nonimmoperand(self, ecx)) return self.returnvar(eax) + def op_int_mod(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.CDQ() + self.mc.IDIV(gv_y.nonimmoperand(self, ecx)) + return self.returnvar(edx) + def op_int_and(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.AND(eax, gv_y.operand(self)) @@ -389,6 +408,16 @@ self.mc.NEG(eax) return self.returnvar(eax) + def op_int_abs(self, gv_x): + self.mc.MOV(eax, gv_x.operand(self)) + # ABS-computing code from Psyco, found by exhaustive search + # on *all* short sequences of operations :-) + self.mc.ADD(eax, eax) + self.mc.SBB(eax, gv_x.operand(self)) + self.mc.SBB(edx, edx) + self.mc.XOR(eax, edx) + return self.returnvar(eax) + def op_int_invert(self, gv_x): self.mc.MOV(eax, gv_x.operand(self)) self.mc.NOT(eax) @@ -403,6 +432,72 @@ def op_int_rshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) self.mc.MOV(ecx, gv_y.operand(self)) + self.mc.SAR(eax, cl) + return self.returnvar(eax) + + op_uint_is_true = op_int_is_true + op_uint_neg = op_int_neg + op_uint_abs = identity + op_uint_invert = op_int_invert + op_uint_add = op_int_add + op_uint_sub = op_int_sub + + def op_uint_mul(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.MUL(gv_y.nonimmoperand(self, edx)) + return self.returnvar(eax) + + def op_uint_floordiv(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.XOR(edx, edx) + self.mc.DIV(gv_y.nonimmoperand(self, ecx)) + return self.returnvar(eax) + + def op_uint_mod(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.XOR(edx, edx) + self.mc.DIV(gv_y.nonimmoperand(self, ecx)) + return self.returnvar(edx) + + def op_uint_lt(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.CMP(eax, gv_y.operand(self)) + self.mc.SETB(al) + self.mc.MOVZX(eax, al) + return self.returnvar(eax) + + def op_uint_le(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.CMP(eax, gv_y.operand(self)) + self.mc.SETBE(al) + self.mc.MOVZX(eax, al) + return self.returnvar(eax) + + op_uint_eq = op_int_eq + op_uint_ne = op_int_ne + + def op_uint_gt(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.CMP(eax, gv_y.operand(self)) + self.mc.SETA(al) + self.mc.MOVZX(eax, al) + return self.returnvar(eax) + + def op_uint_ge(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.CMP(eax, gv_y.operand(self)) + self.mc.SETAE(al) + self.mc.MOVZX(eax, al) + return self.returnvar(eax) + + op_uint_and = op_int_and + op_uint_or = op_int_or + op_uint_xor = op_int_xor + op_uint_lshift = op_int_lshift + + def op_uint_rshift(self, gv_x, gv_y): + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.MOV(ecx, gv_y.operand(self)) self.mc.SHR(eax, cl) return self.returnvar(eax) @@ -418,11 +513,31 @@ self.mc.MOVZX(eax, al) return self.returnvar(eax) - op_cast_char_to_int = identity + op_cast_bool_to_uint = op_cast_bool_to_int + + op_cast_char_to_int = identity op_cast_unichar_to_int = identity + op_cast_int_to_char = identity + op_cast_int_to_unichar = identity + op_cast_int_to_uint = identity + op_cast_uint_to_int = identity + op_cast_ptr_to_int = identity + op_cast_int_to_ptr = identity + + op_char_lt = op_int_lt + op_char_le = op_int_le + op_char_eq = op_int_eq + op_char_ne = op_int_ne + op_char_gt = op_int_gt + op_char_ge = op_int_ge + + op_unichar_eq = op_int_eq + op_unichar_ne = op_int_ne op_ptr_nonzero = op_int_is_true op_ptr_iszero = op_bool_not # for now + op_ptr_eq = op_int_eq + op_ptr_ne = op_int_ne SIZE2SHIFT = {1: 0, Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Sat Sep 9 14:10:23 2006 @@ -56,6 +56,7 @@ lambda x, y: x - y, lambda x, y: x * y, lambda x, y: x // y, + lambda x, y: x % y, lambda x, y: x << y, lambda x, y: x >> y, lambda x, y: x ^ y, @@ -63,9 +64,12 @@ lambda x, y: x | y, lambda x, y: -y, lambda x, y: ~y, + lambda x, y: abs(y), + lambda x, y: abs(-x), ]: fp = self.rgen(fn, [int, int]) assert fp(40, 2) == fn(40, 2) + assert fp(25, 3) == fn(25, 3) def test_comparison(self): for fn in [lambda x, y: int(x < y), @@ -73,7 +77,7 @@ lambda x, y: int(x == y), lambda x, y: int(x != y), lambda x, y: int(x > y), - lambda x, y: int(x >= y) + lambda x, y: int(x >= y), ]: fp = self.rgen(fn, [int, int]) assert fp(12, 11) == fn(12, 11) @@ -89,6 +93,46 @@ assert fp(-12, -12) == fn(-12, -12) assert fp(-12, -13) == fn(-12, -13) + def test_char_comparison(self): + for fn in [lambda x, y: int(chr(x) < chr(y)), + lambda x, y: int(chr(x) <= chr(y)), + lambda x, y: int(chr(x) == chr(y)), + lambda x, y: int(chr(x) != chr(y)), + lambda x, y: int(chr(x) > chr(y)), + lambda x, y: int(chr(x) >= chr(y)), + ]: + fp = self.rgen(fn, [int, int]) + assert fp(12, 11) == fn(12, 11) + assert fp(12, 12) == fn(12, 12) + assert fp(12, 13) == fn(12, 13) + assert fp(182, 11) == fn(182, 11) + assert fp(182, 12) == fn(182, 12) + assert fp(182, 13) == fn(182, 13) + assert fp(12, 181) == fn(12, 181) + assert fp(12, 182) == fn(12, 182) + assert fp(12, 183) == fn(12, 183) + assert fp(182, 181) == fn(182, 181) + assert fp(182, 182) == fn(182, 182) + assert fp(182, 183) == fn(182, 183) + + def test_unichar_comparison(self): + for fn in [lambda x, y: int(unichr(x) == unichr(y)), + lambda x, y: int(unichr(x) != unichr(y)), + ]: + fp = self.rgen(fn, [int, int]) + assert fp(12, 11) == fn(12, 11) + assert fp(12, 12) == fn(12, 12) + assert fp(12, 13) == fn(12, 13) + assert fp(53182, 11) == fn(53182, 11) + assert fp(53182, 12) == fn(53182, 12) + assert fp(53182, 13) == fn(53182, 13) + assert fp(12, 53181) == fn(12, 53181) + assert fp(12, 53182) == fn(12, 53182) + assert fp(12, 53183) == fn(12, 53183) + assert fp(53182, 53181) == fn(53182, 53181) + assert fp(53182, 53182) == fn(53182, 53182) + assert fp(53182, 53183) == fn(53182, 53183) + def test_char_array(self): A = lltype.GcArray(lltype.Char) def fn(n): From fijal at codespeak.net Sat Sep 9 15:48:18 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 9 Sep 2006 15:48:18 +0200 (CEST) Subject: [pypy-svn] r32107 - in pypy/dist/pypy/translator/transformer: . test Message-ID: <20060909134818.F20A41007D@code0.codespeak.net> Author: fijal Date: Sat Sep 9 15:48:16 2006 New Revision: 32107 Modified: pypy/dist/pypy/translator/transformer/basictransform.py pypy/dist/pypy/translator/transformer/debug.py pypy/dist/pypy/translator/transformer/test/test_basictransform.py pypy/dist/pypy/translator/transformer/test/test_debug.py Log: (fijal, arigo) - Fixed transformation not to reflow the graph, but instead to perform flowing by hand. This allows to keep dictionaries unchanged by just not using it. Modified: pypy/dist/pypy/translator/transformer/basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/basictransform.py Sat Sep 9 15:48:16 2006 @@ -22,7 +22,7 @@ self.annotator = translator.annotator self.bookkeeper = self.annotator.bookkeeper - def genop(self, name, args): + def genop(self, name, args, retval_example=None): """ Pass here (example, is_constant) list as args, you'll get retval """ @@ -39,11 +39,26 @@ if is_constant: real_args.append(model.Constant(arg_example, concretetype=bk.immutablevalue(arg_example))) else: - real_args.append(model.Variable(bk.annotation_from_example(arg_example))) + v = model.Variable() + v.concretetype = bk.annotation_from_example(arg_example) + real_args.append(v) + retval = model.Variable() + if isinstance(retval_example, annmodel.SomeObject): + retval.concretetype = retval_example + elif retval_example is not None: + retval.concretetype = bk.annotation_from_example(retval_example) + else: + retval.concretetype = annmodel.s_ImpossibleValue return model.SpaceOperation(name, real_args, retval), retval + def add_bindings(self, vars): + bindings = self.annotator.bindings + for v in vars: + bindings[v] = v.concretetype + def add_block(self, graph, block): + assert False #assert self.annotator.annotated[block] try: self.annotator.reflowpendingblock(graph, block) @@ -61,11 +76,12 @@ return graph def transform_all(self): + self.annotator.simplify() bk = self.translator.annotator.bookkeeper for graph in self.translator.graphs: self.transform_graph(graph) checkgraph(graph) - self.translator.annotator.complete() + #self.translator.annotator.complete() def get_const(self, arg): bk = self.bookkeeper Modified: pypy/dist/pypy/translator/transformer/debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/debug.py (original) +++ pypy/dist/pypy/translator/transformer/debug.py Sat Sep 9 15:48:16 2006 @@ -52,43 +52,53 @@ def transform_block(self, graph, block): next = [] - changed = False + ann = self.annotator + classdef = self.instance_const.concretetype.classdef for num, op in enumerate(block.operations): # XXX: We need to support indirect calls as well, but # just need to do it somehow differently - if op.opname == 'simple_call' and \ + if op.opname == 'simple_call' and\ isinstance(op.args[0], model.Constant) and \ isinstance(op.args[0].value, (FunctionType, MethodType)): # XXX or any other call - opg, v1 = self.genop("getattr", [self.instance_const, 'enter']) + retval = classdef.find_attribute('enter').s_value + retval = classdef.lookup_filter(retval) + opg, v1 = self.genop("getattr", [self.instance_const, 'enter'], + retval) fun_name = op.args[0].value.func_name data, filename, lineno = self.get_info(block, graph, op) opc, v2 = self.genop("simple_call", [v1, fun_name, data, \ filename, lineno]) - opgl, v3 = self.genop("getattr", [self.instance_const, 'leave']) + retval = classdef.find_attribute('leave').s_value + retval = classdef.lookup_filter(retval) + opgl, v3 = self.genop("getattr", [self.instance_const, 'leave'], + retval) oplc, v4 = self.genop("simple_call", [v3, fun_name]) next += [opg, opc, op, opgl, oplc] changed = True + # add to annotator + self.add_bindings([v1, v2, v3, v4]) + #ann.bindings[v2] = #next.append(op) - elif op.opname == 'newlist': - # move listdef position key - bk = self.bookkeeper - listdef = bk.listdefs[(graph, block, num)] - del bk.listdefs[(graph, block, num)] - bk.listdefs[(graph, block, len(next))] = listdef - next.append(op) - elif op.opname == 'newdict': - # move listdef position key - bk = self.bookkeeper - dictdef = bk.dictdefs[(graph, block, num)] - del bk.dictdefs[(graph, block, num)] - bk.dictdefs[(graph, block, len(next))] = dictdef - next.append(op) +## elif op.opname == 'newlist': +## # move listdef position key +## bk = self.bookkeeper +## listdef = bk.listdefs[(graph, block, num)] +## del bk.listdefs[(graph, block, num)] +## bk.listdefs[(graph, block, len(next))] = listdef +## next.append(op) +## elif op.opname == 'newdict': +## # move listdef position key +## bk = self.bookkeeper +## dictdef = bk.dictdefs[(graph, block, num)] +## del bk.dictdefs[(graph, block, num)] +## bk.dictdefs[(graph, block, len(next))] = dictdef +## next.append(op) else: next.append(op) block.operations = next - if changed: - self.add_block(graph, block) +# if changed: +# self.add_block(graph, block) def get_info(self, block, graph, op): """ Returns as much data as we can from our position Modified: pypy/dist/pypy/translator/transformer/test/test_basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_basictransform.py Sat Sep 9 15:48:16 2006 @@ -10,6 +10,9 @@ from pypy.translator.unsimplify import copyvar from pypy.rpython.nonconst import NonConstant +import py +py.test.skip("Needs refactoring") + def transform_function(transformerclass, fun, annotation=[], specialize=True, type_system="ootype"): t = TranslationContext() Modified: pypy/dist/pypy/translator/transformer/test/test_debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_debug.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_debug.py Sat Sep 9 15:48:16 2006 @@ -14,7 +14,7 @@ from pypy.translator.unsimplify import copyvar import py -#py.test.skip("llinterp does not like my transformations") +py.test.skip("llinterp does not like my transformations") def g(): pass @@ -46,7 +46,7 @@ def wrapper(): try: c() - except: + except Exception: pass return traceback_handler.tb @@ -56,7 +56,7 @@ assert len(real_res) == 3 def test_debug_double_raising(): - py.test.skip("llinterp does not like my graph transformations") + #py.test.skip("llinterp does not like my graph transformations") def aaa(i): if i: raise TypeError() From arigo at codespeak.net Sun Sep 10 14:07:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Sep 2006 14:07:28 +0200 (CEST) Subject: [pypy-svn] r32119 - in pypy/dist/pypy/jit: hintannotator hintannotator/test tl Message-ID: <20060910120728.6A53E10071@code0.codespeak.net> Author: arigo Date: Sun Sep 10 14:07:26 2006 New Revision: 32119 Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py pypy/dist/pypy/jit/tl/tlr.py Log: (pedronis, arigo) Add a form of propagation of green variables, for the cases that don't make merge points fail to unify in the timeshifted graphs because of it. XXX needs tons of comments in the source code to explain *how* it does this. Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Sun Sep 10 14:07:26 2006 @@ -85,7 +85,12 @@ origin = self.originflags[self.position_key] except KeyError: from pypy.jit.hintannotator import model as hintmodel - origin = hintmodel.OriginFlags() + if len(self.position_key) == 3: + graph, block, i = self.position_key + spaceop = block.operations[i] + else: + spaceop = None + origin = hintmodel.OriginFlags(self, spaceop) self.originflags[self.position_key] = origin return origin Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Sun Sep 10 14:07:26 2006 @@ -32,6 +32,10 @@ fixed = False read_positions = None + def __init__(self, bookkeeper=None, spaceop=None): + self.bookkeeper = bookkeeper + self.spaceop = spaceop + def __repr__(self): if self.fixed: s = "fixed " @@ -53,6 +57,58 @@ for p in self.read_positions: annotator.reflowfromposition(p) + def greenargs(self, frame=None): + annotator = self.bookkeeper.annotator + if frame is None: + frame = GreenHandlerFrame(annotator) + if self.spaceop.opname == 'direct_call': # ah haa + return frame.greencallresult(self.spaceop) + else: + for v in self.spaceop.args: + if not frame.greenvar(v): + return False + return True + + +class GreenHandlerFrame(object): + + def __init__(self, annotator, parentframe=None): + self.annotator = annotator + self.parentframe = parentframe + self.inputarg2actualarg = {} # {origin: annotation} + + def greenvar(self, v): + hs = self.annotator.binding(v) + if isinstance(hs, SomeLLAbstractConstant) and len(hs.origins) == 1: + [o] = hs.origins.keys() + if o in self.inputarg2actualarg: + hs_actual = self.inputarg2actualarg[o] + return hs_actual.is_green(self.parentframe) + return hs.is_green(self) + + def greencallresult(self, spaceop): +## print spaceop +## if str(spaceop.result) == 'v58': +## import pdb; pdb.set_trace() + args_hs = [self.annotator.binding(v) for v in spaceop.args] + hs_result = self.annotator.binding(spaceop.result) + hs_f1 = args_hs.pop(0) + fnobj = hs_f1.const._obj + input_args_hs = list(args_hs) + bk = self.annotator.bookkeeper + graph = bk.get_graph_for_call(fnobj.graph, + hs_result.is_fixed(), + input_args_hs) + newframe = GreenHandlerFrame(self.annotator, parentframe=self) + for hs_inp_arg, hs_arg in zip(input_args_hs, args_hs): + if isinstance(hs_arg, SomeLLAbstractConstant): + assert len(hs_inp_arg.origins) == 1 + [o] = hs_inp_arg.origins.keys() + newframe.inputarg2actualarg[o] = hs_arg + return newframe.greenvar(graph.getreturnvar()) + +# ____________________________________________________________ + class SomeLLAbstractValue(annmodel.SomeObject): @@ -60,13 +116,18 @@ self.concretetype = T assert self.__class__ != SomeLLAbstractValue + def is_green(self, frame=None): + return False + class SomeLLAbstractConstant(SomeLLAbstractValue): - def __init__(self, T, origins, eager_concrete=False): + def __init__(self, T, origins, eager_concrete=False, myorigin=None): SomeLLAbstractValue.__init__(self, T) self.origins = origins self.eager_concrete = eager_concrete + self.myorigin = myorigin + assert myorigin is None or myorigin.spaceop is not None def fmt_origins(self, origins): counts = {} @@ -84,19 +145,31 @@ lst.append(s) return '<%s>' % (', '.join(lst),) + def fmt_myorigin(self, myorigin): + if myorigin is None: + return None + else: + return str(myorigin.spaceop.result) + def is_fixed(self): for o in self.origins: if not o.fixed: return False return True + def is_green(self, frame=None): + return (self.is_fixed() or self.eager_concrete or + self.concretetype is lltype.Void or + (self.myorigin is not None and + self.myorigin.greenargs(frame))) + def annotationcolor(self): """Compute the color of the variables with this annotation for the pygame viewer """ if self.eager_concrete: return (0,100,0) # green - elif self.is_fixed(): + elif self.is_green(): return (50,140,0) # green-dark-cyan else: return None @@ -260,6 +333,7 @@ if fixed: deps_hs.append(hs_res) hs_res = reorigin(hs_res, *deps_hs) + hs_res.myorigin = bookkeeper.myorigin() # we need to make sure that hs_res does not become temporarily less # general as a result of calling another specialized version of the @@ -270,16 +344,20 @@ S = hs_c1.concretetype.TO FIELD_TYPE = getattr(S, hs_fieldname.const) if S._hints.get('immutable', False): - d = setadd(hs_c1.origins, getbookkeeper().myorigin()) - return SomeLLAbstractConstant(FIELD_TYPE, d) + origin = getbookkeeper().myorigin() + d = setadd(hs_c1.origins, origin) + return SomeLLAbstractConstant(FIELD_TYPE, d, + eager_concrete=hs_c1.eager_concrete, + myorigin=origin) else: return SomeLLAbstractVariable(FIELD_TYPE) def getsubstruct(hs_c1, hs_fieldname): S = hs_c1.concretetype.TO SUB_TYPE = getattr(S, hs_fieldname.const) - d = setadd(hs_c1.origins, getbookkeeper().myorigin()) - return SomeLLAbstractConstant(lltype.Ptr(SUB_TYPE), d) + origin = getbookkeeper().myorigin() + d = setadd(hs_c1.origins, origin) + return SomeLLAbstractConstant(lltype.Ptr(SUB_TYPE), d, myorigin=origin) class __extend__(SomeLLAbstractContainer): @@ -338,15 +416,24 @@ def union((hs_c1, hs_c2)): assert hs_c1.concretetype == hs_c2.concretetype d = newset(hs_c1.origins, hs_c2.origins) - return SomeLLAbstractConstant(hs_c1.concretetype, d, eager_concrete=hs_c1.eager_concrete and hs_c2.eager_concrete) + if hs_c1.myorigin is hs_c2.myorigin: + myorigin = hs_c1.myorigin + else: + myorigin = None + return SomeLLAbstractConstant(hs_c1.concretetype, d, + eager_concrete = hs_c1.eager_concrete and + hs_c2.eager_concrete, + myorigin = myorigin) def getarrayitem((hs_c1, hs_index)): A = hs_c1.concretetype.TO READ_TYPE = A.OF if A._hints.get('immutable', False): - d = newset(hs_c1.origins, hs_index.origins, - {getbookkeeper().myorigin(): True}) - return SomeLLAbstractConstant(READ_TYPE, d, eager_concrete=hs_c1.eager_concrete) + origin = getbookkeeper().myorigin() + d = newset(hs_c1.origins, hs_index.origins, {origin: True}) + return SomeLLAbstractConstant(READ_TYPE, d, + eager_concrete=hs_c1.eager_concrete, + myorigin=origin) else: return SomeLLAbstractVariable(READ_TYPE) @@ -452,18 +539,22 @@ def const_unary(hs_c1): bk = getbookkeeper() - d = setadd(hs_c1.origins, bk.myorigin()) + origin = bk.myorigin() + d = setadd(hs_c1.origins, origin) RESTYPE = bk.current_op_concretetype() return SomeLLAbstractConstant(RESTYPE, d, - eager_concrete = hs_c1.eager_concrete) + eager_concrete = hs_c1.eager_concrete, + myorigin = origin) def const_binary((hs_c1, hs_c2)): bk = getbookkeeper() - d = newset(hs_c1.origins, hs_c2.origins, {bk.myorigin(): True}) + origin = bk.myorigin() + d = newset(hs_c1.origins, hs_c2.origins, {origin: True}) RESTYPE = bk.current_op_concretetype() return SomeLLAbstractConstant(RESTYPE, d, eager_concrete = hs_c1.eager_concrete or - hs_c2.eager_concrete) + hs_c2.eager_concrete, + myorigin = origin) def setup(oplist, ValueCls, var_fn, ConstantCls, const_fn): for name in oplist: Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Sun Sep 10 14:07:26 2006 @@ -6,6 +6,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.objectmodel import hint from pypy.annotation import model as annmodel +from pypy.objspace.flow import model as flowmodel from pypy.annotation.policy import AnnotatorPolicy from pypy.translator.backendopt.inline import auto_inlining from pypy import conftest @@ -145,7 +146,10 @@ def test_op_meet(): def meet(hs1, hs2): bk = HintBookkeeper(None) - bk.enter(None) + block = flowmodel.Block([]) + block.operations.append(flowmodel.SpaceOperation('x', [], + flowmodel.Variable())) + bk.enter(("graph", block, 0)) bk.current_op_concretetype = lambda: lltype.Signed # hack return pair(hs1, hs2).int_add() av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed) @@ -439,6 +443,10 @@ from pypy.jit.tl import tl hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL) +def test_hannotate_tlr_novirtual(): + from pypy.jit.tl import tlr + hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL) + def test_hannotate_plus_minus(): def ll_plus_minus(s, x, y): acc = x @@ -519,3 +527,15 @@ hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL) assert isinstance(hs, SomeLLAbstractConstant) assert hs.concretetype == lltype.Signed + + +def test_more_green(): + def f(x): + z = x + 1 + x2 = hint(x, concrete=True) + return z + + hs = hannotate(f, [int]) + assert isinstance(hs, SomeLLAbstractConstant) + assert hs.is_green() + assert not hs.is_fixed() Modified: pypy/dist/pypy/jit/tl/tlr.py ============================================================================== --- pypy/dist/pypy/jit/tl/tlr.py (original) +++ pypy/dist/pypy/jit/tl/tlr.py Sun Sep 10 14:07:26 2006 @@ -19,11 +19,11 @@ opcode = hint(ord(bytecode[pc]), concrete=True) pc += 1 if opcode == MOV_A_R: - n = ord(bytecode[pc]); hint(n, concrete=True) + n = ord(bytecode[pc]) pc += 1 regs[n] = a elif opcode == MOV_R_A: - n = ord(bytecode[pc]); hint(n, concrete=True) + n = ord(bytecode[pc]) pc += 1 a = regs[n] elif opcode == JUMP_IF_A: @@ -32,16 +32,16 @@ if a: pc = target elif opcode == SET_A: - a = ord(bytecode[pc]); hint(a, concrete=True) + a = ord(bytecode[pc]) pc += 1 elif opcode == ADD_R_TO_A: - n = ord(bytecode[pc]); hint(n, concrete=True) + n = ord(bytecode[pc]) pc += 1 a += regs[n] elif opcode == RETURN_A: return a elif opcode == ALLOCATE: - n = ord(bytecode[pc]); hint(n, concrete=True) + n = ord(bytecode[pc]) pc += 1 regs = [0] * n elif opcode == NEG_A: From mwh at codespeak.net Sun Sep 10 15:01:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 10 Sep 2006 15:01:47 +0200 (CEST) Subject: [pypy-svn] r32120 - in pypy/branch/more-gckinds/pypy/rpython: . lltypesystem test Message-ID: <20060910130147.D5BD910071@code0.codespeak.net> Author: mwh Date: Sun Sep 10 15:01:46 2006 New Revision: 32120 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/rptr.py pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Log: make a test that involves a non-trivial-at-runtime interior pointer pass. some refactoring will be needed. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Sun Sep 10 15:01:46 2006 @@ -619,6 +619,11 @@ o = self.TO._container_example() return _ptr(self, o, solid=True) + def _interior_ptr_type_with_index(self): + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}) + return R + class InteriorPtr(LowLevelType): def __init__(self, PARENTTYPE, TO, offsets): self.PARENTTYPE = PARENTTYPE Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Sun Sep 10 15:01:46 2006 @@ -22,7 +22,10 @@ class __extend__(annmodel.SomeInteriorPtr): def rtyper_makerepr(self, rtyper): - return InteriorPtrRepr(self.ll_ptrtype) + for offset in self.ll_ptrtype.offsets: + if isinstance(offset, int): + return InteriorPtrRepr(self.ll_ptrtype) + return FieldOnlyInteriorPtrRepr(self.ll_ptrtype) class PtrRepr(Repr): @@ -100,7 +103,18 @@ ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, ContainerType): - newopname = 'getarraysubstruct' + if ARRAY._gckind == 'gc' and ITEM_TYPE._gckind == 'raw': + v_array, v_index = hop.inputargs(r_ptr, Signed) + INTERIOR_PTR_TYPE = Ptr(ARRAY)._interior_ptr_type_with_index() + v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], + resulttype = Ptr(INTERIOR_PTR_TYPE)) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('ptr', Void), v_array]) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('index', Void), v_index]) + return v_interior_ptr + else: + newopname = 'getarraysubstruct' else: newopname = 'getarrayitem' vlist = hop.inputargs(r_ptr, Signed) @@ -188,14 +202,13 @@ return v return NotImplemented -class InteriorPtrRepr(Repr): +class FieldOnlyInteriorPtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, InteriorPtr) - assert len(ptrtype.offsets) == 1 - offset, = ptrtype.offsets - assert isinstance(offset, str) + for offset in ptrtype.offsets: + assert isinstance(offset, str) self.lowleveltype = Ptr(ptrtype.PARENTTYPE) - self.v_offsets = [flowmodel.Constant(offset, Void)] + self.v_offsets = [flowmodel.Constant(offset, Void) for offset in ptrtype.offsets] self.resulttype = Ptr(ptrtype.TO) def rtype_getattr(self, hop): @@ -203,7 +216,7 @@ vlist.append(hop.inputarg(Void, 1)) return hop.genop('getinteriorfield', vlist, resulttype=hop.r_result.lowleveltype) - + def rtype_setattr(self, hop): vlist = [hop.inputarg(hop.args_r[0], 0)] + self.v_offsets vlist.append(hop.inputarg(Void, 1)) @@ -211,3 +224,36 @@ return hop.genop('setinteriorfield', vlist, resulttype=hop.r_result.lowleveltype) + +class InteriorPtrRepr(Repr): + def __init__(self, ptrtype): + assert isinstance(ptrtype, InteriorPtr) + assert len(ptrtype.offsets) == 1, "for now" + numitemoffsets = 0 + for offset in ptrtype.offsets: + if isinstance(offset, int): + numitemoffsets += 1 + assert numitemoffsets == 1 + self.parentptrtype = Ptr(ptrtype.PARENTTYPE) + self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index()) + self.resulttype = Ptr(ptrtype.TO) + assert not isinstance(self.resulttype, ContainerType) + + def rtype_getattr(self, hop): + v_interior_ptr, v_fieldname = hop.inputargs(self, Void) + v_ptr = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('ptr', Void)], + resulttype=self.parentptrtype) + v_offset = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('index', Void)], + resulttype=Signed) + return hop.genop('getinteriorfield', [v_ptr, v_offset, v_fieldname], + resulttype=hop.r_result.lowleveltype) + + def rtype_setattr(self, hop): + v_interior_ptr, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2]) + v_ptr = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('ptr', Void)], + resulttype=self.parentptrtype) + v_offset = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('index', Void)], + resulttype=Signed) + return hop.genop('setinteriorfield', [v_ptr, v_offset, v_fieldname, v_value], + resulttype=hop.r_result.lowleveltype) + Modified: pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Sun Sep 10 15:01:46 2006 @@ -217,3 +217,15 @@ return t.s.x res = interpret(f, []) assert res == 1 + +def test_interior_ptr_with_offset(): + S = Struct("S", ('x', Signed)) + T = GcArray(S) + def g(s): + s.x = 1 + def f(): + t = malloc(T, 1) + g(t[0]) + return t[0].x + res = interpret(f, []) + assert res == 1 From arigo at codespeak.net Sun Sep 10 15:37:12 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Sep 2006 15:37:12 +0200 (CEST) Subject: [pypy-svn] r32121 - in pypy/dist/pypy/jit/codegen/i386: . test Message-ID: <20060910133712.1B46610071@code0.codespeak.net> Author: arigo Date: Sun Sep 10 15:37:10 2006 New Revision: 32121 Modified: pypy/dist/pypy/jit/codegen/i386/ri386.py pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: (pedronis, arigo) Fix test_auto_encoding failures. Skip tests relying on Boehm when they don't run in the main thread (as with distributed testing). Modified: pypy/dist/pypy/jit/codegen/i386/ri386.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386.py Sun Sep 10 15:37:10 2006 @@ -33,21 +33,27 @@ class BH(REG8): op=7 class IMM32(OPERAND): + width = 4 + def __init__(self, value): self.value = value def assembler(self): return '$%d' % (self.value,) class IMM8(IMM32): - pass + width = 1 class IMM16(OPERAND): # only for RET + width = 2 + def __init__(self, value): self.value = value def assembler(self): return '$%d' % (self.value,) class MODRM(OPERAND): + width = 4 + def __init__(self, byte, extradata): self.byte = byte self.extradata = extradata @@ -97,9 +103,10 @@ class MODRM8(MODRM): - pass + width = 1 class REL32(OPERAND): + width = 4 def __init__(self, absolute_target): self.absolute_target = absolute_target def assembler(self): Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Sun Sep 10 15:37:10 2006 @@ -558,6 +558,10 @@ return lltype.cast_ptr_to_int(gc_malloc_ptr) else: # don't do this at home + import threading + if not isinstance(threading.currentThread(), threading._MainThread): + import py + py.test.skip("must run in the main thread") try: from ctypes import cast, c_void_p from pypy.rpython.rctypes.tool import util Modified: pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Sun Sep 10 15:37:10 2006 @@ -205,6 +205,11 @@ if instrname in ('SHL', 'SHR', 'SAR'): if args[1][1].assembler() == '$1': return [] + if instrname in ('MOVZX', 'MOVSX'): + if args[1][1].width == 4: + return [] + if instrname == 'o16': + return [] return [args] def hexdump(s): From mwh at codespeak.net Sun Sep 10 16:44:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 10 Sep 2006 16:44:47 +0200 (CEST) Subject: [pypy-svn] r32124 - pypy/branch/more-gckinds/pypy/rpython Message-ID: <20060910144447.A7B7010070@code0.codespeak.net> Author: mwh Date: Sun Sep 10 16:44:46 2006 New Revision: 32124 Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py Log: more baby steps Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Sun Sep 10 16:44:46 2006 @@ -226,6 +226,10 @@ return hop.genop('setinteriorfield', vlist, resulttype=hop.r_result.lowleveltype) +## class __extend__(FieldOnlyInteriorPtrRepr, IntegerRepr): +## def rtype_getitem((r_ptr, r_item), hop): +## pass + class InteriorPtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, InteriorPtr) @@ -240,21 +244,25 @@ self.resulttype = Ptr(ptrtype.TO) assert not isinstance(self.resulttype, ContainerType) + def getinteriorfieldargs(self, hop, v_interior_ptr): + vlist = [] + INTERIOR_TYPE = v_interior_ptr.concretetype.TO + for name in INTERIOR_TYPE._names: + vlist.append( + hop.genop('getfield', + [v_interior_ptr, flowmodel.Constant(name, Void)], + resulttype=INTERIOR_TYPE._flds[name])) + return vlist + def rtype_getattr(self, hop): v_interior_ptr, v_fieldname = hop.inputargs(self, Void) - v_ptr = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('ptr', Void)], - resulttype=self.parentptrtype) - v_offset = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('index', Void)], - resulttype=Signed) - return hop.genop('getinteriorfield', [v_ptr, v_offset, v_fieldname], + vlist = self.getinteriorfieldargs(hop, v_interior_ptr) + return hop.genop('getinteriorfield', vlist + [v_fieldname], resulttype=hop.r_result.lowleveltype) def rtype_setattr(self, hop): v_interior_ptr, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2]) - v_ptr = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('ptr', Void)], - resulttype=self.parentptrtype) - v_offset = hop.genop('getfield', [v_interior_ptr, flowmodel.Constant('index', Void)], - resulttype=Signed) - return hop.genop('setinteriorfield', [v_ptr, v_offset, v_fieldname, v_value], + vlist = self.getinteriorfieldargs(hop, v_interior_ptr) + return hop.genop('setinteriorfield', vlist + [v_fieldname, v_value], resulttype=hop.r_result.lowleveltype) From mwh at codespeak.net Sun Sep 10 18:20:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 10 Sep 2006 18:20:32 +0200 (CEST) Subject: [pypy-svn] r32125 - in pypy/branch/more-gckinds/pypy/rpython: . lltypesystem test Message-ID: <20060910162032.494C910070@code0.codespeak.net> Author: mwh Date: Sun Sep 10 18:20:30 2006 New Revision: 32125 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/rptr.py pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Log: progress. get rid of the FieldOnlyInteriorPtrRepr/InteriorPtrRepr distinction, it doesn't really help much. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Sun Sep 10 18:20:30 2006 @@ -620,6 +620,7 @@ return _ptr(self, o, solid=True) def _interior_ptr_type_with_index(self): + assert self.TO._gckind == 'gc' R = GcStruct("Interior", ('ptr', self), ('index', Signed), hints={'interior_ptr_type':True}) return R Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Sun Sep 10 18:20:30 2006 @@ -22,10 +22,7 @@ class __extend__(annmodel.SomeInteriorPtr): def rtyper_makerepr(self, rtyper): - for offset in self.ll_ptrtype.offsets: - if isinstance(offset, int): - return InteriorPtrRepr(self.ll_ptrtype) - return FieldOnlyInteriorPtrRepr(self.ll_ptrtype) + return InteriorPtrRepr(self.ll_ptrtype) class PtrRepr(Repr): @@ -40,7 +37,7 @@ FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): if self.lowleveltype.TO._gckind == 'gc' and FIELD_TYPE._gckind == 'raw': - return hop.genop('same_as', [hop.inputarg(hop.args_r[0], 0)], + return hop.genop('same_as', [hop.inputarg(self, 0)], resulttype=self.lowleveltype) else: newopname = 'getsubstruct' @@ -106,7 +103,7 @@ if isinstance(ITEM_TYPE, ContainerType): if ARRAY._gckind == 'gc' and ITEM_TYPE._gckind == 'raw': v_array, v_index = hop.inputargs(r_ptr, Signed) - INTERIOR_PTR_TYPE = Ptr(ARRAY)._interior_ptr_type_with_index() + INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index() v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], resulttype = Ptr(INTERIOR_PTR_TYPE)) hop.genop('setfield', @@ -203,66 +200,100 @@ return v return NotImplemented -class FieldOnlyInteriorPtrRepr(Repr): - def __init__(self, ptrtype): - assert isinstance(ptrtype, InteriorPtr) - for offset in ptrtype.offsets: - assert isinstance(offset, str) - self.lowleveltype = Ptr(ptrtype.PARENTTYPE) - self.v_offsets = [flowmodel.Constant(offset, Void) for offset in ptrtype.offsets] - self.resulttype = Ptr(ptrtype.TO) - - def rtype_getattr(self, hop): - vlist = [hop.inputarg(hop.args_r[0], 0)] + self.v_offsets - vlist.append(hop.inputarg(Void, 1)) - return hop.genop('getinteriorfield', vlist, - resulttype=hop.r_result.lowleveltype) - - def rtype_setattr(self, hop): - vlist = [hop.inputarg(hop.args_r[0], 0)] + self.v_offsets - vlist.append(hop.inputarg(Void, 1)) - vlist.append(hop.inputarg(hop.args_r[2], 2)) - - return hop.genop('setinteriorfield', vlist, - resulttype=hop.r_result.lowleveltype) - -## class __extend__(FieldOnlyInteriorPtrRepr, IntegerRepr): -## def rtype_getitem((r_ptr, r_item), hop): -## pass class InteriorPtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, InteriorPtr) - assert len(ptrtype.offsets) == 1, "for now" + self.v_offsets = [] numitemoffsets = 0 - for offset in ptrtype.offsets: + for i, offset in enumerate(ptrtype.offsets): if isinstance(offset, int): numitemoffsets += 1 - assert numitemoffsets == 1 + self.v_offsets.append(None) + else: + assert isinstance(offset, str) + self.v_offsets.append(flowmodel.Constant(offset, Void)) self.parentptrtype = Ptr(ptrtype.PARENTTYPE) - self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index()) self.resulttype = Ptr(ptrtype.TO) - assert not isinstance(self.resulttype, ContainerType) + assert numitemoffsets <= 1 + if numitemoffsets > 0: + self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index()) + else: + self.lowleveltype = self.parentptrtype - def getinteriorfieldargs(self, hop, v_interior_ptr): + def getinteriorfieldargs(self, hop, v_self): vlist = [] - INTERIOR_TYPE = v_interior_ptr.concretetype.TO - for name in INTERIOR_TYPE._names: + if None in self.v_offsets: + INTERIOR_TYPE = v_self.concretetype.TO + nameiter = iter(INTERIOR_TYPE._names) + name = nameiter.next() vlist.append( hop.genop('getfield', - [v_interior_ptr, flowmodel.Constant(name, Void)], + [v_self, flowmodel.Constant(name, Void)], resulttype=INTERIOR_TYPE._flds[name])) + else: + vlist.append(v_self) + for v_offset in self.v_offsets: + if v_offset is None: + name = nameiter.next() + vlist.append( + hop.genop('getfield', + [v_self, flowmodel.Constant(name, Void)], + resulttype=INTERIOR_TYPE._flds[name])) + else: + vlist.append(v_offset) + if None in self.v_offsets: + try: + nameiter.next() + except StopIteration: + pass + else: + assert False return vlist def rtype_getattr(self, hop): - v_interior_ptr, v_fieldname = hop.inputargs(self, Void) - vlist = self.getinteriorfieldargs(hop, v_interior_ptr) - return hop.genop('getinteriorfield', vlist + [v_fieldname], - resulttype=hop.r_result.lowleveltype) + attr = hop.args_s[1].const + if isinstance(hop.s_result, annmodel.SomeLLADTMeth): + return hop.inputarg(hop.r_result, arg=0) + FIELD_TYPE = getattr(self.resulttype.TO, attr) + if isinstance(FIELD_TYPE, ContainerType): + return hop.genop('same_as', [hop.inputarg(self, 0)], + resulttype=self.lowleveltype) + else: + v_self, v_attr = hop.inputargs(self, Void) + vlist = self.getinteriorfieldargs(hop, v_self) + [v_attr] + return hop.genop('getinteriorfield', vlist, + resulttype=hop.r_result.lowleveltype) def rtype_setattr(self, hop): - v_interior_ptr, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2]) - vlist = self.getinteriorfieldargs(hop, v_interior_ptr) - return hop.genop('setinteriorfield', vlist + [v_fieldname, v_value], + attr = hop.args_s[1].const + FIELD_TYPE = getattr(self.resulttype.TO, attr) + assert not isinstance(FIELD_TYPE, ContainerType) + v_self, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2]) + vlist = self.getinteriorfieldargs(hop, v_self) + [v_fieldname, v_value] + return hop.genop('setinteriorfield', vlist, resulttype=hop.r_result.lowleveltype) + + + +class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)): + def rtype_getitem((r_ptr, r_item), hop): + ARRAY = r_ptr.resulttype.TO + ITEM_TYPE = ARRAY.OF + if isinstance(ITEM_TYPE, ContainerType): + v_array, v_index = hop.inputargs(r_ptr, Signed) + INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index() + v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], + resulttype = Ptr(INTERIOR_PTR_TYPE)) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('ptr', Void), v_array]) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('index', Void), v_index]) + return v_interior_ptr + else: + v_self, v_index = hop.inputargs(r_ptr, Signed) + vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index] + return hop.genop('getinteriorfield', vlist, + resulttype=ITEM_TYPE) + Modified: pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Sun Sep 10 18:20:30 2006 @@ -218,7 +218,7 @@ res = interpret(f, []) assert res == 1 -def test_interior_ptr_with_offset(): +def test_interior_ptr_with_index(): S = Struct("S", ('x', Signed)) T = GcArray(S) def g(s): @@ -229,3 +229,28 @@ return t[0].x res = interpret(f, []) assert res == 1 + +def test_interior_ptr_with_field_and_index(): + S = Struct("S", ('x', Signed)) + T = GcStruct("T", ('items', Array(S))) + def g(s): + s.x = 1 + def f(): + t = malloc(T, 1) + g(t.items[0]) + return t.items[0].x + res = interpret(f, []) + assert res == 1 + +def test_interior_ptr_with_index_and_field(): + S = Struct("S", ('x', Signed)) + T = Struct("T", ('s', S)) + U = GcArray(T) + def g(s): + s.x = 1 + def f(): + u = malloc(U, 1) + g(u[0].s) + return u[0].s.x + res = interpret(f, []) + assert res == 1 From pedronis at codespeak.net Sun Sep 10 18:53:33 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Sep 2006 18:53:33 +0200 (CEST) Subject: [pypy-svn] r32127 - pypy/dist/pypy/jit/tl/test Message-ID: <20060910165333.7616B10070@code0.codespeak.net> Author: pedronis Date: Sun Sep 10 18:53:27 2006 New Revision: 32127 Added: pypy/dist/pypy/jit/tl/test/test_tlc.py (contents, props changed) Log: oops, this new test go with the previous check-in. Added: pypy/dist/pypy/jit/tl/test/test_tlc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/tl/test/test_tlc.py Sun Sep 10 18:53:27 2006 @@ -0,0 +1,112 @@ +import py +from pypy.jit.tl.opcode import compile +from pypy.jit.tl.test import test_tl + + +class TestTLC(test_tl.TestTL): + from pypy.jit.tl.tlc import interp + interp = staticmethod(interp) + + def test_basic_cons_cell(self): + bytecode = compile(""" + NIL + PUSHARG + CONS + PUSH 1 + CONS + CDR + CAR + """) + + res = self.interp(bytecode, 0, 42) + assert res == 42 + + def test_nth(self): + bytecode = compile(""" + NIL + PUSH 4 + CONS + PUSH 2 + CONS + PUSH 1 + CONS + PUSHARG + DIV + """) + + res = self.interp(bytecode, 0, 0) + assert res == 1 + res = self.interp(bytecode, 0, 1) + assert res == 2 + res = self.interp(bytecode, 0, 2) + assert res == 4 + + py.test.raises(IndexError, self.interp, bytecode, 0, 3) + + def test_concat(self): + bytecode = compile(""" + NIL + PUSH 4 + CONS + PUSH 2 + CONS + NIL + PUSH 5 + CONS + PUSH 3 + CONS + PUSH 1 + CONS + ADD + PUSHARG + DIV + """) + + for i, n in enumerate([2, 4, 1, 3, 5]): + res = self.interp(bytecode, 0, i) + assert res == n + + def test_concat_errors(self): + bytecode = compile(""" + NIL + PUSH 4 + ADD + """) + py.test.raises(TypeError, self.interp, bytecode, 0, 0) + + bytecode = compile(""" + PUSH 4 + NIL + ADD + """) + py.test.raises(TypeError, self.interp, bytecode, 0, 0) + + + bytecode = compile(""" + NIL + PUSH 1 + CONS + PUSH 4 + ADD + """) + py.test.raises(TypeError, self.interp, bytecode, 0, 0) + + bytecode = compile(""" + PUSH 4 + NIL + PUSH 1 + CONS + ADD + """) + py.test.raises(TypeError, self.interp, bytecode, 0, 0) + + + bytecode = compile(""" + PUSH 2 + PUSH 1 + CONS + NIL + ADD + """) + py.test.raises(TypeError, self.interp, bytecode, 0, 0) + From mwh at codespeak.net Sun Sep 10 19:18:22 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 10 Sep 2006 19:18:22 +0200 (CEST) Subject: [pypy-svn] r32129 - in pypy/branch/more-gckinds/pypy/rpython: . lltypesystem test Message-ID: <20060910171822.F100810070@code0.codespeak.net> Author: mwh Date: Sun Sep 10 19:18:21 2006 New Revision: 32129 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py pypy/branch/more-gckinds/pypy/rpython/rptr.py pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Log: support for len(interior pointer) Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lloperation.py Sun Sep 10 19:18:21 2006 @@ -301,6 +301,7 @@ 'getarraysize': LLOp(canfold=True), 'getsubstruct': LLOp(canfold=True), 'getinteriorfield': LLOp(canfold=True), # XXX not sure about the foldability... + 'getinteriorarraysize': LLOp(canfold=True), 'getarraysubstruct': LLOp(canfold=True), 'setfield': LLOp(), 'setinteriorfield': LLOp(), Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/opimpl.py Sun Sep 10 19:18:21 2006 @@ -133,11 +133,20 @@ if isinstance(o, str): ob = getattr(ob, o) else: - #1/0 ob = ob[o] assert not isinstance(ob, lltype._interior_ptr) return ob +def op_getinteriorarraysize(obj, *offsets): + checkptr(obj) + ob = obj + for o in offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[o] + return len(ob) + def op_getarraysubstruct(array, index): checkptr(array) result = array[index] Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Sun Sep 10 19:18:21 2006 @@ -251,6 +251,12 @@ assert False return vlist + def rtype_len(self, hop): + v_self, = hop.inputargs(self) + vlist = self.getinteriorfieldargs(hop, v_self) + return hop.genop('getinteriorarraysize', vlist, + resulttype=Signed) + def rtype_getattr(self, hop): attr = hop.args_s[1].const if isinstance(hop.s_result, annmodel.SomeLLADTMeth): Modified: pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Sun Sep 10 19:18:21 2006 @@ -254,3 +254,12 @@ return u[0].s.x res = interpret(f, []) assert res == 1 + +def test_interior_ptr_len(): + S = Struct("S", ('x', Signed)) + T = GcStruct("T", ('items', Array(S))) + def f(): + t = malloc(T, 1) + return len(t.items) + res = interpret(f, []) + assert res == 1 From mwh at codespeak.net Mon Sep 11 10:22:48 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 10:22:48 +0200 (CEST) Subject: [pypy-svn] r32135 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem Message-ID: <20060911082248.2DC751007C@code0.codespeak.net> Author: mwh Date: Mon Sep 11 10:22:46 2006 New Revision: 32135 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rdict.py Log: oops Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rdict.py Mon Sep 11 10:22:46 2006 @@ -639,14 +639,14 @@ # methods def ll_get(dict, key, default): - entry = d.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] + entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] if entry.valid(): return entry.value else: return default def ll_setdefault(dict, key, default): - entry = d.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] + entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] if entry.valid(): return entry.value else: From mwh at codespeak.net Mon Sep 11 10:23:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 10:23:47 +0200 (CEST) Subject: [pypy-svn] r32136 - in pypy/branch/more-gckinds/pypy: annotation rpython rpython/lltypesystem Message-ID: <20060911082347.B3AEC10081@code0.codespeak.net> Author: mwh Date: Mon Sep 11 10:23:46 2006 New Revision: 32136 Modified: pypy/branch/more-gckinds/pypy/annotation/model.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/rptr.py Log: obscure fixes and hacks to get adt methods attached to interior pointers working. this was hard. Modified: pypy/branch/more-gckinds/pypy/annotation/model.py ============================================================================== --- pypy/branch/more-gckinds/pypy/annotation/model.py (original) +++ pypy/branch/more-gckinds/pypy/annotation/model.py Mon Sep 11 10:23:46 2006 @@ -568,6 +568,13 @@ return s_val.ootype if isinstance(s_val, SomeOOStaticMeth): return s_val.method + if isinstance(s_val, SomeInteriorPtr): + p = s_val.ll_ptrtype + if 0 in p.offsets: + assert list(p.offsets).count(0) == 1 + return lltype.Ptr(lltype.Ptr(p.PARENTTYPE)._interior_ptr_type_with_index(p.TO)) + else: + return lltype.Ptr(p.PARENTTYPE) if isinstance(s_val, SomePtr): return s_val.ll_ptrtype for witness, T in annotation_to_ll_map: Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Mon Sep 11 10:23:46 2006 @@ -619,10 +619,15 @@ o = self.TO._container_example() return _ptr(self, o, solid=True) - def _interior_ptr_type_with_index(self): + def _interior_ptr_type_with_index(self, TO): assert self.TO._gckind == 'gc' - R = GcStruct("Interior", ('ptr', self), ('index', Signed), - hints={'interior_ptr_type':True}) + if isinstance(TO, Struct): + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}, + adtmeths=TO._adtmeths) + else: + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}) return R class InteriorPtr(LowLevelType): Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Mon Sep 11 10:23:46 2006 @@ -103,7 +103,7 @@ if isinstance(ITEM_TYPE, ContainerType): if ARRAY._gckind == 'gc' and ITEM_TYPE._gckind == 'raw': v_array, v_index = hop.inputargs(r_ptr, Signed) - INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index() + INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], resulttype = Ptr(INTERIOR_PTR_TYPE)) hop.genop('setfield', @@ -181,6 +181,7 @@ def __init__(self, adtmeth, rtyper): self.func = adtmeth.func + self.ll_ptrtype = adtmeth.ll_ptrtype self.lowleveltype = rtyper.getrepr(annmodel.lltype_to_annotation(adtmeth.ll_ptrtype)).lowleveltype def rtype_simple_call(self, hop): @@ -189,7 +190,7 @@ s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func) v_ptr = hop2.args_v[0] hop2.r_s_popfirstarg() - hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.lowleveltype)) + hop2.v_s_insertfirstarg(v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype)) hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func) return hop2.dispatch() @@ -217,7 +218,7 @@ self.resulttype = Ptr(ptrtype.TO) assert numitemoffsets <= 1 if numitemoffsets > 0: - self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index()) + self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO)) else: self.lowleveltype = self.parentptrtype @@ -289,7 +290,7 @@ ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, ContainerType): v_array, v_index = hop.inputargs(r_ptr, Signed) - INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index() + INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], resulttype = Ptr(INTERIOR_PTR_TYPE)) hop.genop('setfield', From ale at codespeak.net Mon Sep 11 10:38:52 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 11 Sep 2006 10:38:52 +0200 (CEST) Subject: [pypy-svn] r32138 - pypy/dist/pypy/lib/pyontology/test Message-ID: <20060911083852.13CEE10086@code0.codespeak.net> Author: ale Date: Mon Sep 11 10:38:50 2006 New Revision: 32138 Modified: pypy/dist/pypy/lib/pyontology/test/test_sparql.py Log: Skip the test if pyparsing is not installed Modified: pypy/dist/pypy/lib/pyontology/test/test_sparql.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_sparql.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_sparql.py Mon Sep 11 10:38:50 2006 @@ -1,8 +1,14 @@ -from pypy.lib.pyontology.sparql_grammar import SPARQLGrammar as SP +try: + import pyparsing +except ImportError: + from py.test import skip + skip("Pyparsing not installed") +from pypy.lib.pyontology.sparql_grammar import SPARQLGrammar as SP qt = """ - PREFIX ns : + PREFIX ns: + SELECT ?x ?y WHERE { ?x ns:p 123 . @@ -15,7 +21,6 @@ query = SP.Query.parseString(qt)[0] assert query.PrefixDecl[0].ns == 'http://example.org/ns#' where = query.SelectQuery[0].WhereClause[0] - assert len(where) == 1 triples = where.GroupGraphPattern[0].Triples assert len(triples) == 2 From mwh at codespeak.net Mon Sep 11 11:24:18 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 11:24:18 +0200 (CEST) Subject: [pypy-svn] r32139 - pypy/branch/rdict-index-based Message-ID: <20060911092418.59C741007C@code0.codespeak.net> Author: mwh Date: Mon Sep 11 11:24:17 2006 New Revision: 32139 Added: pypy/branch/rdict-index-based/ - copied from r32138, pypy/dist/ Log: a branch for making rdict less oriented about pointers to entries. From mwh at codespeak.net Mon Sep 11 11:29:38 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 11:29:38 +0200 (CEST) Subject: [pypy-svn] r32140 - pypy/branch/rdict-index-based/pypy/rpython/lltypesystem Message-ID: <20060911092938.5DD601007C@code0.codespeak.net> Author: mwh Date: Mon Sep 11 11:29:37 2006 New Revision: 32140 Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py Log: the changes from the (now inaccurately named) more-gckinds branch Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py Mon Sep 11 11:29:37 2006 @@ -389,7 +389,7 @@ return bool(d) and d.num_items != 0 def ll_dict_getitem(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) + entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))] if entry.valid(): return entry.value else: @@ -397,7 +397,7 @@ def ll_dict_setitem(d, key, value): hash = d.keyhash(key) - entry = ll_dict_lookup(d, key, hash) + entry = d.entries[ll_dict_lookup(d, key, hash)] everused = entry.everused() valid = entry.valid() # set up the new entry @@ -421,7 +421,7 @@ # the dict contains no deleted entries. This routine has the advantage # of never calling d.keyhash() and d.keyeq(), so it cannot call back # to user code. ll_dict_insertclean() doesn't resize the dict, either. - entry = ll_dict_lookup_clean(d, hash) + entry = d.entries[ll_dict_lookup_clean(d, hash)] ENTRY = lltype.typeOf(entry).TO entry.value = value entry.key = key @@ -432,7 +432,7 @@ d.num_pristine_entries -= 1 def ll_dict_delitem(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) + entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))] if not entry.valid(): raise KeyError entry.mark_deleted() @@ -481,7 +481,7 @@ if entry.valid(): checkingkey = entry.key if checkingkey == key: - return entry # found the entry + return i # found the entry if d.keyeq is not None and entry.hash() == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object @@ -492,12 +492,12 @@ # the compare did major nasty stuff to the dict: start over return ll_dict_lookup(d, key, hash) if found: - return entry # found the entry - freeslot = lltype.nullptr(lltype.typeOf(entry).TO) + return i # found the entry + freeslot_index = -1 elif entry.everused(): - freeslot = entry + freeslot_index = i else: - return entry # pristine entry -- lookup failed + return i # pristine entry -- lookup failed # In the loop, a deleted entry (everused and not valid) is by far # (factor of 100s) the least likely outcome, so test for that last. @@ -506,11 +506,14 @@ i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] if not entry.everused(): - return freeslot or entry + if freeslot_index >= 0: + return freeslot_index + else: + return i elif entry.valid(): checkingkey = entry.key if checkingkey == key: - return entry + return i if d.keyeq is not None and entry.hash() == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object @@ -522,9 +525,9 @@ # start over return ll_dict_lookup(d, key, hash) if found: - return entry # found the entry - elif not freeslot: - freeslot = entry + return i + elif freeslot_index < 0: + freeslot_index = i perturb >>= PERTURB_SHIFT def ll_dict_lookup_clean(d, hash): @@ -540,7 +543,7 @@ i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] perturb >>= PERTURB_SHIFT - return entry + return i # ____________________________________________________________ # @@ -636,14 +639,14 @@ # methods def ll_get(dict, key, default): - entry = ll_dict_lookup(dict, key, dict.keyhash(key)) + entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] if entry.valid(): return entry.value else: return default def ll_setdefault(dict, key, default): - entry = ll_dict_lookup(dict, key, dict.keyhash(key)) + entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] if entry.valid(): return entry.value else: @@ -727,5 +730,5 @@ return res def ll_contains(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) + entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))] return entry.valid() From mwh at codespeak.net Mon Sep 11 11:59:22 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 11:59:22 +0200 (CEST) Subject: [pypy-svn] r32141 - pypy/branch/rdict-index-based/pypy/rpython/lltypesystem Message-ID: <20060911095922.52F801007C@code0.codespeak.net> Author: mwh Date: Mon Sep 11 11:59:21 2006 New Revision: 32141 Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py Log: obscure: if (something that gets merged with r_uint) >= 0: isn't useful Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py Mon Sep 11 11:59:21 2006 @@ -478,6 +478,8 @@ i = r_uint(hash & mask) # do the first try before any looping entry = entries[i] + found_freeslot = False + freeslot_index = r_uint(0) if entry.valid(): checkingkey = entry.key if checkingkey == key: @@ -493,9 +495,9 @@ return ll_dict_lookup(d, key, hash) if found: return i # found the entry - freeslot_index = -1 elif entry.everused(): freeslot_index = i + found_freeslot = True else: return i # pristine entry -- lookup failed @@ -506,7 +508,7 @@ i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] if not entry.everused(): - if freeslot_index >= 0: + if found_freeslot: return freeslot_index else: return i @@ -526,8 +528,9 @@ return ll_dict_lookup(d, key, hash) if found: return i - elif freeslot_index < 0: - freeslot_index = i + elif not found_freeslot: + freeslot_index = i + found_freeslot = True perturb >>= PERTURB_SHIFT def ll_dict_lookup_clean(d, hash): From arigo at codespeak.net Mon Sep 11 13:58:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Sep 2006 13:58:08 +0200 (CEST) Subject: [pypy-svn] r32145 - in pypy/dist/pypy: rpython/memory translator/llvm translator/llvm/module Message-ID: <20060911115808.7233D1007E@code0.codespeak.net> Author: arigo Date: Mon Sep 11 13:58:06 2006 New Revision: 32145 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/llvm/database.py pypy/dist/pypy/translator/llvm/gc.py pypy/dist/pypy/translator/llvm/module/genexterns.c pypy/dist/pypy/translator/llvm/opwriter.py pypy/dist/pypy/translator/llvm/structnode.py Log: Started support for --gc=framework in llvm. Cleaned up and support more address and offset features. Always do raisingop2direct_call in the graphs produced by the GC (because they come after the normal backend_optimize() has been called). Now we die in llvm's own optimizers in a failed assertion. Hard to test our code now :-((( It's known to be incomplete, though. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Mon Sep 11 13:58:06 2006 @@ -947,7 +947,7 @@ annmodel.s_None) annhelper.finish() # at this point, annotate all mix-level helpers - annhelper.backend_optimize() + annhelper.backend_optimize(raisingop2direct_call_all=True) self.collect_analyzer = CollectAnalyzer(self.translator) self.collect_analyzer.analyze_all() Modified: pypy/dist/pypy/translator/llvm/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm/database.py (original) +++ pypy/dist/pypy/translator/llvm/database.py Mon Sep 11 13:58:06 2006 @@ -144,6 +144,11 @@ def prepare_constant(self, type_, value): if isinstance(type_, lltype.Primitive): #log.prepareconstant(value, "(is primitive)") + if type_ is llmemory.Address: + # prepare the constant data which this address references + assert isinstance(value, llmemory.fakeaddress) + if value.ob is not None: + self.prepare_constant(lltype.typeOf(value.ob), value.ob) return if isinstance(type_, lltype.Ptr): @@ -229,10 +234,10 @@ return self.primitives.repr(arg.concretetype, arg.value) else: assert isinstance(arg.value, lltype._ptr) - node = self.obj2node.get(arg.value._obj) - if node is None: + if not arg.value: return 'null' else: + node = self.obj2node[arg.value._obj] return node.get_ref() else: assert isinstance(arg, Variable) @@ -405,9 +410,11 @@ def repr(self, type_, value): try: - return self.reprs[type_](type_, value) + reprfn = self.reprs[type_] except KeyError: raise Exception, "unsupported primitive type %r, value %r" % (type_, value) + else: + return reprfn(type_, value) def repr_default(self, type_, value): return str(value) @@ -461,14 +468,22 @@ from_, indices, to = self.get_offset(value.offset) indices_as_str = ", ".join("%s %s" % (w, i) for w, i in indices) - original_typename = self.database.repr_type(from_) - orignal_ref = self.database.repr_name(value.ob._obj) + #original_typename = self.database.repr_type(from_) + #orignal_ref = self.database.repr_name(value.ob._obj) + # + #typename = self.database.repr_type(to) + #ref = "getelementptr(%s* %s, %s)" % (original_typename, + # orignal_ref, + # indices_as_str) + + ptrtype = self.database.repr_type(lltype.Ptr(from_)) + node = self.database.obj2node[value.ob._obj] + parentref = node.get_pbcref(ptrtype) typename = self.database.repr_type(to) - ref = "getelementptr(%s* %s, %s)" % (original_typename, - orignal_ref, - indices_as_str) - + ref = "getelementptr(%s %s, %s)" % (ptrtype, parentref, + indices_as_str) + res = "cast(%s* %s to sbyte*)" % (typename, ref) return res @@ -506,42 +521,46 @@ return repr - def get_offset(self, value, fromoffset=False): + def get_offset(self, value, initialindices=None): " return (from_type, (indices, ...), to_type) " word = self.database.get_machine_word() uword = self.database.get_machine_uword() - indices = [] + indices = initialindices or [(word, 0)] if isinstance(value, llmemory.ItemOffset): # skips over a fixed size item (eg array access) from_ = value.TYPE - indices.append((word, value.repeat)) + lasttype, lastvalue = indices[-1] + assert lasttype == word + indices[-1] = (word, lastvalue + value.repeat) to = value.TYPE elif isinstance(value, llmemory.FieldOffset): # jumps to a field position in a struct from_ = value.TYPE pos = getindexhelper(value.fldname, value.TYPE) - if not fromoffset: - indices.append((word, 0)) indices.append((uword, pos)) to = getattr(value.TYPE, value.fldname) - + + elif isinstance(value, llmemory.ArrayLengthOffset): + # jumps to the place where the array length is stored + from_ = value.TYPE # or + assert isinstance(value.TYPE, lltype.Array) + indices.append((uword, 0)) + to = lltype.Signed + elif isinstance(value, llmemory.ArrayItemsOffset): # jumps to the beginning of array area from_ = value.TYPE - if not fromoffset: - indices.append((word, 0)) if not isinstance(value.TYPE, lltype.FixedSizeArray): indices.append((uword, 1)) + indices.append((word, 0)) # go to the 1st item to = value.TYPE.OF elif isinstance(value, llmemory.CompositeOffset): - from_, indices, to = self.get_offset(value.offsets[0]) - indices = list(indices) + from_, indices, to = self.get_offset(value.offsets[0], indices) for item in value.offsets[1:]: - _, more, to = self.get_offset(item, fromoffset=True) - indices.extend(more) + _, indices, to = self.get_offset(item, indices) else: raise Exception("unsupported offset") Modified: pypy/dist/pypy/translator/llvm/gc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/gc.py (original) +++ pypy/dist/pypy/translator/llvm/gc.py Mon Sep 11 13:58:06 2006 @@ -119,6 +119,8 @@ gcpolicy = RefcountingGcPolicy(db) elif gcpolicy in ('none', 'raw'): gcpolicy = RawGcPolicy(db) + elif gcpolicy == 'framework': + gcpolicy = FrameworkGcPolicy(db) else: raise Exception, 'unknown gcpolicy: ' + str(gcpolicy) return gcpolicy @@ -186,10 +188,14 @@ uword = self.db.get_machine_uword() fnname = '%pypy_malloc' + (atomic and '_atomic' or '') - if self.exc_useringbuf and exc_flag: - fnname += '_ringbuffer' - # dont clear the ringbuffer data - atomic = False + +## XXX (arigo) disabled the ring buffer for comparison purposes +## XXX until we know if it's a valid optimization or not + +## if self.exc_useringbuf and exc_flag: +## fnname += '_ringbuffer' +## # dont clear the ringbuffer data +## atomic = False # malloc_size is unsigned right now sizei = '%malloc_sizei' + self.get_count() @@ -218,3 +224,19 @@ def op_free(self, codewriter, opr): assert opr.rettype == 'void' and len(opr.argtypes) == 1 codewriter.free(opr.argtypes[0], opr.argrefs[0]) + +class FrameworkGcPolicy(GcPolicy): + + def __init__(self, db): + self.db = db + + def genextern_code(self): + # XXX + # This is not finished: we must call the gc init function! + r = '' + r += '#define __GC_STARTUP_CODE__\n' + r += '#define __GC_SETUP_CODE__\n' + return r + + def gc_libraries(self): + return ['pthread'] Modified: pypy/dist/pypy/translator/llvm/module/genexterns.c ============================================================================== --- pypy/dist/pypy/translator/llvm/module/genexterns.c (original) +++ pypy/dist/pypy/translator/llvm/module/genexterns.c Mon Sep 11 13:58:06 2006 @@ -37,6 +37,10 @@ memcpy((void *) ptr2, (void *) ptr1, size); } +void raw_memclear(void* ptr, long size) { + memset(ptr, 0, size); +} + char *LLVM_RPython_StartupCode(); char *RPython_StartupCode() { Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Mon Sep 11 13:58:06 2006 @@ -359,6 +359,8 @@ self.codewriter.store(opr.argtypes[2], opr.argrefs[2], tmpvar) else: self._skipped(opr) + + bare_setfield = setfield def getarrayitem(self, opr): if opr.rettype == "void": @@ -451,6 +453,10 @@ self.codewriter.call(opr.retref, opr.rettype, "%raw_malloc", opr.argtypes, opr.argrefs) + def raw_malloc_usage(self, opr): + self.codewriter.cast(opr.retref, opr.argtypes[0], opr.argrefs[0], + opr.rettype) + def raw_free(self, opr): self.codewriter.call(opr.retref, opr.rettype, "%raw_free", opr.argtypes, opr.argrefs) @@ -459,6 +465,10 @@ self.codewriter.call(opr.retref, opr.rettype, "%raw_memcopy", opr.argtypes, opr.argrefs) + def raw_memclear(self, opr): + self.codewriter.call(opr.retref, opr.rettype, "%raw_memclear", + opr.argtypes, opr.argrefs) + def raw_store(self, opr): arg_addr, arg_dummy, arg_incr, arg_value = opr.argrefs (argtype_addr, argtype_dummy, @@ -503,3 +513,6 @@ cast_addr = incr_addr self.codewriter.load(opr.retref, opr.rettype, cast_addr) + + def debug_print(self, opr): + pass # XXX Modified: pypy/dist/pypy/translator/llvm/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm/structnode.py (original) +++ pypy/dist/pypy/translator/llvm/structnode.py Mon Sep 11 13:58:06 2006 @@ -259,6 +259,7 @@ found = True break pos += 1 + assert found ref = "getelementptr(%s* %s, int 0, uint %s)" %( self.get_typerepr(), From mwh at codespeak.net Mon Sep 11 14:48:20 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 14:48:20 +0200 (CEST) Subject: [pypy-svn] r32151 - in pypy/branch/rdict-index-based/pypy/rpython: lltypesystem test Message-ID: <20060911124820.C9CBF1006C@code0.codespeak.net> Author: mwh Date: Mon Sep 11 14:48:19 2006 New Revision: 32151 Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py Log: move all the adt methods onto the dictionary rather than the entry. haven't made much attempt to make the code look natural, but it's not too bad apart from ll_dict_resize which is really really horrible. Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py Mon Sep 11 14:48:19 2006 @@ -93,6 +93,7 @@ nullkeymarker = not self.key_repr.can_ll_be_null(s_key) nullvaluemarker = not self.value_repr.can_ll_be_null(s_value) + entrymeths['entry_has_f_everused'] = 0 if nullkeymarker: entrymeths['everused'] = ll_everused_from_key elif nullvaluemarker: @@ -100,11 +101,13 @@ else: entryfields.append(("f_everused", lltype.Bool)) entrymeths['everused'] = ll_everused_from_flag + entrymeths['entry_has_f_everused'] = 1 # * if the key or the value can also contain a "dummy" non-null # marker, we use it for deleted entries. rtyper = self.rtyper dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key) + entrymeths['entry_has_f_valid'] = 0 if dummy_obj: entrymeths['dummy_obj'] = dummy_obj entrymeths['valid'] = ll_valid_from_key @@ -122,6 +125,7 @@ entrymeths['must_clear_value'] = False else: entryfields.append(("f_valid", lltype.Bool)) + entrymeths['entry_has_f_valid'] = 1 entrymeths['valid'] = ll_valid_from_flag entrymeths['mark_deleted'] = ll_mark_deleted_in_flag @@ -133,15 +137,18 @@ fasthashfn = None else: fasthashfn = self.key_repr.get_ll_fasthash_function() + + entrymeths['entry_has_f_hash'] = 0 if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) + entrymeths['entry_has_f_hash'] = 1 entrymeths['hash'] = ll_hash_from_cache else: entrymeths['hash'] = ll_hash_recomputed entrymeths['fasthashfn'] = fasthashfn # Build the lltype data structures - self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths, + self.DICTENTRY = lltype.Struct("dictentry", #adtmeths=entrymeths, *entryfields) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) fields = [ ("num_items", lltype.Signed), @@ -170,6 +177,7 @@ 'keyeq': ll_keyeq, 'paranoia': False, } + adtmeths.update(entrymeths) self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) @@ -331,47 +339,47 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. -def ll_everused_from_flag(entry): - return entry.f_everused +def ll_everused_from_flag(d, i): + return d.entries[i].f_everused -def ll_everused_from_key(entry): - return bool(entry.key) +def ll_everused_from_key(d, i): + return bool(d.entries[i].key) -def ll_everused_from_value(entry): - return bool(entry.value) +def ll_everused_from_value(d, i): + return bool(d.entries[i].value) -def ll_valid_from_flag(entry): - return entry.f_valid - -def ll_mark_deleted_in_flag(entry): - entry.f_valid = False - -def ll_valid_from_key(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - return entry.everused() and entry.key != dummy - -def ll_mark_deleted_in_key(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - entry.key = dummy - -def ll_valid_from_value(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - return entry.everused() and entry.value != dummy - -def ll_mark_deleted_in_value(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - entry.value = dummy - -def ll_hash_from_cache(entry): - return entry.f_hash - -def ll_hash_recomputed(entry): - ENTRY = lltype.typeOf(entry).TO - return ENTRY.fasthashfn(entry.key) +def ll_valid_from_flag(d, i): + return d.entries[i].f_valid + +def ll_mark_deleted_in_flag(d, i): + d.entries[i].f_valid = False + +def ll_valid_from_key(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + return d.everused(i) and d.entries[i].key != dummy + +def ll_mark_deleted_in_key(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + d.entries[i].key = dummy + +def ll_valid_from_value(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + return d.everused(i) and d.entries[i].value != dummy + +def ll_mark_deleted_in_value(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + d.entries[i].value = dummy + +def ll_hash_from_cache(d, i): + return d.entries[i].f_hash + +def ll_hash_recomputed(d, i): + DICT = lltype.typeOf(d).TO + return DICT.fasthashfn(d.entries[i].key) def ll_keyhash_custom(d, key): DICT = lltype.typeOf(d).TO @@ -389,28 +397,29 @@ return bool(d) and d.num_items != 0 def ll_dict_getitem(d, key): - entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))] - if entry.valid(): - return entry.value + i = ll_dict_lookup(d, key, d.keyhash(key)) + if d.valid(i): + return d.entries[i].value else: raise KeyError def ll_dict_setitem(d, key, value): hash = d.keyhash(key) - entry = d.entries[ll_dict_lookup(d, key, hash)] - everused = entry.everused() - valid = entry.valid() + i = ll_dict_lookup(d, key, hash) + entry = d.entries[i] + everused = d.everused(i) + valid = d.valid(i) # set up the new entry - ENTRY = lltype.typeOf(entry).TO + DICT = lltype.typeOf(d).TO entry.value = value if valid: return entry.key = key - if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash - if hasattr(ENTRY, 'f_valid'): entry.f_valid = True + if DICT.entry_has_f_hash: entry.f_hash = hash + if DICT.entry_has_f_valid: entry.f_valid = True d.num_items += 1 if not everused: - if hasattr(ENTRY, 'f_everused'): entry.f_everused = True + if DICT.entry_has_f_everused: entry.f_everused = True d.num_pristine_entries -= 1 if d.num_pristine_entries <= len(d.entries) / 3: ll_dict_resize(d) @@ -422,52 +431,76 @@ # of never calling d.keyhash() and d.keyeq(), so it cannot call back # to user code. ll_dict_insertclean() doesn't resize the dict, either. entry = d.entries[ll_dict_lookup_clean(d, hash)] - ENTRY = lltype.typeOf(entry).TO + DICT = lltype.typeOf(d).TO entry.value = value entry.key = key - if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash - if hasattr(ENTRY, 'f_valid'): entry.f_valid = True - if hasattr(ENTRY, 'f_everused'): entry.f_everused = True + if DICT.entry_has_f_hash: entry.f_hash = hash + if DICT.entry_has_f_valid: entry.f_valid = True + if DICT.entry_has_f_everused: entry.f_everused = True d.num_items += 1 d.num_pristine_entries -= 1 def ll_dict_delitem(d, key): - entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))] - if not entry.valid(): + i = ll_dict_lookup(d, key, d.keyhash(key)) + if not d.valid(i): raise KeyError - entry.mark_deleted() + entry = d.entries[i] + d.mark_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers - ENTRY = lltype.typeOf(entry).TO - if ENTRY.must_clear_key: + DICT = lltype.typeOf(d).TO + if DICT.must_clear_key: key = entry.key # careful about destructor side effects: # keep key alive until entry.value has also # been zeroed (if it must be) - entry.key = lltype.nullptr(ENTRY.key.TO) - if ENTRY.must_clear_value: - entry.value = lltype.nullptr(ENTRY.value.TO) + entry.key = lltype.nullptr(DICT.entries.OF.key.TO) + if DICT.must_clear_value: + entry.value = lltype.nullptr(DICT.entries.OF.value.TO) num_entries = len(d.entries) if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4: ll_dict_resize(d) def ll_dict_resize(d): old_entries = d.entries - old_size = len(old_entries) + old_size = len(old_entries) # make a 'new_size' estimate and shrink it if there are many # deleted entry markers new_size = old_size * 2 while new_size > DICT_INITSIZE and d.num_items < new_size / 4: new_size /= 2 - d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True) - d.num_items = 0 - d.num_pristine_entries = new_size + new_entries = lltype.malloc(lltype.typeOf(d).TO.entries.TO, new_size, zero=True) + new_num_items = 0 + new_num_pristine_entries = new_size i = 0 while i < old_size: - entry = old_entries[i] - if entry.valid(): - ll_dict_insertclean(d, entry.key, entry.value, entry.hash()) + entry = d.entries[i] + if d.valid(i): + + # AAAAAAAAAAA + hash = d.hash(i) + + old_entries = d.entries + old_num_items = d.num_items + old_num_pristine_entries = d.num_pristine_entries + d.entries = new_entries + d.num_items = new_num_items + d.num_pristine_entries = new_num_pristine_entries + + ll_dict_insertclean(d, entry.key, entry.value, hash) + + new_entries = d.entries + new_num_items = d.num_items + new_num_pristine_entries = d.num_pristine_entries + d.entries = old_entries + d.num_items = old_num_items + d.num_pristine_entries = old_num_pristine_entries + i += 1 + d.entries = new_entries + d.num_items = new_num_items + d.num_pristine_entries = new_num_pristine_entries + # ------- a port of CPython's dictobject.c's lookdict implementation ------- PERTURB_SHIFT = 5 @@ -480,22 +513,22 @@ entry = entries[i] found_freeslot = False freeslot_index = r_uint(0) - if entry.valid(): + if d.valid(i): checkingkey = entry.key if checkingkey == key: return i # found the entry - if d.keyeq is not None and entry.hash() == hash: + if d.keyeq is not None and d.hash(i) == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not entry.valid() or entry.key != checkingkey): + not d.valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: start over return ll_dict_lookup(d, key, hash) if found: return i # found the entry - elif entry.everused(): + elif d.everused(i): freeslot_index = i found_freeslot = True else: @@ -507,22 +540,22 @@ while 1: i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] - if not entry.everused(): + if not d.everused(i): if found_freeslot: return freeslot_index else: return i - elif entry.valid(): + elif d.valid(i): checkingkey = entry.key if checkingkey == key: return i - if d.keyeq is not None and entry.hash() == hash: + if d.keyeq is not None and d.hash(i) == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not entry.valid() or entry.key != checkingkey): + not d.valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: # start over return ll_dict_lookup(d, key, hash) @@ -542,7 +575,7 @@ i = r_uint(hash & mask) entry = entries[i] perturb = r_uint(hash) - while entry.everused(): + while d.everused(i): i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] perturb >>= PERTURB_SHIFT @@ -620,8 +653,9 @@ entries_len = len(entries) while index < entries_len: entry = entries[index] + i = index index = index + 1 - if entry.valid(): + if dict.valid(i): iter.index = index if RETURNTYPE is lltype.Void: return None @@ -631,6 +665,9 @@ r.item1 = recast(RETURNTYPE.TO.item1, entry.value) return r elif func is dum_keys: + from pypy.rpython.lltypesystem.lloperation import llop + from pypy.rpython.lltypesystem.lltype import Void + llop.debug_print(Void, entry.key) return entry.key elif func is dum_values: return entry.value @@ -642,16 +679,16 @@ # methods def ll_get(dict, key, default): - entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] - if entry.valid(): - return entry.value + i = ll_dict_lookup(dict, key, dict.keyhash(key)) + if dict.valid(i): + return dict.entries[i].value else: return default def ll_setdefault(dict, key, default): - entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))] - if entry.valid(): - return entry.value + i = ll_dict_lookup(dict, key, dict.keyhash(key)) + if dict.valid(i): + return dict.entries[i].value else: ll_dict_setitem(dict, key, default) return default @@ -669,12 +706,12 @@ while i < dictsize: d_entry = d.entries[i] entry = dict.entries[i] - ENTRY = lltype.typeOf(entry).TO + DICT = lltype.typeOf(dict).TO d_entry.key = entry.key - if hasattr(ENTRY, 'f_valid'): d_entry.f_valid = entry.f_valid - if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused + if DICT.entry_has_f_valid: d_entry.f_valid = entry.f_valid + if DICT.entry_has_f_everused: d_entry.f_everused = entry.f_everused d_entry.value = entry.value - if hasattr(ENTRY, 'f_hash'): d_entry.f_hash = entry.f_hash + if DICT.entry_has_f_hash: d_entry.f_hash = entry.f_hash i += 1 return d @@ -692,7 +729,7 @@ i = 0 while i < d2len: entry = entries[i] - if entry.valid(): + if dic2.valid(i): ll_dict_setitem(dic1, entry.key, entry.value) i += 1 @@ -716,7 +753,7 @@ p = 0 while i < dlen: entry = entries[i] - if entry.valid(): + if dic.valid(i): ELEM = lltype.typeOf(items).TO.OF if ELEM is not lltype.Void: if func is dum_items: @@ -733,5 +770,5 @@ return res def ll_contains(d, key): - entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))] - return entry.valid() + i = ll_dict_lookup(d, key, d.keyhash(key)) + return d.valid(i) Modified: pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py (original) +++ pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py Mon Sep 11 14:48:19 2006 @@ -548,7 +548,7 @@ res = self.interpret(func2, [ord(x), ord(y)]) for i in range(len(res.entries)): - assert not (res.entries[i].everused() and not res.entries[i].valid()) + assert not (res.everused(i) and not res.valid(i)) def func3(c0, c1, c2, c3, c4, c5, c6, c7): d = {} @@ -568,7 +568,7 @@ for i in range(rdict.DICT_INITSIZE)]) count_frees = 0 for i in range(len(res.entries)): - if not res.entries[i].everused(): + if not res.everused(i): count_frees += 1 assert count_frees >= 3 @@ -659,8 +659,8 @@ res = self.interpret(f, []) assert res.item0 == True DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy + assert not DICT.entry_has_f_everused# non-None string keys + assert not DICT.entry_has_f_valid # strings have a dummy def test_opt_nullvaluemarker(self): def f(n): @@ -670,8 +670,8 @@ res = self.interpret(f, [-5]) assert res.item0 == 4 DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy + assert not DICT.entry_has_f_everused# non-None string keys + assert not DICT.entry_has_f_valid # strings have a dummy def test_opt_nonullmarker(self): class A: @@ -687,8 +687,8 @@ res = self.interpret(f, [-5]) assert res.item0 == -5441 DICT = lltype.typeOf(res.item1).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance + assert DICT.entry_has_f_everused # can-be-None A instances + assert not DICT.entry_has_f_valid# with a dummy A instance res = self.interpret(f, [6]) assert res.item0 == -5441 @@ -703,8 +703,8 @@ assert res.item0 == 1 assert res.item1 == 24 DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1 + assert DICT.entry_has_f_everused # all ints can be zero + assert not DICT.entry_has_f_valid# nonneg int: dummy -1 def test_opt_no_dummy(self): def f(n): @@ -716,8 +716,8 @@ assert res.item0 == 1 assert res.item1 == -24 DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available + assert DICT.entry_has_f_everused # all ints can be zero + assert DICT.entry_has_f_valid # no dummy available def test_opt_multiple_identical_dicts(self): def f(n): @@ -748,7 +748,3 @@ return dic[i] res = self.interpret(func, [5]) assert res.ll_get(5) is res - - - - From mwh at codespeak.net Mon Sep 11 16:15:01 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 16:15:01 +0200 (CEST) Subject: [pypy-svn] r32154 - in pypy/branch/rdict-index-based/pypy/rpython: lltypesystem test Message-ID: <20060911141501.A1EDD10077@code0.codespeak.net> Author: mwh Date: Mon Sep 11 16:15:00 2006 New Revision: 32154 Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py Log: trivial cleanups Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py Mon Sep 11 16:15:00 2006 @@ -75,7 +75,7 @@ # compute the shape of the DICTENTRY structure entryfields = [] - entrymeths = { + adtmeths = { 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) @@ -93,41 +93,41 @@ nullkeymarker = not self.key_repr.can_ll_be_null(s_key) nullvaluemarker = not self.value_repr.can_ll_be_null(s_value) - entrymeths['entry_has_f_everused'] = 0 + adtmeths['entry_has_f_everused'] = 0 if nullkeymarker: - entrymeths['everused'] = ll_everused_from_key + adtmeths['entry_everused'] = ll_everused_from_key elif nullvaluemarker: - entrymeths['everused'] = ll_everused_from_value + adtmeths['entry_everused'] = ll_everused_from_value else: entryfields.append(("f_everused", lltype.Bool)) - entrymeths['everused'] = ll_everused_from_flag - entrymeths['entry_has_f_everused'] = 1 + adtmeths['entry_everused'] = ll_everused_from_flag + adtmeths['entry_has_f_everused'] = 1 # * if the key or the value can also contain a "dummy" non-null # marker, we use it for deleted entries. rtyper = self.rtyper dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key) - entrymeths['entry_has_f_valid'] = 0 + adtmeths['entry_has_f_valid'] = 0 if dummy_obj: - entrymeths['dummy_obj'] = dummy_obj - entrymeths['valid'] = ll_valid_from_key - entrymeths['mark_deleted'] = ll_mark_deleted_in_key + adtmeths['dummy_obj'] = dummy_obj + adtmeths['entry_valid'] = ll_valid_from_key + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_key # the key is overwritten by 'dummy' when the entry is deleted - entrymeths['must_clear_key'] = False + adtmeths['must_clear_key'] = False else: dummy_obj = self.value_repr.get_ll_dummyval_obj(rtyper, s_value) if dummy_obj: - entrymeths['dummy_obj'] = dummy_obj - entrymeths['valid'] = ll_valid_from_value - entrymeths['mark_deleted'] = ll_mark_deleted_in_value + adtmeths['dummy_obj'] = dummy_obj + adtmeths['entry_valid'] = ll_valid_from_value + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted - entrymeths['must_clear_value'] = False + adtmeths['must_clear_value'] = False else: entryfields.append(("f_valid", lltype.Bool)) - entrymeths['entry_has_f_valid'] = 1 - entrymeths['valid'] = ll_valid_from_flag - entrymeths['mark_deleted'] = ll_mark_deleted_in_flag + adtmeths['entry_has_f_valid'] = 1 + adtmeths['entry_valid'] = ll_valid_from_flag + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_flag # * the value entryfields.append(("value", self.DICTVALUE)) @@ -138,14 +138,14 @@ else: fasthashfn = self.key_repr.get_ll_fasthash_function() - entrymeths['entry_has_f_hash'] = 0 + adtmeths['entry_has_f_hash'] = 0 if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) - entrymeths['entry_has_f_hash'] = 1 - entrymeths['hash'] = ll_hash_from_cache + adtmeths['entry_has_f_hash'] = 1 + adtmeths['hash'] = ll_hash_from_cache else: - entrymeths['hash'] = ll_hash_recomputed - entrymeths['fasthashfn'] = fasthashfn + adtmeths['hash'] = ll_hash_recomputed + adtmeths['fasthashfn'] = fasthashfn # Build the lltype data structures self.DICTENTRY = lltype.Struct("dictentry", #adtmeths=entrymeths, @@ -158,13 +158,13 @@ self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr() fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype), ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ]) - adtmeths = { + adtmeths.update({ 'keyhash': ll_keyhash_custom, 'keyeq': ll_keyeq_custom, 'r_rdict_eqfn': self.r_rdict_eqfn, 'r_rdict_hashfn': self.r_rdict_hashfn, 'paranoia': True, - } + }) else: # figure out which functions must be used to hash and compare ll_keyhash = self.key_repr.get_ll_hash_function() @@ -172,12 +172,11 @@ ll_keyhash = lltype.staticAdtMethod(ll_keyhash) if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) - adtmeths = { + adtmeths.update({ 'keyhash': ll_keyhash, 'keyeq': ll_keyeq, 'paranoia': False, - } - adtmeths.update(entrymeths) + }) self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) @@ -357,7 +356,7 @@ def ll_valid_from_key(d, i): DICT = lltype.typeOf(d).TO dummy = DICT.dummy_obj.ll_dummy_value - return d.everused(i) and d.entries[i].key != dummy + return d.entry_everused(i) and d.entries[i].key != dummy def ll_mark_deleted_in_key(d, i): DICT = lltype.typeOf(d).TO @@ -367,7 +366,7 @@ def ll_valid_from_value(d, i): DICT = lltype.typeOf(d).TO dummy = DICT.dummy_obj.ll_dummy_value - return d.everused(i) and d.entries[i].value != dummy + return d.entry_everused(i) and d.entries[i].value != dummy def ll_mark_deleted_in_value(d, i): DICT = lltype.typeOf(d).TO @@ -398,7 +397,7 @@ def ll_dict_getitem(d, key): i = ll_dict_lookup(d, key, d.keyhash(key)) - if d.valid(i): + if d.entry_valid(i): return d.entries[i].value else: raise KeyError @@ -407,8 +406,8 @@ hash = d.keyhash(key) i = ll_dict_lookup(d, key, hash) entry = d.entries[i] - everused = d.everused(i) - valid = d.valid(i) + everused = d.entry_everused(i) + valid = d.entry_valid(i) # set up the new entry DICT = lltype.typeOf(d).TO entry.value = value @@ -442,10 +441,10 @@ def ll_dict_delitem(d, key): i = ll_dict_lookup(d, key, d.keyhash(key)) - if not d.valid(i): + if not d.entry_valid(i): raise KeyError entry = d.entries[i] - d.mark_deleted(i) + d.mark_entry_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers DICT = lltype.typeOf(d).TO @@ -474,7 +473,7 @@ i = 0 while i < old_size: entry = d.entries[i] - if d.valid(i): + if d.entry_valid(i): # AAAAAAAAAAA hash = d.hash(i) @@ -513,7 +512,7 @@ entry = entries[i] found_freeslot = False freeslot_index = r_uint(0) - if d.valid(i): + if d.entry_valid(i): checkingkey = entry.key if checkingkey == key: return i # found the entry @@ -523,12 +522,12 @@ found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not d.valid(i) or entry.key != checkingkey): + not d.entry_valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: start over return ll_dict_lookup(d, key, hash) if found: return i # found the entry - elif d.everused(i): + elif d.entry_everused(i): freeslot_index = i found_freeslot = True else: @@ -540,12 +539,12 @@ while 1: i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] - if not d.everused(i): + if not d.entry_everused(i): if found_freeslot: return freeslot_index else: return i - elif d.valid(i): + elif d.entry_valid(i): checkingkey = entry.key if checkingkey == key: return i @@ -555,7 +554,7 @@ found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not d.valid(i) or entry.key != checkingkey): + not d.entry_valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: # start over return ll_dict_lookup(d, key, hash) @@ -575,7 +574,7 @@ i = r_uint(hash & mask) entry = entries[i] perturb = r_uint(hash) - while d.everused(i): + while d.entry_everused(i): i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] perturb >>= PERTURB_SHIFT @@ -655,7 +654,7 @@ entry = entries[index] i = index index = index + 1 - if dict.valid(i): + if dict.entry_valid(i): iter.index = index if RETURNTYPE is lltype.Void: return None @@ -680,14 +679,14 @@ def ll_get(dict, key, default): i = ll_dict_lookup(dict, key, dict.keyhash(key)) - if dict.valid(i): + if dict.entry_valid(i): return dict.entries[i].value else: return default def ll_setdefault(dict, key, default): i = ll_dict_lookup(dict, key, dict.keyhash(key)) - if dict.valid(i): + if dict.entry_valid(i): return dict.entries[i].value else: ll_dict_setitem(dict, key, default) @@ -729,7 +728,7 @@ i = 0 while i < d2len: entry = entries[i] - if dic2.valid(i): + if dic2.entry_valid(i): ll_dict_setitem(dic1, entry.key, entry.value) i += 1 @@ -753,7 +752,7 @@ p = 0 while i < dlen: entry = entries[i] - if dic.valid(i): + if dic.entry_valid(i): ELEM = lltype.typeOf(items).TO.OF if ELEM is not lltype.Void: if func is dum_items: @@ -771,4 +770,4 @@ def ll_contains(d, key): i = ll_dict_lookup(d, key, d.keyhash(key)) - return d.valid(i) + return d.entry_valid(i) Modified: pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py (original) +++ pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py Mon Sep 11 16:15:00 2006 @@ -548,7 +548,7 @@ res = self.interpret(func2, [ord(x), ord(y)]) for i in range(len(res.entries)): - assert not (res.everused(i) and not res.valid(i)) + assert not (res.entry_everused(i) and not res.entry_valid(i)) def func3(c0, c1, c2, c3, c4, c5, c6, c7): d = {} @@ -568,7 +568,7 @@ for i in range(rdict.DICT_INITSIZE)]) count_frees = 0 for i in range(len(res.entries)): - if not res.everused(i): + if not res.entry_everused(i): count_frees += 1 assert count_frees >= 3 From mwh at codespeak.net Mon Sep 11 16:20:46 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 16:20:46 +0200 (CEST) Subject: [pypy-svn] r32156 - in pypy/branch/more-gckinds/pypy/rpython: lltypesystem test Message-ID: <20060911142046.5F8F310079@code0.codespeak.net> Author: mwh Date: Mon Sep 11 16:20:43 2006 New Revision: 32156 Removed: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rdict.py pypy/branch/more-gckinds/pypy/rpython/test/test_rdict.py Log: remove rdict on this branch From mwh at codespeak.net Mon Sep 11 16:21:26 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 16:21:26 +0200 (CEST) Subject: [pypy-svn] r32157 - in pypy/branch/more-gckinds/pypy/rpython: lltypesystem test Message-ID: <20060911142126.2C74A10079@code0.codespeak.net> Author: mwh Date: Mon Sep 11 16:21:25 2006 New Revision: 32157 Added: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rdict.py - copied unchanged from r32156, pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py pypy/branch/more-gckinds/pypy/rpython/test/test_rdict.py - copied unchanged from r32156, pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py Log: copy them back again from the other branch From mwh at codespeak.net Mon Sep 11 16:31:37 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 16:31:37 +0200 (CEST) Subject: [pypy-svn] r32159 - in pypy/branch/more-gckinds/pypy/rpython: . lltypesystem test Message-ID: <20060911143137.510191007D@code0.codespeak.net> Author: mwh Date: Mon Sep 11 16:31:36 2006 New Revision: 32159 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/rptr.py pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Log: setitem for interior pointers Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Mon Sep 11 16:31:36 2006 @@ -1193,12 +1193,10 @@ if ob is None: raise RuntimeError for o in self._offsets: - if isinstance(o, int): - ob = ob.getitem(o) - elif isinstance(o, str): + if isinstance(o, str): ob = ob._getattr(o) else: - 1/0 + ob = ob.getitem(o) return ob _obj = property(_get_obj) Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Mon Sep 11 16:31:36 2006 @@ -278,8 +278,7 @@ assert not isinstance(FIELD_TYPE, ContainerType) v_self, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2]) vlist = self.getinteriorfieldargs(hop, v_self) + [v_fieldname, v_value] - return hop.genop('setinteriorfield', vlist, - resulttype=hop.r_result.lowleveltype) + return hop.genop('setinteriorfield', vlist) @@ -303,6 +302,14 @@ vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index] return hop.genop('getinteriorfield', vlist, resulttype=ITEM_TYPE) + + def rtype_setitem((r_ptr, r_index), hop): + ARRAY = r_ptr.resulttype.TO + ITEM_TYPE = ARRAY.OF + assert not isinstance(ITEM_TYPE, ContainerType) + v_self, v_index, v_value = hop.inputargs(r_ptr, Signed, hop.args_r[2]) + vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index, v_value] + hop.genop('setinteriorfield', vlist) class __extend__(pairtype(InteriorPtrRepr, LLADTMethRepr)): Modified: pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Mon Sep 11 16:31:36 2006 @@ -263,3 +263,14 @@ return len(t.items) res = interpret(f, []) assert res == 1 + +def test_interior_ptr_with_setitem(): + T = GcStruct("T", ('s', Array(Signed))) + def g(a): + a[0] = 1 + def f(): + t = malloc(T, 1) + g(t.s) + return t.s[0] + res = interpret(f, []) + assert res == 1 From mwh at codespeak.net Mon Sep 11 16:41:57 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 16:41:57 +0200 (CEST) Subject: [pypy-svn] r32160 - in pypy/branch/more-gckinds/pypy: annotation rpython/lltypesystem rpython/test Message-ID: <20060911144157.E89FF1007D@code0.codespeak.net> Author: mwh Date: Mon Sep 11 16:41:57 2006 New Revision: 32160 Modified: pypy/branch/more-gckinds/pypy/annotation/model.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Log: remove _TYPE from _interior_ptr -- thanks for the prodding arigo Modified: pypy/branch/more-gckinds/pypy/annotation/model.py ============================================================================== --- pypy/branch/more-gckinds/pypy/annotation/model.py (original) +++ pypy/branch/more-gckinds/pypy/annotation/model.py Mon Sep 11 16:41:57 2006 @@ -630,6 +630,12 @@ # adtmeths: the getattr() result is then a plain FunctionType object. from pypy.annotation.bookkeeper import getbookkeeper return getbookkeeper().immutablevalue(v) + if isinstance(v, lltype._interior_ptr): + ob = v._parent + if ob is None: + raise RuntimeError + T = lltype.InteriorPtr(lltype.typeOf(ob), v._T, v._offsets) + return SomeInteriorPtr(T) return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Mon Sep 11 16:41:57 2006 @@ -1205,7 +1205,7 @@ if ob is None: raise RuntimeError return InteriorPtr(typeOf(ob), self._T, self._offsets) - _TYPE = property(_get_TYPE) +## _TYPE = property(_get_TYPE) def _expose(self, offset, val): """XXX A nice docstring here""" Modified: pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/test/test_rptr.py Mon Sep 11 16:41:57 2006 @@ -209,11 +209,9 @@ def test_interior_ptr(): S = Struct("S", ('x', Signed)) T = GcStruct("T", ('s', S)) - def g(s): - s.x = 1 def f(): t = malloc(T) - g(t.s) + t.s.x = 1 return t.s.x res = interpret(f, []) assert res == 1 @@ -221,11 +219,9 @@ def test_interior_ptr_with_index(): S = Struct("S", ('x', Signed)) T = GcArray(S) - def g(s): - s.x = 1 def f(): t = malloc(T, 1) - g(t[0]) + t[0].x = 1 return t[0].x res = interpret(f, []) assert res == 1 @@ -233,11 +229,9 @@ def test_interior_ptr_with_field_and_index(): S = Struct("S", ('x', Signed)) T = GcStruct("T", ('items', Array(S))) - def g(s): - s.x = 1 def f(): t = malloc(T, 1) - g(t.items[0]) + t.items[0].x = 1 return t.items[0].x res = interpret(f, []) assert res == 1 @@ -246,11 +240,9 @@ S = Struct("S", ('x', Signed)) T = Struct("T", ('s', S)) U = GcArray(T) - def g(s): - s.x = 1 def f(): u = malloc(U, 1) - g(u[0].s) + u[0].s.x = 1 return u[0].s.x res = interpret(f, []) assert res == 1 @@ -266,11 +258,9 @@ def test_interior_ptr_with_setitem(): T = GcStruct("T", ('s', Array(Signed))) - def g(a): - a[0] = 1 def f(): t = malloc(T, 1) - g(t.s) + t.s[0] = 1 return t.s[0] res = interpret(f, []) assert res == 1 From mwh at codespeak.net Mon Sep 11 17:18:42 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Sep 2006 17:18:42 +0200 (CEST) Subject: [pypy-svn] r32165 - in pypy/branch/more-gckinds/pypy: rpython/lltypesystem translator/c/src Message-ID: <20060911151842.78A0410078@code0.codespeak.net> Author: mwh Date: Mon Sep 11 17:18:41 2006 New Revision: 32165 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py pypy/branch/more-gckinds/pypy/translator/c/src/support.h Log: redefine the pyobject <-> rpython string functions to not trade in interior pointers. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/rstr.py Mon Sep 11 17:18:41 2006 @@ -85,10 +85,7 @@ cstr = inputconst(Void, STR) v_result = llops.genop('malloc_varsize', [cstr, v_len], resulttype=Ptr(STR)) - cchars = inputconst(Void, "chars") - v_chars = llops.genop('getsubstruct', [v_result, cchars], - resulttype=Ptr(STR.chars)) - llops.gencapicall('PyString_ToLLCharArray', [v, v_chars]) + llops.gencapicall('PyString_ToRPyString', [v, v_result]) string_repr = llops.rtyper.type_system.rstr.string_repr v_result = llops.convertvar(v_result, string_repr, r_to) return v_result @@ -99,15 +96,11 @@ string_repr = llops.rtyper.type_system.rstr.string_repr v = llops.convertvar(v, r_from, string_repr) cchars = inputconst(Void, "chars") - v_chars = llops.genop('getsubstruct', [v, cchars], - resulttype=Ptr(STR.chars)) - v_size = llops.genop('getarraysize', [v_chars], - resulttype=Signed) # xxx put in table - return llops.gencapicall('PyString_FromLLCharArrayAndSize', - [v_chars, v_size], + return llops.gencapicall('PyString_FromRPyString', + [v], resulttype=pyobj_repr, - _callable= lambda chars, sz: pyobjectptr(''.join(chars))) + _callable= lambda v: pyobjectptr(''.join(v.chars))) def mallocstr(length): r = malloc(STR, length) Modified: pypy/branch/more-gckinds/pypy/translator/c/src/support.h ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/src/support.h (original) +++ pypy/branch/more-gckinds/pypy/translator/c/src/support.h Mon Sep 11 17:18:41 2006 @@ -18,12 +18,12 @@ #define FAIL_ZER(msg) FAIL_EXCEPTION(PyExc_ZeroDivisionError, msg) #define CFAIL() RPyConvertExceptionFromCPython() -#define PyString_FromLLCharArrayAndSize(itemsarray, size) \ - PyString_FromStringAndSize(itemsarray->items, size) +#define PyString_FromRPyString(rpystr) \ + PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr)) -#define PyString_ToLLCharArray(s, itemsarray) \ - memcpy(itemsarray->items, PyString_AS_STRING(s), \ - itemsarray->length) +#define PyString_ToRPyString(s, rpystr) \ + memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \ + RPyString_Size(rpystr)) #ifndef PYPY_STANDALONE From pedronis at codespeak.net Mon Sep 11 17:29:41 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 11 Sep 2006 17:29:41 +0200 (CEST) Subject: [pypy-svn] r32166 - pypy/dist/pypy/jit/tl/test Message-ID: <20060911152941.C76AE1007B@code0.codespeak.net> Author: pedronis Date: Mon Sep 11 17:29:40 2006 New Revision: 32166 Modified: pypy/dist/pypy/jit/tl/test/test_tl.py Log: fix shallow test breakage. Modified: pypy/dist/pypy/jit/tl/test/test_tl.py ============================================================================== --- pypy/dist/pypy/jit/tl/test/test_tl.py (original) +++ pypy/dist/pypy/jit/tl/test/test_tl.py Mon Sep 11 17:29:40 2006 @@ -231,38 +231,15 @@ assert res == 5040 - FACTORIAL_SOURCE = ''' - PUSH 1 # accumulator - PUSHARG - - start: - PICK 0 - PUSH 1 - LE - BR_COND exit - - SWAP - PICK 1 - MUL - SWAP - PUSH 1 - SUB - PUSH 1 - BR_COND start - - exit: - POP - RETURN - ''' def test_factorial_with_arg(self): - code = compile(self.FACTORIAL_SOURCE) + code = compile(FACTORIAL_SOURCE) # see below res = self.interp(code, 0, 6) assert res == 720 def test_translate_factorial(self): # use py.test --benchmark to do the benchmarking - code = compile(self.FACTORIAL_SOURCE) + code = compile(FACTORIAL_SOURCE) interp = self.interp def driver(): bench = Benchmark() @@ -275,3 +252,28 @@ fn = translate(driver, []) res = fn() assert res == 0 # too many powers of 2 to be anything else + + +FACTORIAL_SOURCE = ''' + PUSH 1 # accumulator + PUSHARG + + start: + PICK 0 + PUSH 1 + LE + BR_COND exit + + SWAP + PICK 1 + MUL + SWAP + PUSH 1 + SUB + PUSH 1 + BR_COND start + + exit: + POP + RETURN + ''' From pedronis at codespeak.net Mon Sep 11 17:39:56 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 11 Sep 2006 17:39:56 +0200 (CEST) Subject: [pypy-svn] r32169 - pypy/dist/pypy/rpython/memory/test Message-ID: <20060911153956.A3EA81007E@code0.codespeak.net> Author: pedronis Date: Mon Sep 11 17:39:55 2006 New Revision: 32169 Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py Log: update the fragile counters to the values for the new style of malloc failure checking used by the exception transform. Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py Mon Sep 11 17:39:55 2006 @@ -307,7 +307,7 @@ for gc in rgc, bgc: t, transformer = rtype_and_transform(f, [object], gc, check=False) ops = getops(graphof(t, f)) - assert len(ops.get('getfield', [])) == 2 + assert len(ops.get('getfield', [])) == 1 def DONOTtest_protect_unprotect_no_exception_block(): def p(): protect('this is an object') @@ -410,7 +410,7 @@ t, transformer = rtype_and_transform(f, [], gctransform.RefcountingGCTransformer, check=False) graph = graphof(t, f) ops = getops(graph) - assert len(ops['getfield']) == 5 + assert len(ops['getfield']) == 2 assert len(ops['setfield']) == 4 def test_arraybarrier(): From pedronis at codespeak.net Mon Sep 11 18:09:55 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 11 Sep 2006 18:09:55 +0200 (CEST) Subject: [pypy-svn] r32171 - pypy/dist/pypy/rpython/memory Message-ID: <20060911160955.CB3221007B@code0.codespeak.net> Author: pedronis Date: Mon Sep 11 18:09:54 2006 New Revision: 32171 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: (arigo, pedronis) revert this change, it breaks some tests on top of the llinterp because of symbolic to float conversions caused by the transformation. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Mon Sep 11 18:09:54 2006 @@ -947,7 +947,7 @@ annmodel.s_None) annhelper.finish() # at this point, annotate all mix-level helpers - annhelper.backend_optimize(raisingop2direct_call_all=True) + annhelper.backend_optimize() self.collect_analyzer = CollectAnalyzer(self.translator) self.collect_analyzer.analyze_all() From pedronis at codespeak.net Mon Sep 11 18:18:56 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 11 Sep 2006 18:18:56 +0200 (CEST) Subject: [pypy-svn] r32172 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060911161856.92ECD1007E@code0.codespeak.net> Author: pedronis Date: Mon Sep 11 18:18:55 2006 New Revision: 32172 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py Log: (arigo, pedronis) Make debug_assert canfold again. This means it will be removed by backendopts and fixes some now failing tests. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Mon Sep 11 18:18:55 2006 @@ -401,7 +401,7 @@ 'debug_print': LLOp(), 'debug_pdb': LLOp(), 'debug_log_exc': LLOp(), - 'debug_assert': LLOp(canrun=True), + 'debug_assert': LLOp(canfold=True), } # __________ operations on PyObjects __________ From fijal at codespeak.net Mon Sep 11 18:42:51 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Sep 2006 18:42:51 +0200 (CEST) Subject: [pypy-svn] r32175 - pypy/dist/pypy/annotation Message-ID: <20060911164251.4802210071@code0.codespeak.net> Author: fijal Date: Mon Sep 11 18:42:50 2006 New Revision: 32175 Modified: pypy/dist/pypy/annotation/model.py Log: Allow it to be None. Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Mon Sep 11 18:42:50 2006 @@ -433,7 +433,7 @@ attributes as well as methods """ def can_be_none(self): - return False + return True class SomeCTypesObject(SomeExternalObject): """Stands for an object of the ctypes module.""" From fijal at codespeak.net Mon Sep 11 18:48:20 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Sep 2006 18:48:20 +0200 (CEST) Subject: [pypy-svn] r32177 - pypy/dist/pypy/rpython/ootypesystem Message-ID: <20060911164820.80BF710071@code0.codespeak.net> Author: fijal Date: Mon Sep 11 18:48:18 2006 New Revision: 32177 Modified: pypy/dist/pypy/rpython/ootypesystem/bltregistry.py Log: Missing commit, which fixes decorators. Modified: pypy/dist/pypy/rpython/ootypesystem/bltregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/bltregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/bltregistry.py Mon Sep 11 18:48:18 2006 @@ -16,6 +16,9 @@ def __init__(self, name, ex_value): self.name = name self.example = ex_value + + def __repr__(self): + return "" % (self.name, self.example) class MethodDesc(object): def __init__(self, args, retval = None): @@ -32,6 +35,9 @@ else: self.num += 1 return ArgDesc('v%d' % (self.num-1), val) + + def __repr__(self): + return "" % (self.args,) class CallableEntry(ExtRegistryEntry): _type_ = MethodDesc @@ -50,6 +56,16 @@ class BasicMetaExternal(type): def _is_compatible(type2): return type(type2) is BasicMetaExternal + + def __new__(self, _name, _type, _vars): + retval = type.__new__(self, _name, _type, _vars) + if not retval._methods: + retval._methods = {} + for name, var in _vars.iteritems(): + if hasattr(var, '_method'): + meth_name, desc = var._method + retval._methods[meth_name] = desc + return retval _is_compatible = staticmethod(_is_compatible) @@ -60,7 +76,7 @@ _fields = {} _methods = {} - def described(cls, retval=None, args={}): + def described(retval=None, args={}): def decorator(func): code = func.func_code if not func.func_defaults: @@ -68,7 +84,6 @@ else: defs = func.func_defaults - assert(code.co_argcount < len(defs) + len(args), "Not enough information for describing method") for arg in xrange(1, code.co_argcount - len(defs)): @@ -82,11 +97,11 @@ arg_pass.append((varname, args[varname])) else: arg_pass.append((varname, defs[arg - start_pos])) - cls._methods[func.__name__] = MethodDesc(arg_pass, retval) + func._method = (func.__name__, MethodDesc(arg_pass, retval)) return func return decorator - described = classmethod(described) + described = staticmethod(described) described = BasicExternal.described From fijal at codespeak.net Mon Sep 11 18:50:28 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Sep 2006 18:50:28 +0200 (CEST) Subject: [pypy-svn] r32178 - pypy/dist/pypy/translator Message-ID: <20060911165028.3851110071@code0.codespeak.net> Author: fijal Date: Mon Sep 11 18:50:25 2006 New Revision: 32178 Modified: pypy/dist/pypy/translator/driver.py Log: Added debug transform option for JS builds. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon Sep 11 18:50:25 2006 @@ -29,7 +29,8 @@ 'lowmem': False, 'fork_before': None, 'raisingop2direct_call' : False, - 'merge_if_blocks': True + 'merge_if_blocks': True, + 'debug_transform' : False, } _default_options = optparse.Values(defaults=DEFAULT_OPTIONS) @@ -207,7 +208,14 @@ annmodel.DEBUG = self.options.debug annotator = translator.buildannotator(policy=policy) + s = annotator.build_types(self.entry_point, self.inputtypes) + + if self.options.debug_transform: + from pypy.translator.transformer.debug import DebugTransformer + dt = DebugTransformer(translator) + dt.transform_all() + self.sanity_check_annotation() if self.standalone and s.knowntype != int: raise Exception("stand-alone program entry point must return an " @@ -452,7 +460,7 @@ def task_source_js(self): from pypy.translator.js.js import JS self.gen = JS(self.translator, functions=[self.entry_point], - stackless=self.options.stackless) + stackless=self.options.stackless, use_debug=self.options.debug_transform) filename = self.gen.write_source() self.log.info("Wrote %s" % (filename,)) task_source_js = taskdef(task_source_js, From fijal at codespeak.net Mon Sep 11 18:52:13 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Sep 2006 18:52:13 +0200 (CEST) Subject: [pypy-svn] r32180 - pypy/dist/pypy/translator/transformer/test Message-ID: <20060911165213.C172510071@code0.codespeak.net> Author: fijal Date: Mon Sep 11 18:52:13 2006 New Revision: 32180 Modified: pypy/dist/pypy/translator/transformer/test/test_basictransform.py Log: Change level of skipness Modified: pypy/dist/pypy/translator/transformer/test/test_basictransform.py ============================================================================== --- pypy/dist/pypy/translator/transformer/test/test_basictransform.py (original) +++ pypy/dist/pypy/translator/transformer/test/test_basictransform.py Mon Sep 11 18:52:13 2006 @@ -11,7 +11,8 @@ from pypy.rpython.nonconst import NonConstant import py -py.test.skip("Needs refactoring") +def setup_module(mod): + py.test.skip("Needs refactoring") def transform_function(transformerclass, fun, annotation=[], specialize=True, type_system="ootype"): From fijal at codespeak.net Mon Sep 11 18:54:16 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Sep 2006 18:54:16 +0200 (CEST) Subject: [pypy-svn] r32181 - pypy/dist/pypy/translator/js/test Message-ID: <20060911165416.E90F310071@code0.codespeak.net> Author: fijal Date: Mon Sep 11 18:54:16 2006 New Revision: 32181 Modified: pypy/dist/pypy/translator/js/test/test_basicexternal.py Log: Missing check Modified: pypy/dist/pypy/translator/js/test/test_basicexternal.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_basicexternal.py (original) +++ pypy/dist/pypy/translator/js/test/test_basicexternal.py Mon Sep 11 18:54:16 2006 @@ -34,7 +34,7 @@ check_source_contains(fun, "\.some_code") def test_basicexternal_raise(): - py.test.skip("Raises") + py.test.skip("Constant BasicExternals not implemented") def raising_fun(): try: b = B() @@ -46,7 +46,7 @@ fun = compile_function(raising_fun, []) assert fun() == 3 -class C(object): +class C(BasicExternal): @described(retval=3) def f(self): pass @@ -61,3 +61,5 @@ pass fun = compile_function(raising_method_call, []) + assert len(C._methods) == 1 + assert 'f' in C._methods From fijal at codespeak.net Mon Sep 11 18:54:36 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Sep 2006 18:54:36 +0200 (CEST) Subject: [pypy-svn] r32182 - pypy/dist/pypy/translator/js/test Message-ID: <20060911165436.E310410071@code0.codespeak.net> Author: fijal Date: Mon Sep 11 18:54:35 2006 New Revision: 32182 Modified: pypy/dist/pypy/translator/js/test/runtest.py Log: Added view after transformation. Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Mon Sep 11 18:54:35 2006 @@ -39,6 +39,8 @@ ann.build_types(function, annotations) if debug_transform: DebugTransformer(t).transform_all() + if view or option.view: + t.view() t.buildrtyper(type_system="ootype").specialize() if view or option.view: From arigo at codespeak.net Mon Sep 11 21:22:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Sep 2006 21:22:17 +0200 (CEST) Subject: [pypy-svn] r32188 - pypy/dist/pypy/module/crypt Message-ID: <20060911192217.2BC3310079@code0.codespeak.net> Author: arigo Date: Mon Sep 11 21:22:15 2006 New Revision: 32188 Modified: pypy/dist/pypy/module/crypt/interp_crypt.py Log: Fix 'module/crypt'. Using CConfig ensures that we get the correct '-l' linker option when compiling. Modified: pypy/dist/pypy/module/crypt/interp_crypt.py ============================================================================== --- pypy/dist/pypy/module/crypt/interp_crypt.py (original) +++ pypy/dist/pypy/module/crypt/interp_crypt.py Mon Sep 11 21:22:15 2006 @@ -6,10 +6,13 @@ import sys from ctypes import * -cryptfn = find_library("crypt") -cryptdll = load_library(cryptfn) +class CConfig: + _includes_ = ('unistd.h',) + cryptlib = ctypes_platform.Library('crypt') -c_crypt = cryptdll.crypt +globals().update(ctypes_platform.configure(CConfig)) + +c_crypt = cryptlib.crypt c_crypt.argtypes = [c_char_p, c_char_p] c_crypt.restype = c_char_p From arigo at codespeak.net Mon Sep 11 21:46:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Sep 2006 21:46:08 +0200 (CEST) Subject: [pypy-svn] r32189 - in pypy/dist/pypy/module: _md5 _random _ssl bz2 mmap rctime Message-ID: <20060911194608.8B40510079@code0.codespeak.net> Author: arigo Date: Mon Sep 11 21:46:06 2006 New Revision: 32189 Modified: pypy/dist/pypy/module/_md5/__init__.py pypy/dist/pypy/module/_random/__init__.py pypy/dist/pypy/module/_ssl/__init__.py pypy/dist/pypy/module/bz2/__init__.py pypy/dist/pypy/module/mmap/__init__.py pypy/dist/pypy/module/rctime/__init__.py Log: Marked 5 modules with py.test.skip() because they are entierely unreviewed and have some clear problems. The idea is to prevent people from trying to include them into a pypy-c and be under the illusion that it will work. I'll open an issue pointing to the REVIEWME and the FINISHME... Modified: pypy/dist/pypy/module/_md5/__init__.py ============================================================================== --- pypy/dist/pypy/module/_md5/__init__.py (original) +++ pypy/dist/pypy/module/_md5/__init__.py Mon Sep 11 21:46:06 2006 @@ -1,3 +1,7 @@ +import py # FINISHME - well, STARTME +py.test.skip("The _md5 module is not implemented at all. " + "Only the app-level md5 module works so far.") + from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): @@ -7,4 +11,4 @@ # constants / module definitions 'digest_size' : 'space.wrap(16)', 'new' : 'interp_md5.new_md5', - 'md5' : 'interp_md5.new_md5'} \ No newline at end of file + 'md5' : 'interp_md5.new_md5'} Modified: pypy/dist/pypy/module/_random/__init__.py ============================================================================== --- pypy/dist/pypy/module/_random/__init__.py (original) +++ pypy/dist/pypy/module/_random/__init__.py Mon Sep 11 21:46:06 2006 @@ -1,3 +1,7 @@ +import py # FINISHME +py.test.skip("The _random module is not ready: it misses the post-2.2 parts of " + "the interface and it needs to use new Mersenne Twister algorithm.") + from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): @@ -29,4 +33,4 @@ 'weibullvariate' : 'interp_random.get_random_method(space, "weibullvariate")', 'whseed' : 'interp_random.get_random_method(space, "whseed")', # officially obsolete } - \ No newline at end of file + Modified: pypy/dist/pypy/module/_ssl/__init__.py ============================================================================== --- pypy/dist/pypy/module/_ssl/__init__.py (original) +++ pypy/dist/pypy/module/_ssl/__init__.py Mon Sep 11 21:46:06 2006 @@ -1,3 +1,7 @@ +import py # FINISHME - more thinking needed +py.test.skip("The _ssl module is only usable when running on the exact " + "same platform from which the ssl.py was computed.") + # This module is imported by socket.py. It should *not* be used # directly. from pypy.interpreter.mixedmodule import MixedModule Modified: pypy/dist/pypy/module/bz2/__init__.py ============================================================================== --- pypy/dist/pypy/module/bz2/__init__.py (original) +++ pypy/dist/pypy/module/bz2/__init__.py Mon Sep 11 21:46:06 2006 @@ -1,3 +1,4 @@ +# REVIEWME from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): Modified: pypy/dist/pypy/module/mmap/__init__.py ============================================================================== --- pypy/dist/pypy/module/mmap/__init__.py (original) +++ pypy/dist/pypy/module/mmap/__init__.py Mon Sep 11 21:46:06 2006 @@ -14,6 +14,11 @@ } def buildloaders(cls): + import py # REVIEWME + py.test.skip("The mmap module is not ready: many methods do far too " + "much copying, and it uses 'pythonapi', which makes it " + "not translatable.") + from pypy.module.mmap import interp_mmap import os Modified: pypy/dist/pypy/module/rctime/__init__.py ============================================================================== --- pypy/dist/pypy/module/rctime/__init__.py (original) +++ pypy/dist/pypy/module/rctime/__init__.py Mon Sep 11 21:46:06 2006 @@ -19,6 +19,12 @@ } def buildloaders(cls): + import py # REVIEWME + py.test.skip("The rctime module is not ready: the checks on the input " + "arguments are incomplete; strftime() can eat all your " + "memory in error conditions; the use of math.fmod() " + "should be removed.") + from pypy.module.rctime import interp_time import os From mwh at codespeak.net Tue Sep 12 10:28:04 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 10:28:04 +0200 (CEST) Subject: [pypy-svn] r32191 - in pypy/branch/more-gckinds/pypy/rpython: . lltypesystem Message-ID: <20060912082804.544621007B@code0.codespeak.net> Author: mwh Date: Tue Sep 12 10:27:59 2006 New Revision: 32191 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/rptr.py Log: treat pointers to internal opaques as boring old pointers. that this required fixing three places is not good at all... Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Tue Sep 12 10:27:59 2006 @@ -1164,7 +1164,7 @@ """XXX A nice docstring here""" T = typeOf(val) if isinstance(T, ContainerType): - if self._T._gckind == 'gc' and T._gckind == 'raw': + if self._T._gckind == 'gc' and T._gckind == 'raw' and not isinstance(T, OpaqueType): val = _interior_ptr(T, self._obj, [offset]) else: val = _ptr(Ptr(T), val, solid=self._solid) @@ -1211,10 +1211,8 @@ """XXX A nice docstring here""" T = typeOf(val) if isinstance(T, ContainerType): - if T._gckind == 'raw': - val = _interior_ptr(T, self._parent, self._offsets + [offset]) - else: - 1/0 + assert T._gckind == 'raw' + val = _interior_ptr(T, self._parent, self._offsets + [offset]) return val Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Tue Sep 12 10:27:59 2006 @@ -3,7 +3,7 @@ from pypy.objspace.flow import model as flowmodel from pypy.rpython.lltypesystem.lltype import \ Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray, \ - InteriorPtr + InteriorPtr, OpaqueType from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr @@ -36,7 +36,7 @@ return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): - if self.lowleveltype.TO._gckind == 'gc' and FIELD_TYPE._gckind == 'raw': + if self.lowleveltype.TO._gckind == 'gc' and FIELD_TYPE._gckind == 'raw' and not isinstance(FIELD_TYPE, OpaqueType): return hop.genop('same_as', [hop.inputarg(self, 0)], resulttype=self.lowleveltype) else: @@ -101,7 +101,7 @@ ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, ContainerType): - if ARRAY._gckind == 'gc' and ITEM_TYPE._gckind == 'raw': + if ARRAY._gckind == 'gc' and ITEM_TYPE._gckind == 'raw' and not isinstance(ITEM_TYPE, OpaqueType): v_array, v_index = hop.inputargs(r_ptr, Signed) INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], From mwh at codespeak.net Tue Sep 12 10:31:51 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 10:31:51 +0200 (CEST) Subject: [pypy-svn] r32192 - pypy/branch/more-gckinds/pypy/rpython Message-ID: <20060912083151.A7D201007B@code0.codespeak.net> Author: mwh Date: Tue Sep 12 10:31:49 2006 New Revision: 32192 Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py Log: an arigo-suggested cheat (thanks :) Modified: pypy/branch/more-gckinds/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rptr.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rptr.py Tue Sep 12 10:31:49 2006 @@ -36,7 +36,7 @@ return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): - if self.lowleveltype.TO._gckind == 'gc' and FIELD_TYPE._gckind == 'raw' and not isinstance(FIELD_TYPE, OpaqueType): + if isinstance(hop.r_result, InteriorPtrRepr): return hop.genop('same_as', [hop.inputarg(self, 0)], resulttype=self.lowleveltype) else: @@ -101,7 +101,7 @@ ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, ContainerType): - if ARRAY._gckind == 'gc' and ITEM_TYPE._gckind == 'raw' and not isinstance(ITEM_TYPE, OpaqueType): + if isinstance(hop.r_result, InteriorPtrRepr): v_array, v_index = hop.inputargs(r_ptr, Signed) INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], From cfbolz at codespeak.net Tue Sep 12 10:38:05 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 12 Sep 2006 10:38:05 +0200 (CEST) Subject: [pypy-svn] r32193 - in pypy/branch/config-in-more-places/pypy/config: . test Message-ID: <20060912083805.909351007B@code0.codespeak.net> Author: cfbolz Date: Tue Sep 12 10:38:01 2006 New Revision: 32193 Modified: pypy/branch/config-in-more-places/pypy/config/config.py pypy/branch/config-in-more-places/pypy/config/pypyoption.py pypy/branch/config-in-more-places/pypy/config/test/test_config.py Log: improve requirement handling in the config management: allow requirements on Choice Options too Modified: pypy/branch/config-in-more-places/pypy/config/config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/config.py Tue Sep 12 10:38:01 2006 @@ -4,9 +4,10 @@ class Config(object): _frozen = False - def __init__(self, descr, **overrides): + def __init__(self, descr, parent=None, **overrides): self._descr = descr self._value_owners = {} + self._parent = parent self._build(overrides) def _build(self, overrides): @@ -15,7 +16,7 @@ self.__dict__[child._name] = child.default self._value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): - self.__dict__[child._name] = Config(child) + self.__dict__[child._name] = Config(child, parent=self) for name, value in overrides.iteritems(): subconfig, name = self._get_by_path(name) setattr(subconfig, name, value) @@ -52,6 +53,11 @@ self = getattr(self, step) return self, path[-1] + def _get_toplevel(self): + while self._parent is not None: + self = self._parent + return self + def _freeze_(self): self.__dict__['_frozen'] = True return True @@ -140,10 +146,21 @@ raise NotImplemented('abstract base class') class ChoiceOption(Option): - def __init__(self, name, doc, values, default, cmdline=DEFAULT_OPTION_NAME): + def __init__(self, name, doc, values, default, requires=None, + cmdline=DEFAULT_OPTION_NAME): super(ChoiceOption, self).__init__(name, doc, cmdline) self.values = values self.default = default + if requires is None: + requires = {} + self._requires = requires + + def setoption(self, config, value): + name = self._name + for path, reqvalue in self._requires.get(value, []): + subconfig, name = config._get_toplevel()._get_by_path(path) + subconfig.require(name, reqvalue) + super(ChoiceOption, self).setoption(config, value) def validate(self, value): return value in self.values @@ -155,21 +172,17 @@ except ValueError, e: raise optparse.OptionValueError(e.args[0]) parser.add_option(help=self.doc, - action='callback', type='string', + action='callback', type='string', callback=_callback, *argnames) class BoolOption(ChoiceOption): - def __init__(self, name, doc, default=True, requires=None, cmdline=DEFAULT_OPTION_NAME): + def __init__(self, name, doc, default=True, requires=None, + cmdline=DEFAULT_OPTION_NAME): + if requires is not None: + requires = {True: requires} super(BoolOption, self).__init__(name, doc, [True, False], default, - cmdline=cmdline) - self._requires = requires or [] - - def setoption(self, config, value): - name = self._name - for path, reqvalue in self._requires: - subconfig, name = config._get_by_path(path) - subconfig.require(name, reqvalue) - super(BoolOption, self).setoption(config, value) + requires=requires, + cmdline=cmdline) def add_optparse_option(self, argnames, parser, config): def _callback(option, opt_str, value, parser, *args, **kwargs): @@ -178,7 +191,7 @@ except ValueError, e: raise optparse.OptionValueError(e.args[0]) parser.add_option(help=self.doc, - action='callback', + action='callback', callback=_callback, *argnames) class IntOption(Option): @@ -203,7 +216,7 @@ def _callback(option, opt_str, value, parser, *args, **kwargs): config.setoption(self._name, value, who='cmdline') parser.add_option(help=self.doc, - action='callback', type='int', + action='callback', type='int', callback=_callback, *argnames) class FloatOption(Option): @@ -228,12 +241,13 @@ def _callback(option, opt_str, value, parser, *args, **kwargs): config.setoption(self._name, value, who='cmdline') parser.add_option(help=self.doc, - action='callback', type='float', - callback=_callback, *argnames) + action='callback', type='float', + callback=_callback, *argnames) class OptionDescription(object): - def __init__(self, name, children, cmdline=DEFAULT_OPTION_NAME): + def __init__(self, name, doc, children, cmdline=DEFAULT_OPTION_NAME): self._name = name + self.doc = doc self._children = children self._build() self.cmdline = cmdline @@ -270,15 +284,14 @@ def to_optparse(config, useoptions=None, parser=None): grps = {} - def get_group(name): + def get_group(name, doc): steps = name.split('.') if len(steps) < 2: return parser - grpname = steps[0] + grpname = steps[-2] grp = grps.get(grpname, None) if grp is None: - print "groupname", grpname - grp = grps[grpname] = parser.add_option_group(grpname) + grp = grps[grpname] = parser.add_option_group(doc) return grp if parser is None: @@ -303,7 +316,7 @@ else: chunks = option.cmdline.split(' ') try: - grp = get_group(path) + grp = get_group(path, subconf._descr.doc) option.add_optparse_option(chunks, grp, subconf) except ValueError: # an option group that does not only contain bool values Modified: pypy/branch/config-in-more-places/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/pypyoption.py (original) +++ pypy/branch/config-in-more-places/pypy/config/pypyoption.py Tue Sep 12 10:38:01 2006 @@ -1,4 +1,6 @@ import py +print py.magic.autopath().dirpath().dirpath().dirpath() +py.std.sys.path.insert(0, py.magic.autopath().dirpath().dirpath().dirpath()) from pypy.config.config import OptionDescription, BoolOption, IntOption from pypy.config.config import ChoiceOption, to_optparse, Config @@ -11,8 +13,8 @@ "math", "_sre", "_pickle_support", "sys", "exceptions", "__builtins__", "recparser", "symbol"]) -pypy_optiondescription = OptionDescription("pypy", [ - OptionDescription("objspace", [ +pypy_optiondescription = OptionDescription("pypy", "All PyPy Options", [ + OptionDescription("objspace", "Object Space Option", [ ChoiceOption("name", "Object Space name", ["std", "flow", "logic", "thunk", "cpy"], "std", cmdline='--objspace -o'), @@ -26,18 +28,19 @@ BoolOption("nofaking", "disallow faking in the object space", default=False, requires=[ - ("uselibfile", True), - ("usemodules.posix", True), - ("usemodules.time", True), - ("usemodules.errno", True)]), + ("objspace.uselibfile", True), + ("objspace.usemodules.posix", True), + ("objspace.usemodules.time", True), + ("objspace.usemodules.errno", True)]), BoolOption("uselibfile", "use the applevel file implementation", default=False), - OptionDescription("usemodules", [ + OptionDescription("usemodules", "Which Modules should be used", [ BoolOption(modname, "use module %s" % (modname, ), - default=modname in default_modules) - for modname in all_modules]), + default=modname in default_modules, + cmdline=None) + for modname in all_modules], cmdline="--usemodules"), BoolOption("geninterp", "specify whether geninterp should be used"), @@ -45,12 +48,13 @@ "keep track of bytecode usage", default=False), - OptionDescription("std", [ + OptionDescription("std", "Standard Object Space Options", [ BoolOption("withsmallint", "use tagged integers", default=False), BoolOption("withprebuiltint", "prebuilt commonly used int objects", - default=False, requires=[("withsmallint", False)]), + default=False, + requires=[("objspace.std.withsmallint", False)]), IntOption("prebuiltintfrom", "lowest integer which is prebuilt", default=-5, cmdline="--prebuiltinfrom"), @@ -70,16 +74,18 @@ BoolOption("withmultidict", "use dictionaries optimized for flexibility", - default=False, requires=[("withstrdict", False)]), + default=False, + requires=[("objspace.std.withstrdict", False)]), BoolOption("withdictmeasurement", "create huge files with masses of information " "about dictionaries", - default=False, requires=[("withmultidict", True)]), + default=False, + requires=[("objspace.std.withmultidict", True)]), BoolOption("oldstyle", "specify whether the default metaclass should be classobj", - default=False), + default=False, cmdline="--oldstyle"), ]), @@ -89,9 +95,10 @@ default=False, cmdline=None), ]) + if __name__ == '__main__': config = Config(pypy_optiondescription) - paths = config.getpaths() - parser = to_optparse(config, paths) + print config.getpaths() + parser = to_optparse(config) option, args = parser.parse_args() print config Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_config.py Tue Sep 12 10:38:01 2006 @@ -225,3 +225,34 @@ py.test.raises(SystemExit, "(options, args) = parser.parse_args(args=['--dummy1'])") +def test_requirements_from_top(): + descr = OptionDescription("test", [ + BoolOption("toplevel", "", default=False), + OptionDescription("sub", [ + BoolOption("opt", "", default=False, + requires=[("toplevel", True)]) + ]) + ]) + config = Config(descr) + config.sub.opt = True + assert config.toplevel + +def test_requirements_for_choice(): + descr = OptionDescription("test", [ + BoolOption("toplevel", "", default=False), + OptionDescription("s", [ + ChoiceOption("type_system", "", ["ll", "oo"], "ll"), + ChoiceOption("backend", "", + ["c", "llvm", "cli"], "llvm", + requires={ + "c": [("s.type_system", "ll"), + ("toplevel", True)], + "llvm": [("s.type_system", "ll")], + "cli": [("s.type_system", "oo")], + }) + ]) + ]) + config = Config(descr) + config.s.backend = "cli" + assert config.s.type_system == "oo" + From mwh at codespeak.net Tue Sep 12 10:41:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 10:41:32 +0200 (CEST) Subject: [pypy-svn] r32194 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem Message-ID: <20060912084132.53AD31007B@code0.codespeak.net> Author: mwh Date: Tue Sep 12 10:41:30 2006 New Revision: 32194 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Log: add a call to _check() in _interior_ptr._get_obj() fixes raw_free tests in test_llmemory Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Tue Sep 12 10:41:30 2006 @@ -1192,6 +1192,8 @@ ob = self._parent if ob is None: raise RuntimeError + if isinstance(ob, _container): + ob._check() for o in self._offsets: if isinstance(o, str): ob = ob._getattr(o) From mwh at codespeak.net Tue Sep 12 10:54:55 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 10:54:55 +0200 (CEST) Subject: [pypy-svn] r32195 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem Message-ID: <20060912085455.D29EE10080@code0.codespeak.net> Author: mwh Date: Tue Sep 12 10:54:52 2006 New Revision: 32195 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py Log: convert typeOf(maybeinterior).TO to maybeinterior._T. not 100% happy. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py Tue Sep 12 10:54:52 2006 @@ -47,7 +47,7 @@ def ref(self, firstitemref): assert isinstance(firstitemref, _arrayitemref) array = firstitemref.array - assert lltype.typeOf(array).TO.OF == self.TYPE + assert array._T.OF == self.TYPE index = firstitemref.index + self.repeat return _arrayitemref(array, index) @@ -76,7 +76,7 @@ def ref(self, containerref): struct = containerref.get() - if lltype.typeOf(struct).TO != self.TYPE: + if struct._T != self.TYPE: struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct) return _structfieldref(struct, self.fldname) @@ -136,7 +136,7 @@ def ref(self, arrayref): array = arrayref.get() - assert lltype.typeOf(array).TO == self.TYPE + assert array._T == self.TYPE return _arrayitemref(array, index=0) def raw_malloc(self, rest, parenttype=None): @@ -164,7 +164,7 @@ def ref(self, arrayref): array = arrayref.get() - assert lltype.typeOf(array).TO == self.TYPE + assert array._T == self.TYPE return _arraylenref(array) From mwh at codespeak.net Tue Sep 12 11:00:29 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 11:00:29 +0200 (CEST) Subject: [pypy-svn] r32196 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test Message-ID: <20060912090029.0BCF510080@code0.codespeak.net> Author: mwh Date: Tue Sep 12 11:00:15 2006 New Revision: 32196 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py Log: fixes and skips in test_lltype.py Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py Tue Sep 12 11:00:15 2006 @@ -1,7 +1,5 @@ from pypy.rpython.lltypesystem.lltype import * - -def isweak(p, T): - return p._weak and typeOf(p).TO == T +import py def test_basics(): S0 = GcStruct("s0", ('a', Signed), ('b', Signed)) @@ -24,7 +22,7 @@ x = malloc(Ar,3) print x assert typeOf(x) == Ptr(Ar) - assert isweak(x[0], Ar.OF) + py.test.raises(TypeError, "typeOf(x[0])") x[0].v = 1 x[1].v = 2 x[2].v = 3 @@ -94,9 +92,7 @@ s1 = malloc(S1, 4) s1.a = 0 assert s1.a == 0 - assert isweak(s1.rest, S1.rest) assert len(s1.rest) == 4 - assert isweak(s1.rest[0], S1.rest.OF) s1.rest[0].v = 0 assert typeOf(s1.rest[0].v) == Signed assert s1.rest[0].v == 0 @@ -118,11 +114,13 @@ S2 = Struct("s2", ('s3', S3)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1) - assert isweak(p1.sub1, S2) - assert isweak(p1.sub2, S2) - assert isweak(p1.sub1.s3, S3) + py.test.raises(TypeError, "typeOf(p1.sub1)") + # _T isn't really a public API, but there's not much else to test. + assert p1.sub1._T == S2 + assert p1.sub2._T == S2 + assert p1.sub1.s3._T == S3 p2 = p1.sub1 - assert isweak(p2.s3, S3) + assert p2.s3._T == S3 def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) @@ -130,7 +128,7 @@ S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2)) p1 = malloc(S0) assert typeOf(p1.sub1) == Ptr(S1) - assert isweak(p1.sub2, S2) + py.test.raises(TypeError, "typeOf(p1.sub2)") def test_cast_simple_widening(): S2 = Struct("s2", ('a', Signed)) @@ -202,6 +200,7 @@ py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") def test_best_effort_gced_parent_detection(): + py.test.skip("test not relevant any more") S2 = Struct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) p1 = malloc(S1, 1) @@ -216,6 +215,7 @@ py.test.raises(RuntimeError, "p3[0]") def test_best_effort_gced_parent_for_arrays(): + py.test.skip("test not relevant any more") A1 = GcArray(('v', Signed)) p1 = malloc(A1, 10) p1[5].v=3 From mwh at codespeak.net Tue Sep 12 11:02:14 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 11:02:14 +0200 (CEST) Subject: [pypy-svn] r32197 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test Message-ID: <20060912090214.9FA4A10080@code0.codespeak.net> Author: mwh Date: Tue Sep 12 11:02:06 2006 New Revision: 32197 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py Log: oops, i thought i'd removed all calls to isweak. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_lltype.py Tue Sep 12 11:02:06 2006 @@ -422,6 +422,8 @@ assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) def test_flavor_malloc(): + def isweak(p, T): + return p._weak and typeOf(p).TO == T S = Struct('s', ('x', Signed)) py.test.raises(TypeError, malloc, S) p = malloc(S, flavor="raw") From mwh at codespeak.net Tue Sep 12 11:06:13 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 11:06:13 +0200 (CEST) Subject: [pypy-svn] r32198 - pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test Message-ID: <20060912090613.D7F6C10080@code0.codespeak.net> Author: mwh Date: Tue Sep 12 11:06:09 2006 New Revision: 32198 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_picklelltype.py Log: fix test_picklelltype.py too. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_picklelltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_picklelltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/test/test_picklelltype.py Tue Sep 12 11:06:09 2006 @@ -1,9 +1,6 @@ from pypy.rpython.lltypesystem.lltype import * -import pickle - -def isweak(p, T): - return p._weak and typeOf(p).TO == T +import pickle, py def test_pickle_types(): S0 = GcStruct("s0", ('a', Signed), ('b', Signed)) @@ -33,7 +30,6 @@ p_x = pickle.dumps(x) r_x = pickle.loads(p_x) assert typeOf(x) == Ptr(Ar) - assert isweak(x[0], Ar.OF) assert typeOf(x[0].v) == Signed assert [x[z].v for z in range(3)] == [1, 2, 3] # @@ -98,9 +94,7 @@ p_s1 = pickle.dumps(s1) r_s1 = pickle.loads(p_s1) assert r_s1.a == 0 - assert isweak(r_s1.rest, S1.rest) assert len(r_s1.rest) == 4 - assert isweak(r_s1.rest[0], S1.rest.OF) assert typeOf(r_s1.rest[0].v) == Signed assert r_s1.rest[0].v == 0 py.test.raises(IndexError, "r_s1.rest[4]") @@ -120,11 +114,13 @@ p1 = malloc(S1) p_p1 = pickle.dumps(p1) r_p1 = pickle.loads(p_p1) - assert isweak(r_p1.sub1, S2) - assert isweak(r_p1.sub2, S2) - assert isweak(r_p1.sub1.s3, S3) + py.test.raises(TypeError, "typeOf(p1.sub1)") + # _T isn't really a public API, but there's not much else to test. + assert r_p1.sub1._T == S2 + assert r_p1.sub2._T == S2 + assert r_p1.sub1.s3._T == S3 r_p2 = r_p1.sub1 - assert isweak(r_p2.s3, S3) + assert r_p2.s3._T == S3 def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) @@ -133,7 +129,7 @@ p1 = malloc(S0) r_p1 = pickle.loads(pickle.dumps(p1)) assert typeOf(r_p1.sub1) == Ptr(S1) - assert isweak(r_p1.sub2, S2) + py.test.raises(TypeError, "typeOf(r_p1.sub2)") def test_cast_simple_widening(): S2 = Struct("s2", ('a', Signed)) @@ -148,6 +144,7 @@ assert p4 == r_p1 def test_best_effort_gced_parent_detection(): + py.test.skip("test not relevant any more") S2 = Struct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) p1 = malloc(S1, 1) @@ -167,6 +164,7 @@ py.test.raises(RuntimeError, "r_p3[0]") def test_best_effort_gced_parent_for_arrays(): + py.test.skip("test not relevant any more") A1 = GcArray(('v', Signed)) p1 = malloc(A1, 10) for i in range(10): @@ -340,6 +338,8 @@ assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) def test_flavor_malloc(): + def isweak(p, T): + return p._weak and typeOf(p).TO == T S = Struct('s', ('x', Signed)) py.test.raises(TypeError, malloc, S) p = malloc(S, flavor="raw") From arigo at codespeak.net Tue Sep 12 11:20:59 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Sep 2006 11:20:59 +0200 (CEST) Subject: [pypy-svn] r32199 - pypy/dist/pypy/rpython/rctypes/tool Message-ID: <20060912092059.6F9CE10080@code0.codespeak.net> Author: arigo Date: Tue Sep 12 11:20:56 2006 New Revision: 32199 Modified: pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py Log: Forgot to check this in. Modified: pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py (original) +++ pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py Tue Sep 12 11:20:56 2006 @@ -75,7 +75,7 @@ print >> f for path in getattr(CConfig, '_includes_', ()): # optional print >> f, '#include <%s>' % (path,) - print >> f, CConfig._header_ # mandatory + print >> f, getattr(CConfig, '_header_', '') # optional print >> f for key, entry in entries: print >> f, 'void dump_section_%s(void) {' % (key,) From mwh at codespeak.net Tue Sep 12 11:53:01 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 11:53:01 +0200 (CEST) Subject: [pypy-svn] r32203 - in pypy/branch/more-gckinds/pypy/rpython: lltypesystem memory Message-ID: <20060912095301.D52B310079@code0.codespeak.net> Author: mwh Date: Tue Sep 12 11:53:00 2006 New Revision: 32203 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/rpython/memory/convertlltype.py Log: add rawTypeOf that returns a real Ptr for _interior_ptrs. use it in a few places, including fixing up that smelly fix to llmemory. Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py Tue Sep 12 11:53:00 2006 @@ -47,7 +47,7 @@ def ref(self, firstitemref): assert isinstance(firstitemref, _arrayitemref) array = firstitemref.array - assert array._T.OF == self.TYPE + assert lltype.rawTypeOf(array).TO.OF == self.TYPE index = firstitemref.index + self.repeat return _arrayitemref(array, index) @@ -76,7 +76,7 @@ def ref(self, containerref): struct = containerref.get() - if struct._T != self.TYPE: + if lltype.rawTypeOf(struct).TO != self.TYPE: struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct) return _structfieldref(struct, self.fldname) @@ -136,7 +136,7 @@ def ref(self, arrayref): array = arrayref.get() - assert array._T == self.TYPE + assert lltype.rawTypeOf(array).TO == self.TYPE return _arrayitemref(array, index=0) def raw_malloc(self, rest, parenttype=None): @@ -164,7 +164,7 @@ def ref(self, arrayref): array = arrayref.get() - assert array._T == self.TYPE + assert lltype.rawTypeOf(array).TO == self.TYPE return _arraylenref(array) Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Tue Sep 12 11:53:00 2006 @@ -678,6 +678,12 @@ return val.lltype() raise TypeError("typeOf(%r object)" % (tp.__name__,)) +def rawTypeOf(val): + if isinstance(val, _interior_ptr): + return Ptr(val._T) + else: + return typeOf(val) + _to_primitive = { Char: chr, UniChar: unichr, Modified: pypy/branch/more-gckinds/pypy/rpython/memory/convertlltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/memory/convertlltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/memory/convertlltype.py Tue Sep 12 11:53:00 2006 @@ -34,7 +34,7 @@ self.query_types = qt def convert(self, val_or_ptr, inline_to_ptr=None): - TYPE = lltype.typeOf(val_or_ptr) + TYPE = lltype.rawTypeOf(val_or_ptr) if isinstance(TYPE, lltype.Primitive): assert inline_to_ptr is None return get_real_value(val_or_ptr) @@ -58,7 +58,7 @@ ptr = self.converted[_array] assert inline_to_ptr is None or ptr == inline_to_ptr return ptr - TYPE = lltype.typeOf(_array) + TYPE = lltype.rawTypeOf(_array) arraylength = len(_array.items) size = sizeof(TYPE, arraylength) if inline_to_ptr is not None: @@ -95,7 +95,7 @@ return getattr(ptr, _struct._parent_index) else: return ptr[_struct._parent_index] - TYPE = lltype.typeOf(_struct) + TYPE = lltype.rawTypeOf(_struct) if TYPE._arrayfld is not None: inlinedarraylength = len(getattr(_struct, TYPE._arrayfld).items) size = sizeof(TYPE, inlinedarraylength) @@ -127,7 +127,7 @@ def convert_pointer(self, _ptr, inline_to_ptr): assert inline_to_ptr is None, "can't inline pointer" - TYPE = lltype.typeOf(_ptr) + TYPE = lltype.rawTypeOf(_ptr) if _ptr._obj is not None: return self.convert(_ptr._obj) else: @@ -135,7 +135,7 @@ def convert_object(self, _obj, inline_to_ptr): assert inline_to_ptr is None, "can't inline function or pyobject" - return simulatorptr(lltype.Ptr(lltype.typeOf(_obj)), + return simulatorptr(lltype.Ptr(lltype.rawTypeOf(_obj)), lladdress.get_address_of_object(_obj)) def collect_constants_and_types(graphs): constants = {} @@ -190,7 +190,7 @@ continue elif isinstance(cand, str): continue - elif isinstance(lltype.typeOf(cand), lltype.Primitive): + elif isinstance(lltype.rawTypeOf(cand), lltype.Primitive): continue elif cand in seen: continue From mwh at codespeak.net Tue Sep 12 15:21:08 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 15:21:08 +0200 (CEST) Subject: [pypy-svn] r32216 - pypy/branch/more-gckinds/pypy/rpython/memory Message-ID: <20060912132108.4DBA71007E@code0.codespeak.net> Author: mwh Date: Tue Sep 12 15:21:06 2006 New Revision: 32216 Modified: pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py Log: inadequate fix for zeroing gc pointers inside embedded structs. Modified: pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py Tue Sep 12 15:21:06 2006 @@ -1349,10 +1349,15 @@ c_null = Constant(lltype.nullptr(FIELD.TO), FIELD) llops.genop('bare_setfield', [v, c_name, c_null]) elif isinstance(FIELD, lltype.Struct): - c_name = Constant(name, lltype.Void) - v1 = llops.genop('getsubstruct', [v, c_name], - resulttype = lltype.Ptr(FIELD)) - gen_zero_gc_pointers(FIELD, v1, llops) + # XXX this is insufficient! + for name2 in FIELD._names: + FIELD_TYPE = getattr(FIELD, name2) + if isinstance(FIELD_TYPE, lltype.Ptr) and FIELD_TYPE._needsgc(): + c_name = Constant(name, lltype.Void) + v1 = llops.genop('getsubstruct', [v, c_name], + resulttype = lltype.Ptr(FIELD)) + gen_zero_gc_pointers(FIELD, v1, llops) + break # ____________________________________________________________ From mwh at codespeak.net Tue Sep 12 15:21:35 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Sep 2006 15:21:35 +0200 (CEST) Subject: [pypy-svn] r32217 - in pypy/branch/more-gckinds/pypy/rpython: lltypesystem rctypes Message-ID: <20060912132135.936271007E@code0.codespeak.net> Author: mwh Date: Tue Sep 12 15:21:34 2006 New Revision: 32217 Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py pypy/branch/more-gckinds/pypy/rpython/rctypes/rmodel.py Log: use rawTypeOf in a few more places. now test_transformed_gc passes! Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/llmemory.py Tue Sep 12 15:21:34 2006 @@ -229,7 +229,7 @@ def __ne__(self, other): return not (self == other) def type(self): - return lltype.typeOf(self.array).TO.OF + return lltype.rawTypeOf(self.array).TO.OF class _arraylenref(object): def __init__(self, array): @@ -264,7 +264,7 @@ def __ne__(self, other): return not (self == other) def type(self): - return getattr(lltype.typeOf(self.struct).TO, self.fieldname) + return getattr(lltype.rawTypeOf(self.struct).TO, self.fieldname) class _obref(object): def __init__(self, ob): Modified: pypy/branch/more-gckinds/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/rctypes/rmodel.py Tue Sep 12 15:21:34 2006 @@ -266,8 +266,8 @@ def reccopy(source, dest): # copy recursively a structure or array onto another. - T = lltype.typeOf(source).TO - assert T == lltype.typeOf(dest).TO + T = lltype.rawTypeOf(source).TO + assert T == lltype.rawTypeOf(dest).TO if isinstance(T, (lltype.Array, lltype.FixedSizeArray)): assert len(source) == len(dest) ITEMTYPE = T.OF @@ -295,7 +295,7 @@ raise TypeError(T) def reccopy_arrayitem(source, destarray, destindex): - ITEMTYPE = lltype.typeOf(destarray).TO.OF + ITEMTYPE = lltype.rawTypeOf(destarray).TO.OF if isinstance(ITEMTYPE, lltype.Primitive): destarray[destindex] = source else: From arigo at codespeak.net Tue Sep 12 17:08:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Sep 2006 17:08:25 +0200 (CEST) Subject: [pypy-svn] r32225 - in pypy/dist/pypy/jit/hintannotator: . test Message-ID: <20060912150825.D55901007B@code0.codespeak.net> Author: arigo Date: Tue Sep 12 17:08:24 2006 New Revision: 32225 Added: pypy/dist/pypy/jit/hintannotator/test/test_toy.py (contents, props changed) Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Log: (pedronis, arigo) hint-annotate the TLC. Simple support for indirect_call. Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Tue Sep 12 17:08:24 2006 @@ -14,7 +14,6 @@ self._cache = {} def specialize(self, input_args_hs, key=None, alt_name=None): - from pypy.jit.hintannotator import model as hintmodel # get the specialized graph -- for now, no specialization graph = self.cachedgraph(key, alt_name) @@ -56,6 +55,9 @@ self.virtual_containers = {} self.descs = {} self.annotator = hannotator + # circular imports hack + global hintmodel + from pypy.jit.hintannotator import model as hintmodel def getdesc(self, graph): try: @@ -84,7 +86,6 @@ try: origin = self.originflags[self.position_key] except KeyError: - from pypy.jit.hintannotator import model as hintmodel if len(self.position_key) == 3: graph, block, i = self.position_key spaceop = block.operations[i] @@ -101,13 +102,11 @@ pass def immutableconstant(self, const): - from pypy.jit.hintannotator import model as hintmodel res = hintmodel.SomeLLAbstractConstant(const.concretetype, {}) res.const = const.value return res def immutablevalue(self, value): - from pypy.jit.hintannotator import model as hintmodel res = hintmodel.SomeLLAbstractConstant(lltype.typeOf(value), {}) res.const = value return res @@ -165,6 +164,36 @@ graph = desc.specialize(args_hs, key=key, alt_name=alt_name) return graph + def graph_call(self, graph, fixed, args_hs): + input_args_hs = list(args_hs) + graph = self.get_graph_for_call(graph, fixed, input_args_hs) + + # propagate fixing of arguments in the function to the caller + for inp_arg_hs, arg_hs in zip(input_args_hs, args_hs): + if isinstance(arg_hs, hintmodel.SomeLLAbstractConstant): + assert len(inp_arg_hs.origins) == 1 + [o] = inp_arg_hs.origins.keys() + if o.read_fixed(): + for o in arg_hs.origins: + o.set_fixed() + + hs_res = self.annotator.recursivecall(graph, + self.position_key, + input_args_hs) + # look on which input args the hs_res result depends on + if isinstance(hs_res, hintmodel.SomeLLAbstractConstant): + deps_hs = [] + for hs_inputarg, hs_arg in zip(input_args_hs, args_hs): + if isinstance(hs_inputarg, hintmodel.SomeLLAbstractConstant): + assert len(hs_inputarg.origins) == 1 + [o] = hs_inputarg.origins.keys() + if o in hs_res.origins: + deps_hs.append(hs_arg) + if fixed: + deps_hs.append(hs_res) + hs_res = hintmodel.reorigin(hs_res, *deps_hs) + return hs_res + # get current bookkeeper def getbookkeeper(): Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Tue Sep 12 17:08:24 2006 @@ -6,6 +6,7 @@ UNARY_OPERATIONS = """same_as hint getfield setfield getsubstruct getarraysize setarrayitem cast_pointer direct_call + indirect_call int_is_true int_neg uint_is_true cast_int_to_char @@ -270,6 +271,27 @@ ARRAY = hs_v1.concretetype.TO return SomeLLAbstractVariable(lltype.Ptr(ARRAY.OF)) + def indirect_call(hs_v1, *args_hs): + hs_graph_list = args_hs[-1] + args_hs = args_hs[:-1] + assert hs_graph_list.is_constant() + graph_list = hs_graph_list.const + assert graph_list # XXX for now + + bookkeeper = getbookkeeper() + fixed = bookkeeper.myorigin().read_fixed() + results_hs = [bookkeeper.graph_call(graph, fixed, args_hs) + for graph in graph_list] + hs_res = annmodel.unionof(*results_hs) + + if isinstance(hs_res, SomeLLAbstractConstant): + hs_res.myorigin = bookkeeper.myorigin() + + # we need to make sure that hs_res does not become temporarily less + # general as a result of calling another specialized version of the + # function + return annmodel.unionof(hs_res, bookkeeper.current_op_binding()) + class __extend__(SomeLLAbstractConstant): @@ -309,34 +331,10 @@ if not hasattr(fnobj, 'graph'): raise NotImplementedError("XXX call to externals or primitives") - input_args_hs = list(args_hs) fixed = bookkeeper.myorigin().read_fixed() - graph = bookkeeper.get_graph_for_call(fnobj.graph, fixed, input_args_hs) + hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs) - # propagate fixing of arguments in the function to the caller - for inp_arg_hs, arg_hs in zip(input_args_hs, args_hs): - if isinstance(arg_hs, SomeLLAbstractConstant): - assert len(inp_arg_hs.origins) == 1 - [o] = inp_arg_hs.origins.keys() - if o.read_fixed(): - for o in arg_hs.origins: - o.set_fixed() - - hs_res = bookkeeper.annotator.recursivecall(graph, - bookkeeper.position_key, - input_args_hs) - # look on which input args the hs_res result depends on if isinstance(hs_res, SomeLLAbstractConstant): - deps_hs = [] - for hs_inputarg, hs_arg in zip(input_args_hs, args_hs): - if isinstance(hs_inputarg, SomeLLAbstractConstant): - assert len(hs_inputarg.origins) == 1 - [o] = hs_inputarg.origins.keys() - if o in hs_res.origins: - deps_hs.append(hs_arg) - if fixed: - deps_hs.append(hs_res) - hs_res = reorigin(hs_res, *deps_hs) hs_res.myorigin = bookkeeper.myorigin() # we need to make sure that hs_res does not become temporarily less Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Tue Sep 12 17:08:24 2006 @@ -434,18 +434,6 @@ _, x_v, y_v = gdesc._cache[None].getargs() assert ha.binding(x_v).is_fixed() assert ha.binding(y_v).is_fixed() - -def test_hannotate_tl(): - from pypy.jit.tl import tl - hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC) - -def test_hannotate_tl_novirtual(): - from pypy.jit.tl import tl - hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL) - -def test_hannotate_tlr_novirtual(): - from pypy.jit.tl import tlr - hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL) def test_hannotate_plus_minus(): def ll_plus_minus(s, x, y): Added: pypy/dist/pypy/jit/hintannotator/test/test_toy.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/hintannotator/test/test_toy.py Tue Sep 12 17:08:24 2006 @@ -0,0 +1,20 @@ +from pypy.jit.hintannotator.test.test_annotator import hannotate, P_OOPSPEC +from pypy.jit.hintannotator.test.test_annotator import P_OOPSPEC_NOVIRTUAL + + +def test_hannotate_tl(): + from pypy.jit.tl import tl + hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC) + +def test_hannotate_tl_novirtual(): + from pypy.jit.tl import tl + hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL) + +def test_hannotate_tlr_novirtual(): + from pypy.jit.tl import tlr + hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL) + +def test_hannotate_tlc_novirtual(): + from pypy.jit.tl import tlc + hannotate(tlc.interp_without_call, [str, int, int], + policy=P_OOPSPEC_NOVIRTUAL) From arigo at codespeak.net Tue Sep 12 20:56:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Sep 2006 20:56:36 +0200 (CEST) Subject: [pypy-svn] r32238 - pypy/dist/pypy/tool Message-ID: <20060912185636.B0EB61007E@code0.codespeak.net> Author: arigo Date: Tue Sep 12 20:56:35 2006 New Revision: 32238 Modified: pypy/dist/pypy/tool/sourcetools.py Log: (arigo, pedronis) fix repetition of class names in FunctionGraph reprs. Very important fix! Modified: pypy/dist/pypy/tool/sourcetools.py ============================================================================== --- pypy/dist/pypy/tool/sourcetools.py (original) +++ pypy/dist/pypy/tool/sourcetools.py Tue Sep 12 20:56:35 2006 @@ -254,16 +254,13 @@ def nice_repr_for_func(fn, name=None): mod = getattr(fn, '__module__', None) - if mod is None: - mod = '?' if name is None: name = getattr(fn, '__name__', None) - if name is not None: + cls = getattr(fn, 'class_', None) + if name is not None and cls is not None: + name = "%s.%s" % (cls.__name__, name) + try: firstlineno = fn.func_code.co_firstlineno - else: - name = 'UNKNOWN' + except AttributeError: firstlineno = -1 - cls = getattr(fn, 'class_', None) - if cls is not None: - name = "%s.%s" % (cls.__name__, name) - return "(%s:%d)%s" % (mod, firstlineno, name) + return "(%s:%d)%s" % (mod or '?', firstlineno, name or 'UNKNOWN') From arigo at codespeak.net Tue Sep 12 21:03:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Sep 2006 21:03:07 +0200 (CEST) Subject: [pypy-svn] r32239 - in pypy/dist/pypy: jit/hintannotator jit/hintannotator/test jit/timeshifter jit/timeshifter/test rpython Message-ID: <20060912190307.8436310083@code0.codespeak.net> Author: arigo Date: Tue Sep 12 21:03:04 2006 New Revision: 32239 Added: pypy/dist/pypy/jit/timeshifter/test/test_tlc.py - copied, changed from r32217, pypy/dist/pypy/jit/timeshifter/test/test_tl.py Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py pypy/dist/pypy/jit/hintannotator/test/test_toy.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/rpython/rtyper.py Log: (pedronis, arigo) started timeshifting support for indirect calls, still in progress, we bumped into normalisation problems. Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Tue Sep 12 21:03:04 2006 @@ -137,30 +137,36 @@ def warning(self, msg): return self.annotator.warning(msg) - def get_graph_for_call(self, graph, fixed, args_hs): - # this can modify args_hs in-place! - from pypy.jit.hintannotator.model import SomeLLAbstractConstant - desc = self.getdesc(graph) - key = None - alt_name = None + def specialization_key(self, fixed, args_hs): if fixed: - key = 'fixed' - alt_name = graph.name + '_HFixed' + return 'fixed' else: key = [] specialize = False for i, arg_hs in enumerate(args_hs): - if isinstance(arg_hs, SomeLLAbstractConstant) and arg_hs.eager_concrete: + if (isinstance(arg_hs, hintmodel.SomeLLAbstractConstant) + and arg_hs.eager_concrete): key.append('E') specialize = True else: key.append('x') if specialize: - key = ''.join(key) - alt_name = graph.name + '_H'+key + return ''.join(key) else: - key = None + return None + + def get_graph_by_key(self, graph, specialization_key): + desc = self.getdesc(graph) + return desc._cache[specialization_key] + def get_graph_for_call(self, graph, fixed, args_hs): + # this can modify args_hs in-place! + key = self.specialization_key(fixed, args_hs) + if key is None: + alt_name = None + else: + alt_name = graph.name + '_H'+key + desc = self.getdesc(graph) graph = desc.specialize(args_hs, key=key, alt_name=alt_name) return graph Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Tue Sep 12 21:03:04 2006 @@ -18,7 +18,8 @@ P_OOPSPEC_NOVIRTUAL.oopspec = True P_OOPSPEC_NOVIRTUAL.novirtualcontainer = True -def hannotate(func, argtypes, policy=None, annotator=False, inline=None): +def hannotate(func, argtypes, policy=None, annotator=False, inline=None, + backendoptimize=False): # build the normal ll graphs for ll_function t = TranslationContext() a = t.buildannotator() @@ -27,6 +28,9 @@ rtyper.specialize() if inline: auto_inlining(t, inline) + if backendoptimize: + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t) graph1 = graphof(t, func) # build hint annotator types hannotator = HintAnnotator(base_translator=t, policy=policy) Modified: pypy/dist/pypy/jit/hintannotator/test/test_toy.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_toy.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_toy.py Tue Sep 12 21:03:04 2006 @@ -17,4 +17,4 @@ def test_hannotate_tlc_novirtual(): from pypy.jit.tl import tlc hannotate(tlc.interp_without_call, [str, int, int], - policy=P_OOPSPEC_NOVIRTUAL) + policy=P_OOPSPEC_NOVIRTUAL, backendoptimize=True) Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Tue Sep 12 21:03:04 2006 @@ -333,6 +333,8 @@ def guess_call_kind(self, spaceop): + if spaceop.opname == 'indirect_call': + return 'red' # for now assert spaceop.opname == 'direct_call' c_func = spaceop.args[0] fnobj = c_func.value._obj @@ -351,6 +353,34 @@ meth = getattr(self, 'handle_%s_call' % (kind,)) return meth(hop) + def translate_op_indirect_call(self, hop): + bk = self.annotator.bookkeeper + ts = self.timeshifter + v_jitstate = hop.llops.getjitstate() + v_funcbox = hop.args_v[0] + graph_list = hop.args_v[-1].value + hop.r_s_pop(0) + hop.r_s_pop() + args_hs = hop.args_s[:] + # fixed is always false here + specialization_key = bk.specialization_key(False, args_hs) + FUNC = ts.originalconcretetype(v_funcbox) + + mapper, TS_FUNC, args_r, tsgraphs = ts.get_timeshift_mapper( + FUNC, specialization_key, graph_list) + args_v = hop.inputargs(*args_r) + + v_tsfunc = hop.llops.genmixlevelhelpercall(mapper, + [ts.s_RedBox], + [v_funcbox], + annmodel.SomePtr(TS_FUNC)) + args_v[:0] = [v_tsfunc, v_jitstate] + RESULT = v_tsfunc.concretetype.TO.RESULT + args_v.append(hop.inputconst(lltype.Void, tsgraphs)) + v_newjitstate = hop.genop('indirect_call', args_v, RESULT) + hop.llops.setjitstate(v_newjitstate) + + def translate_op_save_locals(self, hop): ts = self.timeshifter v_jitstate = hop.llops.getjitstate() @@ -441,18 +471,12 @@ hop.r_s_popfirstarg() args_hs = hop.args_s[:] # fixed is always false here - graph = bk.get_graph_for_call(fnobj.graph, False, args_hs) - args_r = [self.getrepr(hs) for hs in args_hs] + specialization_key = bk.specialization_key(False, args_hs) + fnptr, args_r = ts.get_timeshifted_fnptr(fnobj.graph, + specialization_key) args_v = hop.inputargs(*args_r) - ARGS = [ts.r_JITState.lowleveltype] - ARGS += [r.lowleveltype for r in args_r] - RESULT = ts.r_JITState.lowleveltype - fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), - graph.name, - graph=graph, - _callable = graph.func) - self.timeshifter.schedule_graph(graph) args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate] + RESULT = lltype.typeOf(fnptr).TO.RESULT v_newjitstate = hop.genop('direct_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) @@ -491,7 +515,10 @@ # build the 'direct_call' operation rtyper = self.timeshifter.rtyper - RESULT = rtyper.getrepr(s_result).lowleveltype + try: + RESULT = annmodel.annotation_to_lltype(s_result) + except ValueError: + RESULT = rtyper.getrepr(s_result).lowleveltype return self.genop('direct_call', [c]+args_v, resulttype = RESULT) Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Tue Sep 12 21:03:04 2006 @@ -33,7 +33,7 @@ t = annmodel.lltype_to_annotation(T) return a.typeannotation(t) -def hannotate(func, values, policy=None, inline=None): +def hannotate(func, values, policy=None, inline=None, backendoptimize=False): # build the normal ll graphs for ll_function t = TranslationContext() a = t.buildannotator() @@ -43,6 +43,9 @@ rtyper.specialize() if inline: auto_inlining(t, inline) + if backendoptimize: + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t) graph1 = graphof(t, func) # build hint annotator types hannotator = HintAnnotator(base_translator=t, policy=policy) @@ -66,7 +69,8 @@ del cls._cache_order def timeshift_cached(self, ll_function, values, inline=None, policy=None, - check_raises='ignored anyway'): + check_raises='ignored anyway', + backendoptimize=False): # decode the 'values' if they are specified as strings if hasattr(ll_function, 'convert_arguments'): assert len(ll_function.convert_arguments) == len(values) @@ -86,7 +90,8 @@ if len(self._cache_order) >= 3: del self._cache[self._cache_order.pop(0)] hs, ha, rtyper = hannotate(ll_function, values, - inline=inline, policy=policy) + inline=inline, policy=policy, + backendoptimize=backendoptimize) # make the timeshifted graphs htshift = HintTimeshift(ha, rtyper, self.RGenOp) Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Tue Sep 12 21:03:04 2006 @@ -24,8 +24,9 @@ self.rtyper = rtyper self.RGenOp = RGenOp self.hrtyper = HintRTyper(hannotator, self) - self.latestexitindex = -1 self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper) + self.timeshift_mapping = {} + self.sigs = {} self.s_CodeGenerator, self.r_CodeGenerator = self.s_r_instanceof( cgmodel.CodeGenerator) @@ -124,9 +125,84 @@ # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) + def get_sig_hs(self, tsgraph): + # the signature annotations are cached here because + # the graph is going to be modified + try: + return self.sigs[tsgraph] + except KeyError: + ha = self.hannotator + sig_hs = ([ha.binding(v) for v in tsgraph.getargs()], + ha.binding(tsgraph.getreturnvar())) + self.sigs[tsgraph] = sig_hs + return sig_hs + + def get_timeshifted_fnptr(self, graph, specialization_key): + bk = self.hannotator.bookkeeper + tsgraph = bk.get_graph_by_key(graph, specialization_key) + args_hs, hs_res = self.get_sig_hs(tsgraph) + args_r = [self.hrtyper.getrepr(hs_arg) for hs_arg in args_hs] + ARGS = [self.r_JITState.lowleveltype] + ARGS += [r.lowleveltype for r in args_r] + RESULT = self.r_JITState.lowleveltype + fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), + tsgraph.name, + graph=tsgraph, + _callable = graph.func) + self.schedule_graph(tsgraph) + return fnptr, args_r + def error_value(self, TYPE): return exceptiontransform.error_value(TYPE) + def get_timeshift_mapper(self, FUNC, specialization_key, graphs): + key = FUNC, specialization_key + try: + timeshift_mapper, values, keys = self.timeshift_mapping[key] + except KeyError: + values = [] + keys = [] + fnptrmap = {} + + def getter(fnptrmap, fnptr): + # indirection needed to defeat the flow object space + return fnptrmap[fnptr] + + def fill_dict(fnptrmap, values, keys): + for i in range(len(values)): + fnptrmap[values[i]] = keys[i] + + def timeshift_mapper(fnptrbox): + fnptr = rvalue.ll_getvalue(fnptrbox, FUNC) + try: + return getter(fnptrmap, fnptr) + except KeyError: + fill_dict(fnptrmap, values, keys) + return getter(fnptrmap, fnptr) # try again + + self.timeshift_mapping[key] = timeshift_mapper, values, keys + + bk = self.hannotator.bookkeeper + common_args_r = None + COMMON_TS_FUNC = None + tsgraphs = [] + for graph in graphs: + fnptr = self.rtyper.getcallable(graph) + ts_fnptr, args_r = self.get_timeshifted_fnptr(graph, + specialization_key) + tsgraphs.append(ts_fnptr._obj.graph) + TS_FUNC = lltype.typeOf(ts_fnptr) + if common_args_r is None: + common_args_r = args_r + COMMON_TS_FUNC = TS_FUNC + else: + # XXX for now + assert COMMON_TS_FUNC == TS_FUNC + assert common_args_r == args_r + keys.append(fnptr) + values.append(ts_fnptr) + return timeshift_mapper, COMMON_TS_FUNC, common_args_r, tsgraphs + # creates and numbers reentry_block for block reached by link # argument: # @@ -199,21 +275,29 @@ def timeshift_graph(self, graph): #print 'timeshift_graph START', graph + assert graph.startblock in self.hannotator.annotated self.graph = graph self.dispatch_to = [] self.statecaches = [] self.return_cache = None - entering_links = flowmodel.mkentrymap(graph) + self.latestexitindex = -1 + + # cache the annotation signature before changing the graph + args_hs, hs_res = self.get_sig_hs(graph) + assert (originalconcretetype(hs_res) is lltype.Void + or not hs_res.is_green()) # XXX not supported yet originalblocks = list(graph.iterblocks()) timeshifted_blocks = [] for block in originalblocks: - self.timeshift_block(timeshifted_blocks, entering_links, block) + self.timeshift_block(timeshifted_blocks, block) originalblocks = timeshifted_blocks + entering_links = flowmodel.mkentrymap(graph) inputlinkcounters = {} for block in originalblocks: inputlinkcounters[block] = len(entering_links[block]) + # XXX try to not use entering_links in the sequel returnblock = graph.returnblock self.r_returnvalue = self.hrtyper.bindingrepr(returnblock.inputargs[0]) @@ -296,8 +380,9 @@ block.isstartblock = False newblock.isstartblock = True self.graph.startblock = newblock - else: + if block_entering_links: for link in block_entering_links: + assert link.target is block link.settarget(newblock) if closeblock: @@ -629,14 +714,14 @@ dispatchblock.closeblock(*exitlinks) - def timeshift_block(self, timeshifted_blocks, entering_links, block): + def timeshift_block(self, timeshifted_blocks, block): hrtyper = self.hrtyper blocks = [block] i = 0 # XXX in-progress, split block at direct_calls for call support while i < len(block.operations): op = block.operations[i] - if (op.opname == 'direct_call' + if (op.opname in ('direct_call', 'indirect_call') and hrtyper.guess_call_kind(op) == 'red'): link = support.split_block_with_keepalive(block, i+1, @@ -682,7 +767,6 @@ link.args = [replacement.get(var, var) for var in link.args] block = link.target - entering_links[block] = [link] blocks.append(block) self.hannotator.annotated[block] = self.graph # for now the call doesn't return its redbox result, but only Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Sep 12 21:03:04 2006 @@ -721,11 +721,15 @@ def gendirectcall(self, ll_function, *args_v): return self.llops.gendirectcall(ll_function, *args_v) + def r_s_pop(self, index=-1): + "Return and discard the argument with index position." + self.nb_args -= 1 + self.args_v.pop(index) + return self.args_r.pop(index), self.args_s.pop(index) + def r_s_popfirstarg(self): "Return and discard the first argument." - self.nb_args -= 1 - self.args_v.pop(0) - return self.args_r.pop(0), self.args_s.pop(0) + return self.r_s_pop(0) def v_s_insertfirstarg(self, v_newfirstarg, s_newfirstarg): r_newfirstarg = self.rtyper.getrepr(s_newfirstarg) From pedronis at codespeak.net Wed Sep 13 00:42:52 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Sep 2006 00:42:52 +0200 (CEST) Subject: [pypy-svn] r32240 - pypy/dist/pypy/translator/goal Message-ID: <20060912224252.60F8A1007E@code0.codespeak.net> Author: pedronis Date: Wed Sep 13 00:42:43 2006 New Revision: 32240 Modified: pypy/dist/pypy/translator/goal/translate.py Log: grumble, 32178 broke translate.py, grumble Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Wed Sep 13 00:42:43 2006 @@ -120,6 +120,7 @@ 'fork_before': None, 'profile': False, + 'debug_transform': False, } import py From pedronis at codespeak.net Wed Sep 13 00:46:14 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Sep 2006 00:46:14 +0200 (CEST) Subject: [pypy-svn] r32241 - in pypy/dist/pypy: jit/timeshifter translator translator/backendopt Message-ID: <20060912224614.01FE41007E@code0.codespeak.net> Author: pedronis Date: Wed Sep 13 00:46:11 2006 New Revision: 32241 Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/translator/backendopt/support.py pypy/dist/pypy/translator/unsimplify.py Log: don't use anymore the delicate and needing update entering_links mapping. Use split_block instead. I opted to teach it to possibly behave at least when splitting on index = 0, vs. resorting to index() trickery in timeshifter itself. Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Wed Sep 13 00:46:11 2006 @@ -214,7 +214,7 @@ # # then passes the variables to the target of link # - def getexitindex(self, link, entering_links): + def getexitindex(self, link): self.latestexitindex += 1 reentry_block = flowmodel.Block([]) @@ -245,8 +245,6 @@ reenter_vars.append(v_value) reenter_link = flowmodel.Link(reenter_vars, link.target) - if link.target in entering_links: # update entering_links - entering_links[link.target].append(reenter_link) reentry_block.operations[:] = llops reentry_block.closeblock(reenter_link) @@ -294,26 +292,19 @@ originalblocks = timeshifted_blocks entering_links = flowmodel.mkentrymap(graph) - inputlinkcounters = {} - for block in originalblocks: - inputlinkcounters[block] = len(entering_links[block]) - # XXX try to not use entering_links in the sequel returnblock = graph.returnblock self.r_returnvalue = self.hrtyper.bindingrepr(returnblock.inputargs[0]) returnblock.operations = [] graph.returnblock = None - # we need to get the jitstate to the before block of the return block + self.dispatchblock = flowmodel.Block([]) -## self.insert_jitstate_arg(self.dispatchblock) -## for block in originalblocks: -## self.insert_jitstate_arg(block) for block in originalblocks: - block_entering_links = entering_links.pop(block) - self.insert_bookkeeping_enter(block, inputlinkcounters[block], - block_entering_links) - self.insert_bookkeeping_leave_block(block, entering_links) + is_returnblock = len(block.exits) == 0 + nentrylinks = len(entering_links[block]) + self.insert_bookkeeping_leave_block(block) + self.insert_bookkeeping_enter(block, nentrylinks, is_returnblock) # fix its concretetypes self.insert_dispatch_logic() @@ -358,7 +349,7 @@ link.args = [v_jitstate] + link.args def insert_start_setup(self): - newstartblock = self.insert_before_block(self.graph.startblock, None, + newstartblock = self.insert_before_block(self.graph.startblock, closeblock=True) llops = HintLowLevelOpList(self) v_jitstate = llops.getjitstate() @@ -370,8 +361,7 @@ annmodel.s_None) newstartblock.operations = list(llops) - def insert_before_block(self, block, block_entering_links, - closeblock=True): + def insert_before_block(self, block, closeblock=True): newinputargs = [copyvar(self.hannotator, var) for var in block.inputargs] @@ -380,10 +370,6 @@ block.isstartblock = False newblock.isstartblock = True self.graph.startblock = newblock - if block_entering_links: - for link in block_entering_links: - assert link.target is block - link.settarget(newblock) if closeblock: bridge = flowmodel.Link(newinputargs, block) @@ -415,14 +401,15 @@ return v_box - def insert_bookkeeping_enter(self, block, nentrylinks, - block_entering_links): - is_returnblock = len(block.exits) == 0 + def insert_bookkeeping_enter(self, block, nentrylinks, is_returnblock): if nentrylinks == 1 and not is_returnblock: # simple non-merging and non-returning case: nothing to do return - before_block = self.insert_before_block(block, block_entering_links) + support.split_block_with_keepalive(block, 0, + annotator=self.hannotator, + dontshuffle=True) + before_block = block newinputargs = before_block.inputargs llops = HintLowLevelOpList(self) v_boxes = self.pack_state_into_boxes(llops, newinputargs) @@ -436,6 +423,7 @@ if is_returnblock: assert self.return_cache is None self.return_cache = cache + # insert before join blocks a block with: # @@ -585,7 +573,7 @@ # returns its value as res otherwise returns True # and schedule the false case # - def insert_bookkeeping_leave_block(self, block, entering_links): + def insert_bookkeeping_leave_block(self, block): exits = block.exits exitswitch = block.exitswitch @@ -611,7 +599,7 @@ v_boxes_false = self.pack_state_into_boxes(llops, false_exit.args, pack_greens_too = True) - exitindex = self.getexitindex(false_exit, entering_links) + exitindex = self.getexitindex(false_exit) c_exitindex = rmodel.inputconst(lltype.Signed, exitindex) v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split, [self.s_JITState, Modified: pypy/dist/pypy/translator/backendopt/support.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/support.py (original) +++ pypy/dist/pypy/translator/backendopt/support.py Wed Sep 13 00:46:11 2006 @@ -71,8 +71,10 @@ def split_block_with_keepalive(block, index_operation, keep_alive_op_args=True, - annotator=None): - splitlink = split_block(annotator, block, index_operation) + annotator=None, + dontshuffle=False): + splitlink = split_block(annotator, block, index_operation, + dontshuffle=dontshuffle) afterblock = splitlink.target conservative_keepalives = needs_conservative_livevar_calculation(block) if conservative_keepalives: Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Wed Sep 13 00:46:11 2006 @@ -56,11 +56,12 @@ graph.startblock = graph.startblock.exits[0].target graph.startblock.isstartblock = True -def split_block(annotator, block, index): +def split_block(annotator, block, index, dontshuffle=False): """return a link where prevblock is the block leading up but excluding the index'th operation and target is a new block with the neccessary variables passed on. NOTE: if you call this after rtyping, you WILL need to worry - about keepalives, you may use backendopt.support.split_block_with_keepalive.""" + about keepalives, you may use backendopt.support.split_block_with_keepalive. + """ assert 0 <= index <= len(block.operations) if block.exitswitch == c_last_exception: assert index < len(block.operations) @@ -99,12 +100,19 @@ exitswitch = get_new_name(block.exitswitch) #the new block gets all the attributes relevant to outgoing links #from block the old block - newblock = Block(varmap.values()) + if not dontshuffle: + linkargs = varmap.keys() + newinputargs = varmap.values() + else: + assert index == 0 + linkargs = list(block.inputargs) + newinputargs = [get_new_name(v) for v in linkargs] + newblock = Block(newinputargs) newblock.operations = moved_operations newblock.recloseblock(*links) newblock.exitswitch = exitswitch newblock.exc_handler = block.exc_handler - link = Link(varmap.keys(), newblock) + link = Link(linkargs, newblock) block.operations = block.operations[:index] block.recloseblock(link) block.exitswitch = None From mwh at codespeak.net Wed Sep 13 10:49:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 10:49:32 +0200 (CEST) Subject: [pypy-svn] r32244 - in pypy/branch/more-gckinds/pypy: rpython rpython/lltypesystem translator/c Message-ID: <20060913084932.42C7E1007B@code0.codespeak.net> Author: mwh Date: Wed Sep 13 10:49:30 2006 New Revision: 32244 Modified: pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Log: somehow i missed reverting a bit of the change towards _gckind == 'prebuilt' -- this meant function pointers were viewed as needing gc, not really a good thing :-) Modified: pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/annlowlevel.py Wed Sep 13 10:49:30 2006 @@ -178,7 +178,7 @@ return Constant(p, lltype.typeOf(p)) def graph2delayed(self, graph): - FUNCTYPE = lltype.FuncForwardReference() + FUNCTYPE = lltype.ForwardReference() # obscure hack: embed the name of the function in the string, so # that the genc database can get it even before the delayedptr # is really computed Modified: pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/lltypesystem/lltype.py Wed Sep 13 10:49:30 2006 @@ -411,7 +411,7 @@ class FuncType(ContainerType): - _gckind = 'prebuilt' + _gckind = 'raw' __name__ = 'func' def __init__(self, args, result): for arg in args: @@ -512,9 +512,6 @@ class PyForwardReference(ForwardReference): _gckind = 'cpy' -class FuncForwardReference(ForwardReference): - _gckind = 'prebuilt' - FORWARDREF_BY_FLAVOR = {'raw': ForwardReference, 'gc': GcForwardReference, 'cpy': PyForwardReference} Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/funcgen.py (original) +++ pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Wed Sep 13 10:49:30 2006 @@ -10,7 +10,7 @@ from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray -from pypy.rpython.lltypesystem.lltype import FuncForwardReference +from pypy.rpython.lltypesystem.lltype import ForwardReference from pypy.rpython.lltypesystem.llmemory import Address, WeakGcAddress from pypy.translator.backendopt.ssa import SSI_to_SSA @@ -58,7 +58,7 @@ T = getattr(v, 'concretetype', PyObjPtr) # obscure: skip forward references and hope for the best # (needed for delayed function pointers) - if isinstance(T, Ptr) and T.TO.__class__ == FuncForwardReference: + if isinstance(T, Ptr) and T.TO.__class__ == ForwardReference: continue db.gettype(T) # force the type to be considered by the database From fijal at codespeak.net Wed Sep 13 10:57:17 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 13 Sep 2006 10:57:17 +0200 (CEST) Subject: [pypy-svn] r32245 - pypy/dist/pypy/translator/js Message-ID: <20060913085717.ABC681007B@code0.codespeak.net> Author: fijal Date: Wed Sep 13 10:57:15 2006 New Revision: 32245 Modified: pypy/dist/pypy/translator/js/function.py Log: Fixed 2.5 issues. Modified: pypy/dist/pypy/translator/js/function.py ============================================================================== --- pypy/dist/pypy/translator/js/function.py (original) +++ pypy/dist/pypy/translator/js/function.py Wed Sep 13 10:57:15 2006 @@ -206,7 +206,14 @@ self.ilasm.catch() first = False for link in [i for i in block.exits if i.exitcase is not None]: - s = "isinstanceof(exc, %s)"%basename(link.exitcase) + # XXX: Fix for 2.5 + class_name = str(link.exitcase) + m = re.search("'(.*?)'", class_name) + if not m: + real_name = class_name + else: + real_name = m.group(1) + s = "isinstanceof(exc, %s)"%basename(real_name) if not first: first = True self.ilasm.branch_if_string(s) From mwh at codespeak.net Wed Sep 13 11:21:30 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 11:21:30 +0200 (CEST) Subject: [pypy-svn] r32246 - in pypy/branch/more-gckinds/pypy: rpython/memory translator/c Message-ID: <20060913092130.3967C1007B@code0.codespeak.net> Author: mwh Date: Wed Sep 13 11:21:29 2006 New Revision: 32246 Modified: pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Log: gctransform and genc support for {get,set}interiorfield. only 5 genc tests fail, not bad. i think i may have actually made gctransform cleaner in the process... Modified: pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/more-gckinds/pypy/rpython/memory/gctransform.py Wed Sep 13 11:21:29 2006 @@ -258,28 +258,18 @@ raise NotImplementedError("gc_protect does not make sense for this gc") def replace_setfield(self, op, livevars, block): - if not var_ispyobj(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getfield", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) - result.extend(self.pop_alive(oldval)) - return result - - def replace_setarrayitem(self, op, livevars, block): - if not var_ispyobj(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getarrayitem", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) + if not var_ispyobj(op.args[-1]): + return [SpaceOperation("bare_" + op.opname, op.args, op.result)] + oldval = varoftype(op.args[-1].concretetype) + result = [] + result.append(SpaceOperation("g" + op.opname[1:], + op.args[:-1], oldval)) + result.extend(self.push_alive(op.args[-1])) + result.append(SpaceOperation("bare_" + op.opname, op.args, op.result)) result.extend(self.pop_alive(oldval)) return result + replace_setinteriorfield = replace_setfield + replace_setarrayitem = replace_setfield def replace_safe_call(self, op, livevars, block): return [SpaceOperation("direct_call", op.args, op.result)] @@ -502,29 +492,20 @@ newops[-1].result = op.result return newops - def replace_setfield(self, op, livevars, block): - if not var_needsgc(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getfield", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) - result.extend(self.pop_alive(oldval)) - return result - def replace_setarrayitem(self, op, livevars, block): - if not var_needsgc(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getarrayitem", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) + def replace_setfield(self, op, livevars, block): + if not var_needsgc(op.args[-1]): + return [SpaceOperation("bare_" + op.opname, op.args, op.result)] + oldval = varoftype(op.args[-1].concretetype) + result = [] + result.append(SpaceOperation("g" + op.opname[1:], + op.args[:-1], oldval)) + result.extend(self.push_alive(op.args[-1])) + result.append(SpaceOperation("bare_" + op.opname, op.args, op.result)) result.extend(self.pop_alive(oldval)) return result + replace_setinteriorfield = replace_setfield + replace_setarrayitem = replace_setfield ## -- maybe add this for tests and for consistency -- ## def consider_constant(self, TYPE, value): Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/funcgen.py (original) +++ pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Wed Sep 13 11:21:29 2006 @@ -416,9 +416,9 @@ return result def generic_set(self, op, targetexpr): - newvalue = self.expr(op.args[2], special_case_void=False) + newvalue = self.expr(op.args[-1], special_case_void=False) result = ['%s = %s;' % (targetexpr, newvalue)] - T = self.lltypemap(op.args[2]) + T = self.lltypemap(op.args[-1]) result = '\n'.join(result) if T is Void: result = '/* %s */' % result @@ -432,7 +432,7 @@ op.args[1].value) return self.generic_get(op, expr) - def OP_SETFIELD(self, op): + def OP_BARE_SETFIELD(self, op): assert isinstance(op.args[1], Constant) STRUCT = self.lltypemap(op.args[0]).TO structdef = self.db.gettypedefnode(STRUCT) @@ -440,7 +440,7 @@ op.args[1].value) return self.generic_set(op, expr) - OP_BARE_SETFIELD = OP_SETFIELD + #OP_SETFIELD = OP_BARE_SETFIELD def OP_GETSUBSTRUCT(self, op): RESULT = self.lltypemap(op.result).TO @@ -466,7 +466,7 @@ return self.generic_get(op, '%s[%s]' % (items, self.expr(op.args[1]))) - def OP_SETARRAYITEM(self, op): + def OP_BARE_SETARRAYITEM(self, op): ARRAY = self.lltypemap(op.args[0]).TO items = self.expr(op.args[0]) if not isinstance(ARRAY, FixedSizeArray): @@ -474,6 +474,35 @@ return self.generic_set(op, '%s[%s]' % (items, self.expr(op.args[1]))) + def interior_expr(self, args): + TYPE = args[0].concretetype.TO + expr = '(*(' + self.expr(args[0]) + '))' + for arg in args[1:]: + defnode = self.db.gettypedefnode(TYPE) + if arg.concretetype is Void: + fieldname = arg.value + expr = defnode.access_expr(expr, fieldname) + TYPE = getattr(TYPE, fieldname) + else: + if not isinstance(TYPE, FixedSizeArray): + expr = '(%s).items[%s]'%(expr, self.expr(arg)) + else: + expr = '(%s)[%s]'%(expr, self.expr(arg)) + TYPE = TYPE.OF + return expr + + def OP_GETINTERIORFIELD(self, op): + return self.generic_get(op, self.interior_expr(op.args)) + + def OP_BARE_SETINTERIORFIELD(self, op): + return self.generic_set(op, self.interior_expr(op.args[:-1])) + + def OP_GETINTERIORARRAYSIZE(self, op): + expr = self.interior_expr(op.args) + return '%s = %s.length;'%(self.expr(op.result), expr) + + #OP_SETINTERIORFIELD = OP_BARE_SETINTERIORFIELD + def OP_GETARRAYSUBSTRUCT(self, op): ARRAY = self.lltypemap(op.args[0]).TO items = self.expr(op.args[0]) From fijal at codespeak.net Wed Sep 13 11:30:15 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 13 Sep 2006 11:30:15 +0200 (CEST) Subject: [pypy-svn] r32247 - pypy/dist/pypy/translator/js Message-ID: <20060913093015.302C910050@code0.codespeak.net> Author: fijal Date: Wed Sep 13 11:30:13 2006 New Revision: 32247 Modified: pypy/dist/pypy/translator/js/opcodes.py Log: Oops. Add int_mod_zero. Modified: pypy/dist/pypy/translator/js/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js/opcodes.py (original) +++ pypy/dist/pypy/translator/js/opcodes.py Wed Sep 13 11:30:13 2006 @@ -34,6 +34,7 @@ 'int_sub': '-', 'int_floordiv': '/', 'int_mod': '%', + 'int_mod_zer': '%', # XXX: fix zero stuff 'int_and': '&', 'int_or': '|', 'int_xor': '^', From mwh at codespeak.net Wed Sep 13 11:41:35 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 11:41:35 +0200 (CEST) Subject: [pypy-svn] r32248 - pypy/branch/more-gckinds/pypy/translator/c Message-ID: <20060913094135.9DFCF1007B@code0.codespeak.net> Author: mwh Date: Wed Sep 13 11:41:33 2006 New Revision: 32248 Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Log: genc support for len(interior-fixed-size-array) i think the four remaining failing tests do things that are not allowed in the new world. Modified: pypy/branch/more-gckinds/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/more-gckinds/pypy/translator/c/funcgen.py (original) +++ pypy/branch/more-gckinds/pypy/translator/c/funcgen.py Wed Sep 13 11:41:33 2006 @@ -474,7 +474,7 @@ return self.generic_set(op, '%s[%s]' % (items, self.expr(op.args[1]))) - def interior_expr(self, args): + def interior_expr(self, args, rettype=False): TYPE = args[0].concretetype.TO expr = '(*(' + self.expr(args[0]) + '))' for arg in args[1:]: @@ -489,7 +489,10 @@ else: expr = '(%s)[%s]'%(expr, self.expr(arg)) TYPE = TYPE.OF - return expr + if rettype: + return expr, TYPE + else: + return expr def OP_GETINTERIORFIELD(self, op): return self.generic_get(op, self.interior_expr(op.args)) @@ -498,8 +501,12 @@ return self.generic_set(op, self.interior_expr(op.args[:-1])) def OP_GETINTERIORARRAYSIZE(self, op): - expr = self.interior_expr(op.args) - return '%s = %s.length;'%(self.expr(op.result), expr) + expr, ARRAY = self.interior_expr(op.args, True) + if isinstance(ARRAY, FixedSizeArray): + return '%s = %d;'%(self.expr(op.result), ARRAY.length) + else: + assert isinstance(ARRAY, Array) + return '%s = %s.length;'%(self.expr(op.result), expr) #OP_SETINTERIORFIELD = OP_BARE_SETINTERIORFIELD From mwh at codespeak.net Wed Sep 13 11:47:27 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 11:47:27 +0200 (CEST) Subject: [pypy-svn] r32249 - pypy/branch/kill-keepalives Message-ID: <20060913094727.4C94410071@code0.codespeak.net> Author: mwh Date: Wed Sep 13 11:47:26 2006 New Revision: 32249 Added: pypy/branch/kill-keepalives/ - copied from r32248, pypy/dist/ Log: branching to kill-keepalives (i want to merge more-gckinds forwards, and the name is now rather wrong) From mwh at codespeak.net Wed Sep 13 11:50:55 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 11:50:55 +0200 (CEST) Subject: [pypy-svn] r32250 - in pypy/branch/kill-keepalives/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/rctypes rpython/test translator/c translator/c/src Message-ID: <20060913095055.D2D3710071@code0.codespeak.net> Author: mwh Date: Wed Sep 13 11:50:52 2006 New Revision: 32250 Modified: pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py pypy/branch/kill-keepalives/pypy/annotation/model.py pypy/branch/kill-keepalives/pypy/annotation/unaryop.py pypy/branch/kill-keepalives/pypy/rpython/llinterp.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py pypy/branch/kill-keepalives/pypy/rpython/rptr.py pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py pypy/branch/kill-keepalives/pypy/translator/c/src/support.h Log: svn merge -r32048:32248 http://codespeak.net/svn/pypy/branch/more-gckinds . Modified: pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py (original) +++ pypy/branch/kill-keepalives/pypy/annotation/bookkeeper.py Wed Sep 13 11:50:52 2006 @@ -11,7 +11,7 @@ SomeInteger, SomeExternalObject, SomeOOInstance, TLS, SomeAddress, \ SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \ SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \ - SomeList, SomeObject, SomeWeakGcAddress + SomeList, SomeObject, SomeWeakGcAddress, lltype_to_annotation from pypy.annotation.classdef import ClassDef, InstanceSource from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF @@ -237,7 +237,7 @@ if isinstance(s_callable, SomeLLADTMeth): adtmeth = s_callable s_callable = self.immutablevalue(adtmeth.func) - args_s = [SomePtr(adtmeth.ll_ptrtype)] + args_s + args_s = [lltype_to_annotation(adtmeth.ll_ptrtype)] + args_s if isinstance(s_callable, SomePBC): s_result = binding(call_op.result, s_ImpossibleValue) self.consider_call_site_for_pbc(s_callable, Modified: pypy/branch/kill-keepalives/pypy/annotation/model.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/annotation/model.py (original) +++ pypy/branch/kill-keepalives/pypy/annotation/model.py Wed Sep 13 11:50:52 2006 @@ -515,6 +515,11 @@ def can_be_none(self): return False +class SomeInteriorPtr(SomePtr): + def __init__(self, ll_ptrtype): + assert isinstance(ll_ptrtype, lltype.InteriorPtr) + self.ll_ptrtype = ll_ptrtype + class SomeLLADTMeth(SomeObject): immutable = True def __init__(self, ll_ptrtype, func): @@ -563,6 +568,13 @@ return s_val.ootype if isinstance(s_val, SomeOOStaticMeth): return s_val.method + if isinstance(s_val, SomeInteriorPtr): + p = s_val.ll_ptrtype + if 0 in p.offsets: + assert list(p.offsets).count(0) == 1 + return lltype.Ptr(lltype.Ptr(p.PARENTTYPE)._interior_ptr_type_with_index(p.TO)) + else: + return lltype.Ptr(p.PARENTTYPE) if isinstance(s_val, SomePtr): return s_val.ll_ptrtype for witness, T in annotation_to_ll_map: @@ -596,6 +608,8 @@ return SomeOOClass(ootype.ROOT) elif isinstance(T, ExternalType): return SomeExternalBuiltin(T) + elif isinstance(T, lltype.InteriorPtr): + return SomeInteriorPtr(T) else: return SomePtr(T) else: @@ -609,13 +623,19 @@ return getbookkeeper().immutablevalue(None) if isinstance(v, MethodType): ll_ptrtype = lltype.typeOf(v.im_self) - assert isinstance(ll_ptrtype, lltype.Ptr) + assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr)) return SomeLLADTMeth(ll_ptrtype, v.im_func) if isinstance(v, FunctionType): # this case should only be for staticmethod instances used in # adtmeths: the getattr() result is then a plain FunctionType object. from pypy.annotation.bookkeeper import getbookkeeper return getbookkeeper().immutablevalue(v) + if isinstance(v, lltype._interior_ptr): + ob = v._parent + if ob is None: + raise RuntimeError + T = lltype.InteriorPtr(lltype.typeOf(ob), v._T, v._offsets) + return SomeInteriorPtr(T) return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ Modified: pypy/branch/kill-keepalives/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/annotation/unaryop.py (original) +++ pypy/branch/kill-keepalives/pypy/annotation/unaryop.py Wed Sep 13 11:50:52 2006 @@ -671,7 +671,7 @@ def call(adtmeth, args): bookkeeper = getbookkeeper() s_func = bookkeeper.immutablevalue(adtmeth.func) - return s_func.call(args.prepend(SomePtr(adtmeth.ll_ptrtype))) + return s_func.call(args.prepend(lltype_to_annotation(adtmeth.ll_ptrtype))) from pypy.rpython.ootypesystem import ootype class __extend__(SomeOOInstance): Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/llinterp.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Wed Sep 13 11:50:52 2006 @@ -486,6 +486,18 @@ op_bare_setfield = op_setfield + def op_setinteriorfield(self, obj, *fieldnamesval): + prefields, finalfield, fieldvalue = fieldnamesval[:-2], fieldnamesval[-2], fieldnamesval[-1] + for o in prefields: + if isinstance(o, str): + obj = getattr(obj, o) + else: + obj = obj[o] + if isinstance(finalfield, str): + setattr(obj, finalfield, fieldvalue) + else: + obj[finalfield] = fieldvalue + def op_getarrayitem(self, array, index): return array[index] Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py Wed Sep 13 11:50:52 2006 @@ -47,7 +47,7 @@ def ref(self, firstitemref): assert isinstance(firstitemref, _arrayitemref) array = firstitemref.array - assert lltype.typeOf(array).TO.OF == self.TYPE + assert lltype.rawTypeOf(array).TO.OF == self.TYPE index = firstitemref.index + self.repeat return _arrayitemref(array, index) @@ -76,7 +76,7 @@ def ref(self, containerref): struct = containerref.get() - if lltype.typeOf(struct).TO != self.TYPE: + if lltype.rawTypeOf(struct).TO != self.TYPE: struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct) return _structfieldref(struct, self.fldname) @@ -136,7 +136,7 @@ def ref(self, arrayref): array = arrayref.get() - assert lltype.typeOf(array).TO == self.TYPE + assert lltype.rawTypeOf(array).TO == self.TYPE return _arrayitemref(array, index=0) def raw_malloc(self, rest, parenttype=None): @@ -164,7 +164,7 @@ def ref(self, arrayref): array = arrayref.get() - assert lltype.typeOf(array).TO == self.TYPE + assert lltype.rawTypeOf(array).TO == self.TYPE return _arraylenref(array) @@ -229,7 +229,7 @@ def __ne__(self, other): return not (self == other) def type(self): - return lltype.typeOf(self.array).TO.OF + return lltype.rawTypeOf(self.array).TO.OF class _arraylenref(object): def __init__(self, array): @@ -264,7 +264,7 @@ def __ne__(self, other): return not (self == other) def type(self): - return getattr(lltype.typeOf(self.struct).TO, self.fieldname) + return getattr(lltype.rawTypeOf(self.struct).TO, self.fieldname) class _obref(object): def __init__(self, ob): Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py Wed Sep 13 11:50:52 2006 @@ -303,8 +303,11 @@ 'getarrayitem': LLOp(sideeffects=False, canrun=True), 'getarraysize': LLOp(canfold=True), 'getsubstruct': LLOp(canfold=True), + 'getinteriorfield': LLOp(canfold=True), # XXX not sure about the foldability... + 'getinteriorarraysize': LLOp(canfold=True), 'getarraysubstruct': LLOp(canfold=True), 'setfield': LLOp(), + 'setinteriorfield': LLOp(), 'bare_setfield': LLOp(), 'setarrayitem': LLOp(), 'cast_pointer': LLOp(canfold=True), Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py Wed Sep 13 11:50:52 2006 @@ -616,6 +616,34 @@ o = self.TO._container_example() return _ptr(self, o, solid=True) + def _interior_ptr_type_with_index(self, TO): + assert self.TO._gckind == 'gc' + if isinstance(TO, Struct): + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}, + adtmeths=TO._adtmeths) + else: + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}) + return R + +class InteriorPtr(LowLevelType): + def __init__(self, PARENTTYPE, TO, offsets): + self.PARENTTYPE = PARENTTYPE + self.TO = TO + self.offsets = tuple(offsets) + def __str__(self): + return '%s (%s).%s'%(self.__class__.__name__, + self.PARENTTYPE._short_name(), + '.'.join(map(str, self.offsets))) + def _example(self): + ob = Ptr(self.PARENTTYPE)._example() + for o in self.offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[0] + return ob # ____________________________________________________________ @@ -647,6 +675,12 @@ return val.lltype() raise TypeError("typeOf(%r object)" % (tp.__name__,)) +def rawTypeOf(val): + if isinstance(val, _interior_ptr): + return Ptr(val._T) + else: + return typeOf(val) + _to_primitive = { Char: chr, UniChar: unichr, @@ -821,13 +855,6 @@ parent, base = parentlink(ptr._obj) return _subarray._makeptr(parent, base + n, ptr._solid) -def _expose(val, solid=False): - """XXX A nice docstring here""" - T = typeOf(val) - if isinstance(T, ContainerType): - val = _ptr(Ptr(T), val, solid=solid) - return val - def parentlink(container): parent = container._parentstructure() if parent is not None: @@ -874,26 +901,14 @@ class UninitializedMemoryAccess(Exception): pass -class _ptr(object): - __slots__ = ('_TYPE', '_T', - '_weak', '_solid', - '_obj0', '__weakref__') +class _abstract_ptr(object): + __slots__ = ('_T',) - def _set_TYPE(self, TYPE): - _ptr._TYPE.__set__(self, TYPE) + # assumes one can access _TYPE, _expose and _obj def _set_T(self, T): _ptr._T.__set__(self, T) - def _set_weak(self, weak): - _ptr._weak.__set__(self, weak) - - def _set_solid(self, solid): - _ptr._solid.__set__(self, solid) - - def _set_obj0(self, obj): - _ptr._obj0.__set__(self, obj) - def _togckind(self): return self._T._gckind @@ -901,19 +916,8 @@ # XXX deprecated interface return self._TYPE._needsgc() # xxx other rules? - def __init__(self, TYPE, pointing_to, solid=False): - self._set_TYPE(TYPE) - self._set_T(TYPE.TO) - self._set_weak(False) - self._setobj(pointing_to, solid) - - def _become(self, other): - assert self._TYPE == other._TYPE - assert not self._weak - self._setobj(other._obj, other._solid) - def __eq__(self, other): - if not isinstance(other, _ptr): + if type(self) is not type(other): raise TypeError("comparing pointer with %r object" % ( type(other).__name__,)) if self._TYPE != other._TYPE: @@ -929,46 +933,11 @@ def __hash__(self): raise TypeError("pointer objects are not hashable") - def __nonzero__(self): - try: - return self._obj is not None - except DelayedPointer: - return True # assume it's not a delayed null - - # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, - # use _obj if necessary instead ! - def _setobj(self, pointing_to, solid=False): - if pointing_to is None: - obj0 = None - elif (solid or self._T._gckind != 'raw' or - isinstance(self._T, FuncType)): - obj0 = pointing_to - else: - self._set_weak(True) - obj0 = pickleable_weakref(pointing_to) - self._set_solid(solid) - self._set_obj0(obj0) - - def _getobj(self): - obj = self._obj0 - if obj is not None: - if self._weak: - obj = obj() - if obj is None: - raise RuntimeError("accessing already garbage collected %r" - % (self._T,)) - if isinstance(obj, _container): - obj._check() - elif isinstance(obj, str) and obj.startswith("delayed!"): - raise DelayedPointer - return obj - _obj = property(_getobj) - def __getattr__(self, field_name): # ! can only return basic or ptr ! if isinstance(self._T, Struct): if field_name in self._T._flds: o = self._obj._getattr(field_name) - return _expose(o, self._solid) + return self._expose(field_name, o) if isinstance(self._T, ContainerType): try: adtmeth = self._T._adtmeths[field_name] @@ -984,20 +953,6 @@ raise AttributeError("%r instance has no field %r" % (self._T, field_name)) - #def _setfirst(self, p): - # if isinstance(self._T, Struct) and self._T._names: - # if not isinstance(p, _ptr) or not isinstance(p._obj, _struct): - # raise InvalidCast(typeOf(p), typeOf(self)) - # field_name = self._T._names[0] - # T1 = self._T._flds[field_name] - # T2 = typeOf(p._obj) - # if T1 != T2: - # raise InvalidCast(typeOf(p), typeOf(self)) - # setattr(self._obj, field_name, p._obj) - # p._obj._setparentstructure(self._obj, 0) - # return - # raise TypeError("%r instance has no first field" % (self._T,)) - def __setattr__(self, field_name, val): if isinstance(self._T, Struct): if field_name in self._T._flds: @@ -1021,7 +976,7 @@ raise TypeError("array slicing not supported") raise IndexError("array index out of bounds") o = self._obj.getitem(i) - return _expose(o, self._solid) + return self._expose(i, o) raise TypeError("%r instance is not an array" % (self._T,)) def __setitem__(self, i, val): @@ -1084,6 +1039,69 @@ __getstate__ = getstate_with_slots __setstate__ = setstate_with_slots +class _ptr(_abstract_ptr): + __slots__ = ('_TYPE', + '_weak', '_solid', + '_obj0', '__weakref__') + + def _set_TYPE(self, TYPE): + _ptr._TYPE.__set__(self, TYPE) + + def _set_weak(self, weak): + _ptr._weak.__set__(self, weak) + + def _set_solid(self, solid): + _ptr._solid.__set__(self, solid) + + def _set_obj0(self, obj): + _ptr._obj0.__set__(self, obj) + + def __init__(self, TYPE, pointing_to, solid=False): + self._set_TYPE(TYPE) + self._set_T(TYPE.TO) + self._set_weak(False) + self._setobj(pointing_to, solid) + + def _become(self, other): + assert self._TYPE == other._TYPE + assert not self._weak + self._setobj(other._obj, other._solid) + + def __nonzero__(self): + try: + return self._obj is not None + except DelayedPointer: + return True # assume it's not a delayed null + + # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, + # use _obj if necessary instead ! + def _setobj(self, pointing_to, solid=False): + if pointing_to is None: + obj0 = None + elif (solid or self._T._gckind != 'raw' or + isinstance(self._T, FuncType)): + obj0 = pointing_to + else: + self._set_weak(True) + obj0 = pickleable_weakref(pointing_to) + self._set_solid(solid) + self._set_obj0(obj0) + + def _getobj(self): + obj = self._obj0 + if obj is not None: + if self._weak: + obj = obj() + if obj is None: + raise RuntimeError("accessing already garbage collected %r" + % (self._T,)) + if isinstance(obj, _container): + obj._check() + elif isinstance(obj, str) and obj.startswith("delayed!"): + raise DelayedPointer + return obj + _obj = property(_getobj) + def _cast_to(self, PTRTYPE): CURTYPE = self._TYPE down_or_up = castable(PTRTYPE, CURTYPE) @@ -1145,8 +1163,67 @@ def _as_obj(self): return self._obj + def _expose(self, offset, val): + """XXX A nice docstring here""" + T = typeOf(val) + if isinstance(T, ContainerType): + if self._T._gckind == 'gc' and T._gckind == 'raw' and not isinstance(T, OpaqueType): + val = _interior_ptr(T, self._obj, [offset]) + else: + val = _ptr(Ptr(T), val, solid=self._solid) + return val + assert not '__dict__' in dir(_ptr) +class _interior_ptr(_abstract_ptr): + __slots__ = ('_parent', '_offsets') + def _set_parent(self, _parent): + _interior_ptr._parent.__set__(self, _parent) + def _set_offsets(self, _offsets): + _interior_ptr._offsets.__set__(self, _offsets) + + def __init__(self, _T, _parent, _offsets): + self._set_T(_T) + #self._set_parent(weakref.ref(_parent)) + self._set_parent(_parent) + self._set_offsets(_offsets) + + def __nonzero__(self): + raise RuntimeError, "do not test an interior pointer for nullity" + + def _get_obj(self): + ob = self._parent + if ob is None: + raise RuntimeError + if isinstance(ob, _container): + ob._check() + for o in self._offsets: + if isinstance(o, str): + ob = ob._getattr(o) + else: + ob = ob.getitem(o) + return ob + _obj = property(_get_obj) + + def _get_TYPE(self): + ob = self._parent + if ob is None: + raise RuntimeError + return InteriorPtr(typeOf(ob), self._T, self._offsets) +## _TYPE = property(_get_TYPE) + + def _expose(self, offset, val): + """XXX A nice docstring here""" + T = typeOf(val) + if isinstance(T, ContainerType): + assert T._gckind == 'raw' + val = _interior_ptr(T, self._parent, self._offsets + [offset]) + return val + + + +assert not '__dict__' in dir(_interior_ptr) + class _container(object): __slots__ = () def _parentstructure(self): Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py Wed Sep 13 11:50:52 2006 @@ -126,6 +126,27 @@ lltype.ContainerType) return getattr(obj, field) +def op_getinteriorfield(obj, *offsets): + checkptr(obj) + ob = obj + for o in offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[o] + assert not isinstance(ob, lltype._interior_ptr) + return ob + +def op_getinteriorarraysize(obj, *offsets): + checkptr(obj) + ob = obj + for o in offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[o] + return len(ob) + def op_getarraysubstruct(array, index): checkptr(array) result = array[index] Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py Wed Sep 13 11:50:52 2006 @@ -75,7 +75,7 @@ # compute the shape of the DICTENTRY structure entryfields = [] - entrymeths = { + adtmeths = { 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) @@ -93,37 +93,41 @@ nullkeymarker = not self.key_repr.can_ll_be_null(s_key) nullvaluemarker = not self.value_repr.can_ll_be_null(s_value) + adtmeths['entry_has_f_everused'] = 0 if nullkeymarker: - entrymeths['everused'] = ll_everused_from_key + adtmeths['entry_everused'] = ll_everused_from_key elif nullvaluemarker: - entrymeths['everused'] = ll_everused_from_value + adtmeths['entry_everused'] = ll_everused_from_value else: entryfields.append(("f_everused", lltype.Bool)) - entrymeths['everused'] = ll_everused_from_flag + adtmeths['entry_everused'] = ll_everused_from_flag + adtmeths['entry_has_f_everused'] = 1 # * if the key or the value can also contain a "dummy" non-null # marker, we use it for deleted entries. rtyper = self.rtyper dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key) + adtmeths['entry_has_f_valid'] = 0 if dummy_obj: - entrymeths['dummy_obj'] = dummy_obj - entrymeths['valid'] = ll_valid_from_key - entrymeths['mark_deleted'] = ll_mark_deleted_in_key + adtmeths['dummy_obj'] = dummy_obj + adtmeths['entry_valid'] = ll_valid_from_key + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_key # the key is overwritten by 'dummy' when the entry is deleted - entrymeths['must_clear_key'] = False + adtmeths['must_clear_key'] = False else: dummy_obj = self.value_repr.get_ll_dummyval_obj(rtyper, s_value) if dummy_obj: - entrymeths['dummy_obj'] = dummy_obj - entrymeths['valid'] = ll_valid_from_value - entrymeths['mark_deleted'] = ll_mark_deleted_in_value + adtmeths['dummy_obj'] = dummy_obj + adtmeths['entry_valid'] = ll_valid_from_value + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted - entrymeths['must_clear_value'] = False + adtmeths['must_clear_value'] = False else: entryfields.append(("f_valid", lltype.Bool)) - entrymeths['valid'] = ll_valid_from_flag - entrymeths['mark_deleted'] = ll_mark_deleted_in_flag + adtmeths['entry_has_f_valid'] = 1 + adtmeths['entry_valid'] = ll_valid_from_flag + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_flag # * the value entryfields.append(("value", self.DICTVALUE)) @@ -133,15 +137,18 @@ fasthashfn = None else: fasthashfn = self.key_repr.get_ll_fasthash_function() + + adtmeths['entry_has_f_hash'] = 0 if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) - entrymeths['hash'] = ll_hash_from_cache + adtmeths['entry_has_f_hash'] = 1 + adtmeths['hash'] = ll_hash_from_cache else: - entrymeths['hash'] = ll_hash_recomputed - entrymeths['fasthashfn'] = fasthashfn + adtmeths['hash'] = ll_hash_recomputed + adtmeths['fasthashfn'] = fasthashfn # Build the lltype data structures - self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths, + self.DICTENTRY = lltype.Struct("dictentry", #adtmeths=entrymeths, *entryfields) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) fields = [ ("num_items", lltype.Signed), @@ -151,13 +158,13 @@ self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr() fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype), ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ]) - adtmeths = { + adtmeths.update({ 'keyhash': ll_keyhash_custom, 'keyeq': ll_keyeq_custom, 'r_rdict_eqfn': self.r_rdict_eqfn, 'r_rdict_hashfn': self.r_rdict_hashfn, 'paranoia': True, - } + }) else: # figure out which functions must be used to hash and compare ll_keyhash = self.key_repr.get_ll_hash_function() @@ -165,11 +172,11 @@ ll_keyhash = lltype.staticAdtMethod(ll_keyhash) if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) - adtmeths = { + adtmeths.update({ 'keyhash': ll_keyhash, 'keyeq': ll_keyeq, 'paranoia': False, - } + }) self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) @@ -331,47 +338,47 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. -def ll_everused_from_flag(entry): - return entry.f_everused +def ll_everused_from_flag(d, i): + return d.entries[i].f_everused -def ll_everused_from_key(entry): - return bool(entry.key) +def ll_everused_from_key(d, i): + return bool(d.entries[i].key) -def ll_everused_from_value(entry): - return bool(entry.value) +def ll_everused_from_value(d, i): + return bool(d.entries[i].value) -def ll_valid_from_flag(entry): - return entry.f_valid - -def ll_mark_deleted_in_flag(entry): - entry.f_valid = False - -def ll_valid_from_key(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - return entry.everused() and entry.key != dummy - -def ll_mark_deleted_in_key(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - entry.key = dummy - -def ll_valid_from_value(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - return entry.everused() and entry.value != dummy - -def ll_mark_deleted_in_value(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - entry.value = dummy - -def ll_hash_from_cache(entry): - return entry.f_hash - -def ll_hash_recomputed(entry): - ENTRY = lltype.typeOf(entry).TO - return ENTRY.fasthashfn(entry.key) +def ll_valid_from_flag(d, i): + return d.entries[i].f_valid + +def ll_mark_deleted_in_flag(d, i): + d.entries[i].f_valid = False + +def ll_valid_from_key(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + return d.entry_everused(i) and d.entries[i].key != dummy + +def ll_mark_deleted_in_key(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + d.entries[i].key = dummy + +def ll_valid_from_value(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + return d.entry_everused(i) and d.entries[i].value != dummy + +def ll_mark_deleted_in_value(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + d.entries[i].value = dummy + +def ll_hash_from_cache(d, i): + return d.entries[i].f_hash + +def ll_hash_recomputed(d, i): + DICT = lltype.typeOf(d).TO + return DICT.fasthashfn(d.entries[i].key) def ll_keyhash_custom(d, key): DICT = lltype.typeOf(d).TO @@ -389,28 +396,29 @@ return bool(d) and d.num_items != 0 def ll_dict_getitem(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) - if entry.valid(): - return entry.value + i = ll_dict_lookup(d, key, d.keyhash(key)) + if d.entry_valid(i): + return d.entries[i].value else: raise KeyError def ll_dict_setitem(d, key, value): hash = d.keyhash(key) - entry = ll_dict_lookup(d, key, hash) - everused = entry.everused() - valid = entry.valid() + i = ll_dict_lookup(d, key, hash) + entry = d.entries[i] + everused = d.entry_everused(i) + valid = d.entry_valid(i) # set up the new entry - ENTRY = lltype.typeOf(entry).TO + DICT = lltype.typeOf(d).TO entry.value = value if valid: return entry.key = key - if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash - if hasattr(ENTRY, 'f_valid'): entry.f_valid = True + if DICT.entry_has_f_hash: entry.f_hash = hash + if DICT.entry_has_f_valid: entry.f_valid = True d.num_items += 1 if not everused: - if hasattr(ENTRY, 'f_everused'): entry.f_everused = True + if DICT.entry_has_f_everused: entry.f_everused = True d.num_pristine_entries -= 1 if d.num_pristine_entries <= len(d.entries) / 3: ll_dict_resize(d) @@ -421,53 +429,77 @@ # the dict contains no deleted entries. This routine has the advantage # of never calling d.keyhash() and d.keyeq(), so it cannot call back # to user code. ll_dict_insertclean() doesn't resize the dict, either. - entry = ll_dict_lookup_clean(d, hash) - ENTRY = lltype.typeOf(entry).TO + entry = d.entries[ll_dict_lookup_clean(d, hash)] + DICT = lltype.typeOf(d).TO entry.value = value entry.key = key - if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash - if hasattr(ENTRY, 'f_valid'): entry.f_valid = True - if hasattr(ENTRY, 'f_everused'): entry.f_everused = True + if DICT.entry_has_f_hash: entry.f_hash = hash + if DICT.entry_has_f_valid: entry.f_valid = True + if DICT.entry_has_f_everused: entry.f_everused = True d.num_items += 1 d.num_pristine_entries -= 1 def ll_dict_delitem(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) - if not entry.valid(): + i = ll_dict_lookup(d, key, d.keyhash(key)) + if not d.entry_valid(i): raise KeyError - entry.mark_deleted() + entry = d.entries[i] + d.mark_entry_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers - ENTRY = lltype.typeOf(entry).TO - if ENTRY.must_clear_key: + DICT = lltype.typeOf(d).TO + if DICT.must_clear_key: key = entry.key # careful about destructor side effects: # keep key alive until entry.value has also # been zeroed (if it must be) - entry.key = lltype.nullptr(ENTRY.key.TO) - if ENTRY.must_clear_value: - entry.value = lltype.nullptr(ENTRY.value.TO) + entry.key = lltype.nullptr(DICT.entries.OF.key.TO) + if DICT.must_clear_value: + entry.value = lltype.nullptr(DICT.entries.OF.value.TO) num_entries = len(d.entries) if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4: ll_dict_resize(d) def ll_dict_resize(d): old_entries = d.entries - old_size = len(old_entries) + old_size = len(old_entries) # make a 'new_size' estimate and shrink it if there are many # deleted entry markers new_size = old_size * 2 while new_size > DICT_INITSIZE and d.num_items < new_size / 4: new_size /= 2 - d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True) - d.num_items = 0 - d.num_pristine_entries = new_size + new_entries = lltype.malloc(lltype.typeOf(d).TO.entries.TO, new_size, zero=True) + new_num_items = 0 + new_num_pristine_entries = new_size i = 0 while i < old_size: - entry = old_entries[i] - if entry.valid(): - ll_dict_insertclean(d, entry.key, entry.value, entry.hash()) + entry = d.entries[i] + if d.entry_valid(i): + + # AAAAAAAAAAA + hash = d.hash(i) + + old_entries = d.entries + old_num_items = d.num_items + old_num_pristine_entries = d.num_pristine_entries + d.entries = new_entries + d.num_items = new_num_items + d.num_pristine_entries = new_num_pristine_entries + + ll_dict_insertclean(d, entry.key, entry.value, hash) + + new_entries = d.entries + new_num_items = d.num_items + new_num_pristine_entries = d.num_pristine_entries + d.entries = old_entries + d.num_items = old_num_items + d.num_pristine_entries = old_num_pristine_entries + i += 1 + d.entries = new_entries + d.num_items = new_num_items + d.num_pristine_entries = new_num_pristine_entries + # ------- a port of CPython's dictobject.c's lookdict implementation ------- PERTURB_SHIFT = 5 @@ -478,26 +510,28 @@ i = r_uint(hash & mask) # do the first try before any looping entry = entries[i] - if entry.valid(): + found_freeslot = False + freeslot_index = r_uint(0) + if d.entry_valid(i): checkingkey = entry.key if checkingkey == key: - return entry # found the entry - if d.keyeq is not None and entry.hash() == hash: + return i # found the entry + if d.keyeq is not None and d.hash(i) == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not entry.valid() or entry.key != checkingkey): + not d.entry_valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: start over return ll_dict_lookup(d, key, hash) if found: - return entry # found the entry - freeslot = lltype.nullptr(lltype.typeOf(entry).TO) - elif entry.everused(): - freeslot = entry + return i # found the entry + elif d.entry_everused(i): + freeslot_index = i + found_freeslot = True else: - return entry # pristine entry -- lookup failed + return i # pristine entry -- lookup failed # In the loop, a deleted entry (everused and not valid) is by far # (factor of 100s) the least likely outcome, so test for that last. @@ -505,26 +539,30 @@ while 1: i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] - if not entry.everused(): - return freeslot or entry - elif entry.valid(): + if not d.entry_everused(i): + if found_freeslot: + return freeslot_index + else: + return i + elif d.entry_valid(i): checkingkey = entry.key if checkingkey == key: - return entry - if d.keyeq is not None and entry.hash() == hash: + return i + if d.keyeq is not None and d.hash(i) == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not entry.valid() or entry.key != checkingkey): + not d.entry_valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: # start over return ll_dict_lookup(d, key, hash) if found: - return entry # found the entry - elif not freeslot: - freeslot = entry + return i + elif not found_freeslot: + freeslot_index = i + found_freeslot = True perturb >>= PERTURB_SHIFT def ll_dict_lookup_clean(d, hash): @@ -536,11 +574,11 @@ i = r_uint(hash & mask) entry = entries[i] perturb = r_uint(hash) - while entry.everused(): + while d.entry_everused(i): i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] perturb >>= PERTURB_SHIFT - return entry + return i # ____________________________________________________________ # @@ -614,8 +652,9 @@ entries_len = len(entries) while index < entries_len: entry = entries[index] + i = index index = index + 1 - if entry.valid(): + if dict.entry_valid(i): iter.index = index if RETURNTYPE is lltype.Void: return None @@ -625,6 +664,9 @@ r.item1 = recast(RETURNTYPE.TO.item1, entry.value) return r elif func is dum_keys: + from pypy.rpython.lltypesystem.lloperation import llop + from pypy.rpython.lltypesystem.lltype import Void + llop.debug_print(Void, entry.key) return entry.key elif func is dum_values: return entry.value @@ -636,16 +678,16 @@ # methods def ll_get(dict, key, default): - entry = ll_dict_lookup(dict, key, dict.keyhash(key)) - if entry.valid(): - return entry.value + i = ll_dict_lookup(dict, key, dict.keyhash(key)) + if dict.entry_valid(i): + return dict.entries[i].value else: return default def ll_setdefault(dict, key, default): - entry = ll_dict_lookup(dict, key, dict.keyhash(key)) - if entry.valid(): - return entry.value + i = ll_dict_lookup(dict, key, dict.keyhash(key)) + if dict.entry_valid(i): + return dict.entries[i].value else: ll_dict_setitem(dict, key, default) return default @@ -663,12 +705,12 @@ while i < dictsize: d_entry = d.entries[i] entry = dict.entries[i] - ENTRY = lltype.typeOf(entry).TO + DICT = lltype.typeOf(dict).TO d_entry.key = entry.key - if hasattr(ENTRY, 'f_valid'): d_entry.f_valid = entry.f_valid - if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused + if DICT.entry_has_f_valid: d_entry.f_valid = entry.f_valid + if DICT.entry_has_f_everused: d_entry.f_everused = entry.f_everused d_entry.value = entry.value - if hasattr(ENTRY, 'f_hash'): d_entry.f_hash = entry.f_hash + if DICT.entry_has_f_hash: d_entry.f_hash = entry.f_hash i += 1 return d @@ -686,7 +728,7 @@ i = 0 while i < d2len: entry = entries[i] - if entry.valid(): + if dic2.entry_valid(i): ll_dict_setitem(dic1, entry.key, entry.value) i += 1 @@ -710,7 +752,7 @@ p = 0 while i < dlen: entry = entries[i] - if entry.valid(): + if dic.entry_valid(i): ELEM = lltype.typeOf(items).TO.OF if ELEM is not lltype.Void: if func is dum_items: @@ -727,5 +769,5 @@ return res def ll_contains(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) - return entry.valid() + i = ll_dict_lookup(d, key, d.keyhash(key)) + return d.entry_valid(i) Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rstr.py Wed Sep 13 11:50:52 2006 @@ -85,10 +85,7 @@ cstr = inputconst(Void, STR) v_result = llops.genop('malloc_varsize', [cstr, v_len], resulttype=Ptr(STR)) - cchars = inputconst(Void, "chars") - v_chars = llops.genop('getsubstruct', [v_result, cchars], - resulttype=Ptr(STR.chars)) - llops.gencapicall('PyString_ToLLCharArray', [v, v_chars]) + llops.gencapicall('PyString_ToRPyString', [v, v_result]) string_repr = llops.rtyper.type_system.rstr.string_repr v_result = llops.convertvar(v_result, string_repr, r_to) return v_result @@ -99,15 +96,11 @@ string_repr = llops.rtyper.type_system.rstr.string_repr v = llops.convertvar(v, r_from, string_repr) cchars = inputconst(Void, "chars") - v_chars = llops.genop('getsubstruct', [v, cchars], - resulttype=Ptr(STR.chars)) - v_size = llops.genop('getarraysize', [v_chars], - resulttype=Signed) # xxx put in table - return llops.gencapicall('PyString_FromLLCharArrayAndSize', - [v_chars, v_size], + return llops.gencapicall('PyString_FromRPyString', + [v], resulttype=pyobj_repr, - _callable= lambda chars, sz: pyobjectptr(''.join(chars))) + _callable= lambda v: pyobjectptr(''.join(v.chars))) def mallocstr(length): r = malloc(STR, length) Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_lltype.py Wed Sep 13 11:50:52 2006 @@ -1,7 +1,5 @@ from pypy.rpython.lltypesystem.lltype import * - -def isweak(p, T): - return p._weak and typeOf(p).TO == T +import py def test_basics(): S0 = GcStruct("s0", ('a', Signed), ('b', Signed)) @@ -24,7 +22,7 @@ x = malloc(Ar,3) print x assert typeOf(x) == Ptr(Ar) - assert isweak(x[0], Ar.OF) + py.test.raises(TypeError, "typeOf(x[0])") x[0].v = 1 x[1].v = 2 x[2].v = 3 @@ -94,9 +92,7 @@ s1 = malloc(S1, 4) s1.a = 0 assert s1.a == 0 - assert isweak(s1.rest, S1.rest) assert len(s1.rest) == 4 - assert isweak(s1.rest[0], S1.rest.OF) s1.rest[0].v = 0 assert typeOf(s1.rest[0].v) == Signed assert s1.rest[0].v == 0 @@ -118,11 +114,13 @@ S2 = Struct("s2", ('s3', S3)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1) - assert isweak(p1.sub1, S2) - assert isweak(p1.sub2, S2) - assert isweak(p1.sub1.s3, S3) + py.test.raises(TypeError, "typeOf(p1.sub1)") + # _T isn't really a public API, but there's not much else to test. + assert p1.sub1._T == S2 + assert p1.sub2._T == S2 + assert p1.sub1.s3._T == S3 p2 = p1.sub1 - assert isweak(p2.s3, S3) + assert p2.s3._T == S3 def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) @@ -130,7 +128,7 @@ S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2)) p1 = malloc(S0) assert typeOf(p1.sub1) == Ptr(S1) - assert isweak(p1.sub2, S2) + py.test.raises(TypeError, "typeOf(p1.sub2)") def test_cast_simple_widening(): S2 = Struct("s2", ('a', Signed)) @@ -202,6 +200,7 @@ py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") def test_best_effort_gced_parent_detection(): + py.test.skip("test not relevant any more") S2 = Struct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) p1 = malloc(S1, 1) @@ -216,6 +215,7 @@ py.test.raises(RuntimeError, "p3[0]") def test_best_effort_gced_parent_for_arrays(): + py.test.skip("test not relevant any more") A1 = GcArray(('v', Signed)) p1 = malloc(A1, 10) p1[5].v=3 @@ -422,6 +422,8 @@ assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) def test_flavor_malloc(): + def isweak(p, T): + return p._weak and typeOf(p).TO == T S = Struct('s', ('x', Signed)) py.test.raises(TypeError, malloc, S) p = malloc(S, flavor="raw") Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/test/test_picklelltype.py Wed Sep 13 11:50:52 2006 @@ -1,9 +1,6 @@ from pypy.rpython.lltypesystem.lltype import * -import pickle - -def isweak(p, T): - return p._weak and typeOf(p).TO == T +import pickle, py def test_pickle_types(): S0 = GcStruct("s0", ('a', Signed), ('b', Signed)) @@ -33,7 +30,6 @@ p_x = pickle.dumps(x) r_x = pickle.loads(p_x) assert typeOf(x) == Ptr(Ar) - assert isweak(x[0], Ar.OF) assert typeOf(x[0].v) == Signed assert [x[z].v for z in range(3)] == [1, 2, 3] # @@ -98,9 +94,7 @@ p_s1 = pickle.dumps(s1) r_s1 = pickle.loads(p_s1) assert r_s1.a == 0 - assert isweak(r_s1.rest, S1.rest) assert len(r_s1.rest) == 4 - assert isweak(r_s1.rest[0], S1.rest.OF) assert typeOf(r_s1.rest[0].v) == Signed assert r_s1.rest[0].v == 0 py.test.raises(IndexError, "r_s1.rest[4]") @@ -120,11 +114,13 @@ p1 = malloc(S1) p_p1 = pickle.dumps(p1) r_p1 = pickle.loads(p_p1) - assert isweak(r_p1.sub1, S2) - assert isweak(r_p1.sub2, S2) - assert isweak(r_p1.sub1.s3, S3) + py.test.raises(TypeError, "typeOf(p1.sub1)") + # _T isn't really a public API, but there's not much else to test. + assert r_p1.sub1._T == S2 + assert r_p1.sub2._T == S2 + assert r_p1.sub1.s3._T == S3 r_p2 = r_p1.sub1 - assert isweak(r_p2.s3, S3) + assert r_p2.s3._T == S3 def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) @@ -133,7 +129,7 @@ p1 = malloc(S0) r_p1 = pickle.loads(pickle.dumps(p1)) assert typeOf(r_p1.sub1) == Ptr(S1) - assert isweak(r_p1.sub2, S2) + py.test.raises(TypeError, "typeOf(r_p1.sub2)") def test_cast_simple_widening(): S2 = Struct("s2", ('a', Signed)) @@ -148,6 +144,7 @@ assert p4 == r_p1 def test_best_effort_gced_parent_detection(): + py.test.skip("test not relevant any more") S2 = Struct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) p1 = malloc(S1, 1) @@ -167,6 +164,7 @@ py.test.raises(RuntimeError, "r_p3[0]") def test_best_effort_gced_parent_for_arrays(): + py.test.skip("test not relevant any more") A1 = GcArray(('v', Signed)) p1 = malloc(A1, 10) for i in range(10): @@ -340,6 +338,8 @@ assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) def test_flavor_malloc(): + def isweak(p, T): + return p._weak and typeOf(p).TO == T S = Struct('s', ('x', Signed)) py.test.raises(TypeError, malloc, S) p = malloc(S, flavor="raw") Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/convertlltype.py Wed Sep 13 11:50:52 2006 @@ -34,7 +34,7 @@ self.query_types = qt def convert(self, val_or_ptr, inline_to_ptr=None): - TYPE = lltype.typeOf(val_or_ptr) + TYPE = lltype.rawTypeOf(val_or_ptr) if isinstance(TYPE, lltype.Primitive): assert inline_to_ptr is None return get_real_value(val_or_ptr) @@ -58,7 +58,7 @@ ptr = self.converted[_array] assert inline_to_ptr is None or ptr == inline_to_ptr return ptr - TYPE = lltype.typeOf(_array) + TYPE = lltype.rawTypeOf(_array) arraylength = len(_array.items) size = sizeof(TYPE, arraylength) if inline_to_ptr is not None: @@ -95,7 +95,7 @@ return getattr(ptr, _struct._parent_index) else: return ptr[_struct._parent_index] - TYPE = lltype.typeOf(_struct) + TYPE = lltype.rawTypeOf(_struct) if TYPE._arrayfld is not None: inlinedarraylength = len(getattr(_struct, TYPE._arrayfld).items) size = sizeof(TYPE, inlinedarraylength) @@ -127,7 +127,7 @@ def convert_pointer(self, _ptr, inline_to_ptr): assert inline_to_ptr is None, "can't inline pointer" - TYPE = lltype.typeOf(_ptr) + TYPE = lltype.rawTypeOf(_ptr) if _ptr._obj is not None: return self.convert(_ptr._obj) else: @@ -135,7 +135,7 @@ def convert_object(self, _obj, inline_to_ptr): assert inline_to_ptr is None, "can't inline function or pyobject" - return simulatorptr(lltype.Ptr(lltype.typeOf(_obj)), + return simulatorptr(lltype.Ptr(lltype.rawTypeOf(_obj)), lladdress.get_address_of_object(_obj)) def collect_constants_and_types(graphs): constants = {} @@ -190,7 +190,7 @@ continue elif isinstance(cand, str): continue - elif isinstance(lltype.typeOf(cand), lltype.Primitive): + elif isinstance(lltype.rawTypeOf(cand), lltype.Primitive): continue elif cand in seen: continue Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Wed Sep 13 11:50:52 2006 @@ -258,28 +258,18 @@ raise NotImplementedError("gc_protect does not make sense for this gc") def replace_setfield(self, op, livevars, block): - if not var_ispyobj(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getfield", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) - result.extend(self.pop_alive(oldval)) - return result - - def replace_setarrayitem(self, op, livevars, block): - if not var_ispyobj(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getarrayitem", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) + if not var_ispyobj(op.args[-1]): + return [SpaceOperation("bare_" + op.opname, op.args, op.result)] + oldval = varoftype(op.args[-1].concretetype) + result = [] + result.append(SpaceOperation("g" + op.opname[1:], + op.args[:-1], oldval)) + result.extend(self.push_alive(op.args[-1])) + result.append(SpaceOperation("bare_" + op.opname, op.args, op.result)) result.extend(self.pop_alive(oldval)) return result + replace_setinteriorfield = replace_setfield + replace_setarrayitem = replace_setfield def replace_safe_call(self, op, livevars, block): return [SpaceOperation("direct_call", op.args, op.result)] @@ -502,29 +492,20 @@ newops[-1].result = op.result return newops - def replace_setfield(self, op, livevars, block): - if not var_needsgc(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getfield", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) - result.extend(self.pop_alive(oldval)) - return result - def replace_setarrayitem(self, op, livevars, block): - if not var_needsgc(op.args[2]): - return [op] - oldval = varoftype(op.args[2].concretetype) - getoldvalop = SpaceOperation("getarrayitem", - [op.args[0], op.args[1]], oldval) - result = [getoldvalop] - result.extend(self.push_alive(op.args[2])) - result.append(op) + def replace_setfield(self, op, livevars, block): + if not var_needsgc(op.args[-1]): + return [SpaceOperation("bare_" + op.opname, op.args, op.result)] + oldval = varoftype(op.args[-1].concretetype) + result = [] + result.append(SpaceOperation("g" + op.opname[1:], + op.args[:-1], oldval)) + result.extend(self.push_alive(op.args[-1])) + result.append(SpaceOperation("bare_" + op.opname, op.args, op.result)) result.extend(self.pop_alive(oldval)) return result + replace_setinteriorfield = replace_setfield + replace_setarrayitem = replace_setfield ## -- maybe add this for tests and for consistency -- ## def consider_constant(self, TYPE, value): @@ -1349,10 +1330,15 @@ c_null = Constant(lltype.nullptr(FIELD.TO), FIELD) llops.genop('bare_setfield', [v, c_name, c_null]) elif isinstance(FIELD, lltype.Struct): - c_name = Constant(name, lltype.Void) - v1 = llops.genop('getsubstruct', [v, c_name], - resulttype = lltype.Ptr(FIELD)) - gen_zero_gc_pointers(FIELD, v1, llops) + # XXX this is insufficient! + for name2 in FIELD._names: + FIELD_TYPE = getattr(FIELD, name2) + if isinstance(FIELD_TYPE, lltype.Ptr) and FIELD_TYPE._needsgc(): + c_name = Constant(name, lltype.Void) + v1 = llops.genop('getsubstruct', [v, c_name], + resulttype = lltype.Ptr(FIELD)) + gen_zero_gc_pointers(FIELD, v1, llops) + break # ____________________________________________________________ Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Wed Sep 13 11:50:52 2006 @@ -266,8 +266,8 @@ def reccopy(source, dest): # copy recursively a structure or array onto another. - T = lltype.typeOf(source).TO - assert T == lltype.typeOf(dest).TO + T = lltype.rawTypeOf(source).TO + assert T == lltype.rawTypeOf(dest).TO if isinstance(T, (lltype.Array, lltype.FixedSizeArray)): assert len(source) == len(dest) ITEMTYPE = T.OF @@ -295,7 +295,7 @@ raise TypeError(T) def reccopy_arrayitem(source, destarray, destindex): - ITEMTYPE = lltype.typeOf(destarray).TO.OF + ITEMTYPE = lltype.rawTypeOf(destarray).TO.OF if isinstance(ITEMTYPE, lltype.Primitive): destarray[destindex] = source else: Modified: pypy/branch/kill-keepalives/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rptr.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rptr.py Wed Sep 13 11:50:52 2006 @@ -2,7 +2,8 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow import model as flowmodel from pypy.rpython.lltypesystem.lltype import \ - Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray + Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray, \ + InteriorPtr, OpaqueType from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr @@ -19,6 +20,9 @@ ## else: return self.__class__, self.ll_ptrtype +class __extend__(annmodel.SomeInteriorPtr): + def rtyper_makerepr(self, rtyper): + return InteriorPtrRepr(self.ll_ptrtype) class PtrRepr(Repr): @@ -32,7 +36,11 @@ return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): - newopname = 'getsubstruct' + if isinstance(hop.r_result, InteriorPtrRepr): + return hop.genop('same_as', [hop.inputarg(self, 0)], + resulttype=self.lowleveltype) + else: + newopname = 'getsubstruct' else: newopname = 'getfield' vlist = hop.inputargs(self, Void) @@ -93,7 +101,18 @@ ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, ContainerType): - newopname = 'getarraysubstruct' + if isinstance(hop.r_result, InteriorPtrRepr): + v_array, v_index = hop.inputargs(r_ptr, Signed) + INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) + v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], + resulttype = Ptr(INTERIOR_PTR_TYPE)) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('ptr', Void), v_array]) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('index', Void), v_index]) + return v_interior_ptr + else: + newopname = 'getarraysubstruct' else: newopname = 'getarrayitem' vlist = hop.inputargs(r_ptr, Signed) @@ -154,15 +173,16 @@ class __extend__(annmodel.SomeLLADTMeth): def rtyper_makerepr(self, rtyper): - return LLADTMethRepr(self) + return LLADTMethRepr(self, rtyper) def rtyper_makekey(self): return self.__class__, self.ll_ptrtype, self.func class LLADTMethRepr(Repr): - def __init__(self, adtmeth): + def __init__(self, adtmeth, rtyper): self.func = adtmeth.func - self.lowleveltype = adtmeth.ll_ptrtype + self.ll_ptrtype = adtmeth.ll_ptrtype + self.lowleveltype = rtyper.getrepr(annmodel.lltype_to_annotation(adtmeth.ll_ptrtype)).lowleveltype def rtype_simple_call(self, hop): hop2 = hop.copy() @@ -170,7 +190,7 @@ s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func) v_ptr = hop2.args_v[0] hop2.r_s_popfirstarg() - hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.lowleveltype)) + hop2.v_s_insertfirstarg(v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype)) hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func) return hop2.dispatch() @@ -181,4 +201,119 @@ return v return NotImplemented - + +class InteriorPtrRepr(Repr): + def __init__(self, ptrtype): + assert isinstance(ptrtype, InteriorPtr) + self.v_offsets = [] + numitemoffsets = 0 + for i, offset in enumerate(ptrtype.offsets): + if isinstance(offset, int): + numitemoffsets += 1 + self.v_offsets.append(None) + else: + assert isinstance(offset, str) + self.v_offsets.append(flowmodel.Constant(offset, Void)) + self.parentptrtype = Ptr(ptrtype.PARENTTYPE) + self.resulttype = Ptr(ptrtype.TO) + assert numitemoffsets <= 1 + if numitemoffsets > 0: + self.lowleveltype = Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO)) + else: + self.lowleveltype = self.parentptrtype + + def getinteriorfieldargs(self, hop, v_self): + vlist = [] + if None in self.v_offsets: + INTERIOR_TYPE = v_self.concretetype.TO + nameiter = iter(INTERIOR_TYPE._names) + name = nameiter.next() + vlist.append( + hop.genop('getfield', + [v_self, flowmodel.Constant(name, Void)], + resulttype=INTERIOR_TYPE._flds[name])) + else: + vlist.append(v_self) + for v_offset in self.v_offsets: + if v_offset is None: + name = nameiter.next() + vlist.append( + hop.genop('getfield', + [v_self, flowmodel.Constant(name, Void)], + resulttype=INTERIOR_TYPE._flds[name])) + else: + vlist.append(v_offset) + if None in self.v_offsets: + try: + nameiter.next() + except StopIteration: + pass + else: + assert False + return vlist + + def rtype_len(self, hop): + v_self, = hop.inputargs(self) + vlist = self.getinteriorfieldargs(hop, v_self) + return hop.genop('getinteriorarraysize', vlist, + resulttype=Signed) + + def rtype_getattr(self, hop): + attr = hop.args_s[1].const + if isinstance(hop.s_result, annmodel.SomeLLADTMeth): + return hop.inputarg(hop.r_result, arg=0) + FIELD_TYPE = getattr(self.resulttype.TO, attr) + if isinstance(FIELD_TYPE, ContainerType): + return hop.genop('same_as', [hop.inputarg(self, 0)], + resulttype=self.lowleveltype) + else: + v_self, v_attr = hop.inputargs(self, Void) + vlist = self.getinteriorfieldargs(hop, v_self) + [v_attr] + return hop.genop('getinteriorfield', vlist, + resulttype=hop.r_result.lowleveltype) + + def rtype_setattr(self, hop): + attr = hop.args_s[1].const + FIELD_TYPE = getattr(self.resulttype.TO, attr) + assert not isinstance(FIELD_TYPE, ContainerType) + v_self, v_fieldname, v_value = hop.inputargs(self, Void, hop.args_r[2]) + vlist = self.getinteriorfieldargs(hop, v_self) + [v_fieldname, v_value] + return hop.genop('setinteriorfield', vlist) + + + + +class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)): + def rtype_getitem((r_ptr, r_item), hop): + ARRAY = r_ptr.resulttype.TO + ITEM_TYPE = ARRAY.OF + if isinstance(ITEM_TYPE, ContainerType): + v_array, v_index = hop.inputargs(r_ptr, Signed) + INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) + v_interior_ptr = hop.genop('malloc', [flowmodel.Constant(INTERIOR_PTR_TYPE, Void)], + resulttype = Ptr(INTERIOR_PTR_TYPE)) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('ptr', Void), v_array]) + hop.genop('setfield', + [v_interior_ptr, flowmodel.Constant('index', Void), v_index]) + return v_interior_ptr + else: + v_self, v_index = hop.inputargs(r_ptr, Signed) + vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index] + return hop.genop('getinteriorfield', vlist, + resulttype=ITEM_TYPE) + + def rtype_setitem((r_ptr, r_index), hop): + ARRAY = r_ptr.resulttype.TO + ITEM_TYPE = ARRAY.OF + assert not isinstance(ITEM_TYPE, ContainerType) + v_self, v_index, v_value = hop.inputargs(r_ptr, Signed, hop.args_r[2]) + vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index, v_value] + hop.genop('setinteriorfield', vlist) + +class __extend__(pairtype(InteriorPtrRepr, LLADTMethRepr)): + + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == r_to.lowleveltype: + return v + return NotImplemented Modified: pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/test/test_rdict.py Wed Sep 13 11:50:52 2006 @@ -548,7 +548,7 @@ res = self.interpret(func2, [ord(x), ord(y)]) for i in range(len(res.entries)): - assert not (res.entries[i].everused() and not res.entries[i].valid()) + assert not (res.entry_everused(i) and not res.entry_valid(i)) def func3(c0, c1, c2, c3, c4, c5, c6, c7): d = {} @@ -568,7 +568,7 @@ for i in range(rdict.DICT_INITSIZE)]) count_frees = 0 for i in range(len(res.entries)): - if not res.entries[i].everused(): + if not res.entry_everused(i): count_frees += 1 assert count_frees >= 3 @@ -659,8 +659,8 @@ res = self.interpret(f, []) assert res.item0 == True DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy + assert not DICT.entry_has_f_everused# non-None string keys + assert not DICT.entry_has_f_valid # strings have a dummy def test_opt_nullvaluemarker(self): def f(n): @@ -670,8 +670,8 @@ res = self.interpret(f, [-5]) assert res.item0 == 4 DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy + assert not DICT.entry_has_f_everused# non-None string keys + assert not DICT.entry_has_f_valid # strings have a dummy def test_opt_nonullmarker(self): class A: @@ -687,8 +687,8 @@ res = self.interpret(f, [-5]) assert res.item0 == -5441 DICT = lltype.typeOf(res.item1).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance + assert DICT.entry_has_f_everused # can-be-None A instances + assert not DICT.entry_has_f_valid# with a dummy A instance res = self.interpret(f, [6]) assert res.item0 == -5441 @@ -703,8 +703,8 @@ assert res.item0 == 1 assert res.item1 == 24 DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1 + assert DICT.entry_has_f_everused # all ints can be zero + assert not DICT.entry_has_f_valid# nonneg int: dummy -1 def test_opt_no_dummy(self): def f(n): @@ -716,8 +716,8 @@ assert res.item0 == 1 assert res.item1 == -24 DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available + assert DICT.entry_has_f_everused # all ints can be zero + assert DICT.entry_has_f_valid # no dummy available def test_opt_multiple_identical_dicts(self): def f(n): @@ -748,7 +748,3 @@ return dic[i] res = self.interpret(func, [5]) assert res.ll_get(5) is res - - - - Modified: pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py Wed Sep 13 11:50:52 2006 @@ -204,3 +204,63 @@ fptr(*(x,y)) py.test.raises(TypeError, "interpret(wrong, [1, 2])") + + +def test_interior_ptr(): + S = Struct("S", ('x', Signed)) + T = GcStruct("T", ('s', S)) + def f(): + t = malloc(T) + t.s.x = 1 + return t.s.x + res = interpret(f, []) + assert res == 1 + +def test_interior_ptr_with_index(): + S = Struct("S", ('x', Signed)) + T = GcArray(S) + def f(): + t = malloc(T, 1) + t[0].x = 1 + return t[0].x + res = interpret(f, []) + assert res == 1 + +def test_interior_ptr_with_field_and_index(): + S = Struct("S", ('x', Signed)) + T = GcStruct("T", ('items', Array(S))) + def f(): + t = malloc(T, 1) + t.items[0].x = 1 + return t.items[0].x + res = interpret(f, []) + assert res == 1 + +def test_interior_ptr_with_index_and_field(): + S = Struct("S", ('x', Signed)) + T = Struct("T", ('s', S)) + U = GcArray(T) + def f(): + u = malloc(U, 1) + u[0].s.x = 1 + return u[0].s.x + res = interpret(f, []) + assert res == 1 + +def test_interior_ptr_len(): + S = Struct("S", ('x', Signed)) + T = GcStruct("T", ('items', Array(S))) + def f(): + t = malloc(T, 1) + return len(t.items) + res = interpret(f, []) + assert res == 1 + +def test_interior_ptr_with_setitem(): + T = GcStruct("T", ('s', Array(Signed))) + def f(): + t = malloc(T, 1) + t.s[0] = 1 + return t.s[0] + res = interpret(f, []) + assert res == 1 Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Wed Sep 13 11:50:52 2006 @@ -416,9 +416,9 @@ return result def generic_set(self, op, targetexpr): - newvalue = self.expr(op.args[2], special_case_void=False) + newvalue = self.expr(op.args[-1], special_case_void=False) result = ['%s = %s;' % (targetexpr, newvalue)] - T = self.lltypemap(op.args[2]) + T = self.lltypemap(op.args[-1]) result = '\n'.join(result) if T is Void: result = '/* %s */' % result @@ -432,7 +432,7 @@ op.args[1].value) return self.generic_get(op, expr) - def OP_SETFIELD(self, op): + def OP_BARE_SETFIELD(self, op): assert isinstance(op.args[1], Constant) STRUCT = self.lltypemap(op.args[0]).TO structdef = self.db.gettypedefnode(STRUCT) @@ -440,7 +440,7 @@ op.args[1].value) return self.generic_set(op, expr) - OP_BARE_SETFIELD = OP_SETFIELD + #OP_SETFIELD = OP_BARE_SETFIELD def OP_GETSUBSTRUCT(self, op): RESULT = self.lltypemap(op.result).TO @@ -466,7 +466,7 @@ return self.generic_get(op, '%s[%s]' % (items, self.expr(op.args[1]))) - def OP_SETARRAYITEM(self, op): + def OP_BARE_SETARRAYITEM(self, op): ARRAY = self.lltypemap(op.args[0]).TO items = self.expr(op.args[0]) if not isinstance(ARRAY, FixedSizeArray): @@ -474,6 +474,42 @@ return self.generic_set(op, '%s[%s]' % (items, self.expr(op.args[1]))) + def interior_expr(self, args, rettype=False): + TYPE = args[0].concretetype.TO + expr = '(*(' + self.expr(args[0]) + '))' + for arg in args[1:]: + defnode = self.db.gettypedefnode(TYPE) + if arg.concretetype is Void: + fieldname = arg.value + expr = defnode.access_expr(expr, fieldname) + TYPE = getattr(TYPE, fieldname) + else: + if not isinstance(TYPE, FixedSizeArray): + expr = '(%s).items[%s]'%(expr, self.expr(arg)) + else: + expr = '(%s)[%s]'%(expr, self.expr(arg)) + TYPE = TYPE.OF + if rettype: + return expr, TYPE + else: + return expr + + def OP_GETINTERIORFIELD(self, op): + return self.generic_get(op, self.interior_expr(op.args)) + + def OP_BARE_SETINTERIORFIELD(self, op): + return self.generic_set(op, self.interior_expr(op.args[:-1])) + + def OP_GETINTERIORARRAYSIZE(self, op): + expr, ARRAY = self.interior_expr(op.args, True) + if isinstance(ARRAY, FixedSizeArray): + return '%s = %d;'%(self.expr(op.result), ARRAY.length) + else: + assert isinstance(ARRAY, Array) + return '%s = %s.length;'%(self.expr(op.result), expr) + + #OP_SETINTERIORFIELD = OP_BARE_SETINTERIORFIELD + def OP_GETARRAYSUBSTRUCT(self, op): ARRAY = self.lltypemap(op.args[0]).TO items = self.expr(op.args[0]) Modified: pypy/branch/kill-keepalives/pypy/translator/c/src/support.h ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/src/support.h (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/src/support.h Wed Sep 13 11:50:52 2006 @@ -18,12 +18,12 @@ #define FAIL_ZER(msg) FAIL_EXCEPTION(PyExc_ZeroDivisionError, msg) #define CFAIL() RPyConvertExceptionFromCPython() -#define PyString_FromLLCharArrayAndSize(itemsarray, size) \ - PyString_FromStringAndSize(itemsarray->items, size) +#define PyString_FromRPyString(rpystr) \ + PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr)) -#define PyString_ToLLCharArray(s, itemsarray) \ - memcpy(itemsarray->items, PyString_AS_STRING(s), \ - itemsarray->length) +#define PyString_ToRPyString(s, rpystr) \ + memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \ + RPyString_Size(rpystr)) #ifndef PYPY_STANDALONE From mwh at codespeak.net Wed Sep 13 11:52:00 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 11:52:00 +0200 (CEST) Subject: [pypy-svn] r32251 - pypy/branch/more-gckinds Message-ID: <20060913095200.4284810071@code0.codespeak.net> Author: mwh Date: Wed Sep 13 11:51:59 2006 New Revision: 32251 Removed: pypy/branch/more-gckinds/ Log: merged forward From mwh at codespeak.net Wed Sep 13 12:25:00 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 12:25:00 +0200 (CEST) Subject: [pypy-svn] r32252 - pypy/branch/kill-keepalives/pypy/translator/c/test Message-ID: <20060913102500.264E210075@code0.codespeak.net> Author: mwh Date: Wed Sep 13 12:24:58 2006 New Revision: 32252 Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Log: skip two tests for now Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Wed Sep 13 12:24:58 2006 @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem.lltype import * from pypy.translator.c.test import test_typed - +import py class TestLowLevelType(test_typed.CompilationTestCase): @@ -52,6 +52,7 @@ assert fn() == 607 def test_recursivearray(self): + py.test.skip("not allowed any more") A = ForwardReference() A.become(FixedSizeArray(Struct("S", ('a', Ptr(A))), 5)) TREE = GcStruct("TREE", ("root", A), ("other", A)) @@ -95,6 +96,7 @@ assert res == 123 def test_more_prebuilt_arrays(self): + py.test.skip("not allowed any more") A = FixedSizeArray(Struct('s1', ('x', Signed)), 5) S = GcStruct('s', ('a1', Ptr(A)), ('a2', A)) s = malloc(S, zero=True) From arigo at codespeak.net Wed Sep 13 12:26:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 12:26:21 +0200 (CEST) Subject: [pypy-svn] r32253 - pypy/branch/kill-keepalives/pypy/translator/c/test Message-ID: <20060913102621.4BE9D10079@code0.codespeak.net> Author: arigo Date: Wed Sep 13 12:26:18 2006 New Revision: 32253 Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Log: This test is still meaningful with Struct instead of GcStruct. Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Wed Sep 13 12:26:18 2006 @@ -52,12 +52,11 @@ assert fn() == 607 def test_recursivearray(self): - py.test.skip("not allowed any more") A = ForwardReference() A.become(FixedSizeArray(Struct("S", ('a', Ptr(A))), 5)) - TREE = GcStruct("TREE", ("root", A), ("other", A)) + TREE = Struct("TREE", ("root", A), ("other", A)) + tree = malloc(TREE, immortal=True) def llf(): - tree = malloc(TREE) tree.root[0].a = tree.root tree.root[1].a = tree.other assert tree.root[0].a[0].a[0].a[0].a[0].a[1].a == tree.other From mwh at codespeak.net Wed Sep 13 12:26:49 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 12:26:49 +0200 (CEST) Subject: [pypy-svn] r32254 - pypy/branch/kill-keepalives/pypy/translator/c/test Message-ID: <20060913102649.9549210079@code0.codespeak.net> Author: mwh Date: Wed Sep 13 12:26:47 2006 New Revision: 32254 Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_database.py Log: don't use GcStructs in two tests in test_database Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_database.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/test/test_database.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/test/test_database.py Wed Sep 13 12:26:47 2006 @@ -72,10 +72,10 @@ def test_codegen(): db = LowLevelDatabase() U = Struct('inlined', ('z', Signed)) - T = GcStruct('subtest', ('y', Signed)) - S = GcStruct('test', ('x', Ptr(T)), ('u', U), ('p', Ptr(U))) - s = malloc(S) - s.x = malloc(T) + T = Struct('subtest', ('y', Signed)) + S = Struct('test', ('x', Ptr(T)), ('u', U), ('p', Ptr(U))) + s = malloc(S, immortal=True) + s.x = malloc(T, immortal=True) s.x.y = 42 s.u.z = -100 s.p = s.u @@ -99,16 +99,16 @@ def test_codegen_3(): db = LowLevelDatabase() - A = GcStruct('varsizedstuff', ('x', Signed), ('y', Array(('i', Signed)))) - S = GcStruct('test', ('aptr', Ptr(A)), - ('anitem', Ptr(A.y.OF)), - ('anarray', Ptr(A.y))) - a = malloc(A, 3) + A = Struct('varsizedstuff', ('x', Signed), ('y', Array(('i', Signed)))) + S = Struct('test', ('aptr', Ptr(A)), + ('anitem', Ptr(A.y.OF)), + ('anarray', Ptr(A.y))) + a = malloc(A, 3, immortal=True) a.x = 99 a.y[0].i = 100 a.y[1].i = 101 a.y[2].i = 102 - s = malloc(S) + s = malloc(S, immortal=True) s.aptr = a s.anitem = a.y[1] s.anarray = a.y From arigo at codespeak.net Wed Sep 13 12:38:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 12:38:58 +0200 (CEST) Subject: [pypy-svn] r32255 - pypy/dist/pypy/jit/codegen Message-ID: <20060913103858.275CF10075@code0.codespeak.net> Author: arigo Date: Wed Sep 13 12:38:56 2006 New Revision: 32255 Modified: pypy/dist/pypy/jit/codegen/detect_cpu.py Log: Use the 'platform' module, new in 2.3, which I didn't know about. Modified: pypy/dist/pypy/jit/codegen/detect_cpu.py ============================================================================== --- pypy/dist/pypy/jit/codegen/detect_cpu.py (original) +++ pypy/dist/pypy/jit/codegen/detect_cpu.py Wed Sep 13 12:38:56 2006 @@ -8,13 +8,17 @@ pass def autodetect(): - platform = sys.platform.lower() - if platform.startswith('win'): # assume an Intel Windows - return 'i386' - # assume we have 'uname' - mach = os.popen('uname -m', 'r').read().strip() - if not mach: - raise ProcessorAutodetectError, "cannot run 'uname -m'" + try: + import platform + mach = platform.machine() + except ImportError: + platform = sys.platform.lower() + if platform.startswith('win'): # assume an Intel Windows + return 'i386' + # assume we have 'uname' + mach = os.popen('uname -m', 'r').read().strip() + if not mach: + raise ProcessorAutodetectError, "cannot run 'uname -m'" try: return {'i386': 'i386', 'i486': 'i386', From arigo at codespeak.net Wed Sep 13 14:10:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 14:10:57 +0200 (CEST) Subject: [pypy-svn] r32256 - in pypy/dist/pypy/rpython/rctypes: . test Message-ID: <20060913121057.3FDC81007B@code0.codespeak.net> Author: arigo Date: Wed Sep 13 14:10:52 2006 New Revision: 32256 Modified: pypy/dist/pypy/rpython/rctypes/rarray.py pypy/dist/pypy/rpython/rctypes/test/test_rarray.py Log: Support for slicing char arrays, as it's the only way to get an RPython string from a slice without doing multiple copies. Modified: pypy/dist/pypy/rpython/rctypes/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/rarray.py (original) +++ pypy/dist/pypy/rpython/rctypes/rarray.py Wed Sep 13 14:10:52 2006 @@ -1,6 +1,7 @@ from ctypes import ARRAY, c_int from pypy.rpython.lltypesystem.rstr import string_repr from pypy.rpython.rmodel import IntegerRepr, inputconst +from pypy.rpython.rslice import AbstractSliceRepr from pypy.rpython.lltypesystem import lltype from pypy.annotation.pairtype import pairtype from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr @@ -140,6 +141,17 @@ r_array.setitem(hop.llops, v_array, v_index, v_item) +class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)): + def rtype_getitem((r_array, r_slic), hop): + rs = hop.rtyper.type_system.rslice + if r_slic == rs.startstop_slice_repr: + # slicing: char array only + assert r_array.r_item.ll_type == lltype.Char + v_array, v_slice = hop.inputargs(r_array, rs.startstop_slice_repr) + return hop.gendirectcall(ll_chararrayslice, v_array, v_slice) + raise TyperError('getitem does not support slices with %r' % (r_slic,)) + + class __extend__(pairtype(ArrayRepr, PointerRepr)): def convert_from_to((r_from, r_to), v, llops): # XXX keepalives @@ -159,3 +171,16 @@ for i in range(length): newstr.chars[i] = p[i] return newstr + +def ll_chararrayslice(box, slice): + from pypy.rpython.rctypes import rchar_p + p = box.c_data + start = slice.start + stop = slice.stop + length = stop - start + assert length >= 0 + newstr = lltype.malloc(string_repr.lowleveltype.TO, length) + newstr.hash = 0 + for i in range(length): + newstr.chars[i] = p[start+i] + return newstr Modified: pypy/dist/pypy/rpython/rctypes/test/test_rarray.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_rarray.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_rarray.py Wed Sep 13 14:10:52 2006 @@ -163,6 +163,21 @@ a.translator.view() assert s == annmodel.SomeString() + def test_annotate_char_array_slice(self): + A = c_char * 3 + def func(): + a = A() + a[0] = 'x' + a[1] = 'y' + a[2] = 'z' + return a[0:2] + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(func, []) + if conftest.option.view: + a.translator.view() + assert s == annmodel.SomeString() + def test_annotate_varsize_array(self): def func(n): a = (c_int * n)() @@ -229,6 +244,20 @@ res = interpret(func, []) assert ''.join(res.chars) == "xy" + def test_specialize_char_array_slice(self): + A = c_char * 3 + def func(n): + a = A() + a[0] = 'x' + a[1] = 'y' + a[2] = 'z' + assert n >= 0 + return a[0:n] + res = interpret(func, [1]) + assert ''.join(res.chars) == "x" + res = interpret(func, [3]) + assert ''.join(res.chars) == "xyz" + def test_automatic_cast_array_to_pointer(self): A = c_int * 10 class S(Structure): From arigo at codespeak.net Wed Sep 13 14:11:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 14:11:17 +0200 (CEST) Subject: [pypy-svn] r32257 - pypy/dist/pypy/module/mmap Message-ID: <20060913121117.95A581007B@code0.codespeak.net> Author: arigo Date: Wed Sep 13 14:11:16 2006 New Revision: 32257 Modified: pypy/dist/pypy/module/mmap/interp_mmap.py Log: In-progress: various clean-ups of the mmap module. Modified: pypy/dist/pypy/module/mmap/interp_mmap.py ============================================================================== --- pypy/dist/pypy/module/mmap/interp_mmap.py (original) +++ pypy/dist/pypy/module/mmap/interp_mmap.py Wed Sep 13 14:11:16 2006 @@ -19,15 +19,13 @@ class CConfig: - _header_ = "#include " + _includes_ = ("sys/types.h",) size_t = ctypes_platform.SimpleType("size_t", c_long) off_t = ctypes_platform.SimpleType("off_t", c_long) constants = {} if _POSIX: - CConfig._header_ = """ - %s - #include """ % CConfig._header_ + CConfig._includes_ += ("sys/mman.h",) # constants, look in sys/mman.h and platform docs for the meaning # some constants are linux only so they will be correctly exposed outside # depending on the OS @@ -37,9 +35,7 @@ for name in constant_names: setattr(CConfig, name, ctypes_platform.DefinedConstantInteger(name)) elif _MS_WINDOWS: - CConfig._header_ = """ - %s - #include """ % CConfig._header_ + CConfig._includes_ += ("windows.h",) constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY', 'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY', 'DUPLICATE_SAME_ACCESS'] @@ -68,39 +64,31 @@ _ACCESS_DEFAULT, ACCESS_READ, ACCESS_WRITE, ACCESS_COPY = range(4) +PTR = POINTER(c_char) # cannot use c_void_p as return value of functions :-( + size_t = cConfig.size_t off_t = cConfig.off_t libc.strerror.restype = c_char_p libc.strerror.argtypes = [c_int] -libc.memcpy.argtypes = [POINTER(c_char), c_char_p, c_int] -libc.memcpy.restype = c_void_p -libc.memmove.argtypes = [c_char_p, c_char_p, size_t] -libc.memmove.restype = c_void_p if _POSIX: - libc.mmap.argtypes = [c_void_p, size_t, c_int, c_int, c_int, off_t] - libc.mmap.restype = c_void_p + libc.mmap.argtypes = [PTR, size_t, c_int, c_int, c_int, off_t] + libc.mmap.restype = PTR + libc.mmap.includes = ("sys/mman.h",) libc.close.argtypes = [c_int] libc.close.restype = c_int - libc.munmap.argtypes = [c_void_p, size_t] + libc.munmap.argtypes = [PTR, size_t] libc.munmap.restype = c_int - libc.msync.argtypes = [c_char_p, size_t, c_int] + libc.munmap.includes = ("sys/mman.h",) + libc.msync.argtypes = [PTR, size_t, c_int] libc.msync.restype = c_int - - ## LINUX msync syscall helper stuff - # you don't have addressof() in rctypes so I looked up the implementation - # of addressof in ctypes source and come up with this. - pythonapi.PyLong_FromVoidPtr.argtypes = [c_char_p] - pythonapi.PyLong_FromVoidPtr.restype = c_int - # we also need to alias msync to take a c_void_p instead of c_char_p - linux_msync = libc["msync"] - linux_msync.argtypes = [c_void_p, size_t, c_int] - linux_msync.restype = c_int + libc.msync.includes = ("sys/mman.h",) has_mremap = False if hasattr(libc, "mremap"): - libc.mremap.argtypes = [POINTER(c_char), size_t, size_t, c_ulong] - libc.mremap.restype = c_void_p + libc.mremap.argtypes = [PTR, size_t, size_t, c_ulong] + libc.mremap.restype = PTR + libc.mremap.includes = ("sys/mman.h",) has_mremap = True libc.ftruncate.argtypes = [c_int, off_t] libc.ftruncate.restype = c_int @@ -118,7 +106,7 @@ DWORD = wintypes.DWORD BOOL = wintypes.BOOL LONG = wintypes.LONG - LPVOID = c_void_p + LPVOID = PTR LPCVOID = LPVOID DWORD_PTR = DWORD c_int = wintypes.c_int @@ -155,12 +143,12 @@ BOOL, DWORD] DuplicateHandle.restype = BOOL CreateFileMapping = windll.kernel32.CreateFileMappingA - CreateFileMapping.argtypes = [c_int, c_void_p, c_int, c_int, c_int, + CreateFileMapping.argtypes = [c_int, PTR, c_int, c_int, c_int, c_char_p] CreateFileMapping.restype = c_int MapViewOfFile = windll.kernel32.MapViewOfFile MapViewOfFile.argtypes = [c_int, DWORD, DWORD, DWORD, DWORD] - MapViewOfFile.restype = c_void_p + MapViewOfFile.restype = PTR CloseHandle = windll.kernel32.CloseHandle CloseHandle.argtypes = [c_int] CloseHandle.restype = BOOL @@ -168,7 +156,7 @@ UnmapViewOfFile.argtypes = [LPCVOID] UnmapViewOfFile.restype = BOOL FlushViewOfFile = windll.kernel32.FlushViewOfFile - FlushViewOfFile.argtypes = [c_char_p, c_int] + FlushViewOfFile.argtypes = [LPCVOID, c_int] FlushViewOfFile.restype = BOOL SetFilePointer = windll.kernel32.SetFilePointer SetFilePointer.argtypes = [c_int, c_int, POINTER(c_int), c_int] @@ -187,6 +175,7 @@ return int(si.dwPageSize) def _get_file_size(space, handle): + # XXX use native Windows types like WORD high = c_int(0) low = c_int(windll.kernel32.GetFileSize(c_int(handle.value), byref(high))) # low might just happen to have the value INVALID_FILE_SIZE @@ -205,80 +194,86 @@ return libc.strerror(errno) PAGESIZE = _get_page_size() +NULL = PTR() + +# ____________________________________________________________ -class _mmap(Wrappable): - def __init__(self, space): +class W_MMap(Wrappable): + def __init__(self, space, access): self.space = space - self._size = 0 - self._pos = 0 - self._access = _ACCESS_DEFAULT + self.size = 0 + self.pos = 0 + self.access = access if _MS_WINDOWS: - self._map_handle = wintypes.c_int() - self._file_handle = wintypes.c_int() - self._tagname = "" + self.map_handle = wintypes.c_int() + self.file_handle = wintypes.c_int() + self.tagname = "" elif _POSIX: - self._fd = 0 - self._closed = False + self.fd = -1 + self.closed = False - def _to_str(self): - data = "".join([self._data[i] for i in range(self._size)]) - return self.space.wrap(data) - _to_str.unwrap_spec = ['self'] +## def to_str(self): +## return "".join([self.data[i] for i in range(self.size)]) - def _check_valid(self): + def check_valid(self): if _MS_WINDOWS: - to_close = self._map_handle.value == INVALID_c_int_VALUE + to_close = self.map_handle.value == INVALID_c_int_VALUE elif _POSIX: - to_close = self._closed + to_close = self.closed if to_close: raise OperationError(self.space.w_ValueError, self.space.wrap("map closed or invalid")) - _check_valid.unwrap_spec = ['self'] - def _check_writeable(self): - if not (self._access != ACCESS_READ): + def check_writeable(self): + if not (self.access != ACCESS_READ): raise OperationError(self.space.w_TypeError, self.space.wrap("mmap can't modify a readonly memory map.")) - _check_writeable.unwrap_spec = ['self'] - def _check_resizeable(self): - if not (self._access == ACCESS_WRITE or self._access == _ACCESS_DEFAULT): + def check_resizeable(self): + if not (self.access == ACCESS_WRITE or self.access == _ACCESS_DEFAULT): raise OperationError(self.space.w_TypeError, self.space.wrap( "mmap can't resize a readonly or copy-on-write memory map.")) - _check_resizeable.unwrap_spec = ['self'] + + def setdata(self, data, size): + """Set the internal data and map size from a PTR.""" + arraytype = c_char * size + self.data = cast(data, POINTER(arraytype)) + self.size = size def close(self): if _MS_WINDOWS: - if self._data: - self._unmapview() - self._data = POINTER(c_char)() - if self._map_handle.value != INVALID_c_int_VALUE: - CloseHandle(self._map_handle) - self._map_handle.value = INVALID_c_int_VALUE - if self._file_handle.value != INVALID_c_int_VALUE: - CloseHandle(self._file_handle) - self._file_handle.value = INVALID_c_int_VALUE + if self.data: + self.unmapview() + self.setdata(NULL, 0) + if self.map_handle.value != INVALID_c_int_VALUE: + CloseHandle(self.map_handle) + self.map_handle.value = INVALID_c_int_VALUE + if self.file_handle.value != INVALID_c_int_VALUE: + CloseHandle(self.file_handle) + self.file_handle.value = INVALID_c_int_VALUE elif _POSIX: - self._closed = True - libc.close(self._fd) - self._fd = -1 - if self._data: - libc.munmap(self._data, self._size) + self.closed = True + if self.fd != -1: + libc.close(self.fd) + self.fd = -1 + if self.data: + libc.munmap(self.data, self.size) + self.setdata(NULL, 0) close.unwrap_spec = ['self'] - def _unmapview(self): - data = cast(self._data, c_void_p) + def unmapview(self): + data = cast(self.data, PTR) UnmapViewOfFile(data) def read_byte(self): - self._check_valid() + self.check_valid() - if self._pos < self._size: - value = self._data[self._pos] - self._pos += 1 + if self.pos < self.size: + value = self.data[self.pos] + self.pos += 1 return self.space.wrap(value) else: raise OperationError(self.space.w_ValueError, @@ -286,174 +281,157 @@ read_byte.unwrap_spec = ['self'] def readline(self): - self._check_valid() + self.check_valid() - found = False - for pos in range(self._pos, self._size): - if self._data[pos] == '\n': - found = True + for pos in xrange(self.pos, self.size): + if self.data[pos] == '\n': + eol = pos + 1 # we're interested in the position after new line break + else: # no '\n' found + eol = self.size - if not found: - eol = self._size - else: - eol = pos + 1 # we're interested in the position after new line - - # res = self._data[self._pos:eol-self._pos] XXX: can't use this slicing - # in translation step - res = "".join([self._data[i] for i in range(self._pos, eol-self._pos)]) - self._pos += eol - self._pos + res = self.data[self.pos:eol] + self.pos += len(res) return self.space.wrap(res) readline.unwrap_spec = ['self'] - def read(self, num): - self._check_valid() - - num_bytes = num - - # silently adjust out of range requests - assert self._pos >= 0; assert num_bytes >= 0; assert self._size >= 0 - if self._pos + num_bytes > self._size: - num_bytes -= (self._pos + num_bytes) - self._size - - # due to slicing of python, the last char is not always returned - if num_bytes < self._size - 1: - res = "".join([self._data[i] for i in range(self._pos, num_bytes)]) - else: - res = "".join([self._data[i] for i in range(self._pos, self._size)]) - self._pos += num_bytes + def read(self, num=-1): + self.check_valid() + + if num < 0: + # read all + eol = self.size + else: + eol = self.pos + num + # silently adjust out of range requests + if eol > self.size: + eol = self.size + + res = self.data[self.pos:eol] + self.pos += len(res) return self.space.wrap(res) read.unwrap_spec = ['self', int] def find(self, tofind, start=0): - self._check_valid() - - # since we don't have to update positions we - # gain advantage of python strings :-) - w_str_data = self._to_str() - str_data = self.space.str_w(w_str_data) - assert start >= 0 - return self.space.wrap(str_data.find(tofind, start)) + self.check_valid() + + # XXX naive! how can we reuse the rstr algorithm? + if start < 0: + start += self.size + if start < 0: + start = 0 + data = self.data + for p in xrange(start, self.size): + for q in range(len(tofind)): + if data[p+q] != tofind[q]: + break # position 'p' is not a match + else: + # full match + return self.space.wrap(p) + # failure + return self.space.wrap(-1) find.unwrap_spec = ['self', str, int] def seek(self, pos, whence=0): - self._check_valid() + self.check_valid() dist = pos how = whence if how == 0: # relative to start - if dist < 0: - raise OperationError(self.space.w_ValueError, - self.space.wrap("seek out of range")) where = dist elif how == 1: # relative to current position - if self._pos + dist < 0: - raise OperationError(self.space.w_ValueError, - self.space.wrap("seek out of range")) - where = self._pos + dist + where = self.pos + dist elif how == 2: # relative to the end - if self._size + dist < 0: - raise OperationError(self.space.w_ValueError, - self.space.wrap("seek out of range")) - where = self._size + dist + where = self.size + dist else: raise OperationError(self.space.w_ValueError, self.space.wrap("unknown seek type")) - - assert where >= 0 - if where > self._size: + + if not (0 <= where <= self.size): raise OperationError(self.space.w_ValueError, - self.space.wrap("seek out of range")) + self.space.wrap("seek out of range")) - self._pos = where + self.pos = where seek.unwrap_spec = ['self', int, int] def tell(self): - self._check_valid() + self.check_valid() - return self.space.wrap(self._pos) + return self.space.wrap(self.pos) tell.unwrap_spec = ['self'] def size(self): - self._check_valid() + self.check_valid() + size = self.size if _MS_WINDOWS: - if self._file_handle.value != INVALID_c_int_VALUE: - low, high = _get_file_size(self.space, self._file_handle) - if not high and low < sys.maxint: + if self.file_handle.value != INVALID_c_int_VALUE: + low, high = _get_file_size(self.space, self.file_handle) + if not high and low <= sys.maxint: return self.space.wrap(low) size = c_int((high << 32) + low).value - return self.space.wrap(size) - else: - return self.space.wrap(self._size) elif _POSIX: - st = os.fstat(self._fd) - SIZE_BIT = 6 - return self.space.wrap(st[SIZE_BIT]) + st = os.fstat(self.fd) + size = st[stat.ST_SIZE] + return self.space.wrap(size) size.unwrap_spec = ['self'] def write(self, data): - self._check_valid() - self._check_writeable() + self.check_valid() + self.check_writeable() data_len = len(data) - if self._pos + data_len > self._size: + if self.pos + data_len > self.size: raise OperationError(self.space.w_ValueError, self.space.wrap("data out of range")) - - p = c_char_p(data) - libc.memcpy(self._data, p, data_len) - self._pos += data_len + + internaldata = self.data + start = self.pos + for i in range(data_len): + internaldata[start+i] = data[i] + self.pos = start + data_len write.unwrap_spec = ['self', str] def write_byte(self, byte): - self._check_valid() + self.check_valid() if len(byte) > 1: raise OperationError(self.space.w_TypeError, self.space.wrap("write_byte() argument must be char")) - self._check_writeable() - - str_data = self.space.str_w(self._to_str()) - str_data_lst = [i for i in str_data] - str_data_lst[self._pos] = byte - str_data = "".join(str_data_lst) - - p = c_char_p(str_data) - libc.memcpy(self._data, p, len(str_data)) - self._pos += 1 + self.check_writeable() + self.data[self.pos] = byte + self.pos += 1 write_byte.unwrap_spec = ['self', str] def flush(self, offset=0, size=0): - self._check_valid() - + self.check_valid() + if size == 0: - size = self._size - - assert offset >= 0 - assert size >= 0 - if offset + size > self._size: + size = self.size + if offset < 0 or size < 0 or offset + size > self.size: raise OperationError(self.space.w_ValueError, self.space.wrap("flush values out of range")) else: - data = c_char_p("".join([self._data[i] for i in range(offset, size)])) - + # XXX 64-bit support for pointer arithmetic! + start = cast(self.data, c_void_p) + if offset > 0: + start = c_void_p(start.value + offset) + start = cast(start, PTR) if _MS_WINDOWS: - res = FlushViewOfFile(data, size) + res = FlushViewOfFile(start, size) return self.space.wrap(res) elif _POSIX: - if _LINUX: - # alignment of the address - value = pythonapi.PyLong_FromVoidPtr(data) - aligned_value = value & ~(PAGESIZE - 1) - # the size should be increased too. otherwise the final - # part is not "msynced" - new_size = size + value & (PAGESIZE - 1) - res = linux_msync(c_void_p(aligned_value), new_size, MS_SYNC) - else: - res = libc.msync(data, size, MS_SYNC) +## XXX why is this code here? There is no equivalent in CPython +## if _LINUX: +## # alignment of the address +## value = cast(self.data, c_void_p).value +## aligned_value = value & ~(PAGESIZE - 1) +## # the size should be increased too. otherwise the final +## # part is not "msynced" +## new_size = size + value & (PAGESIZE - 1) + res = libc.msync(start, size, MS_SYNC) if res == -1: raise OperationError(self.space.w_EnvironmentError, self.space.wrap(_get_error_msg())) @@ -462,32 +440,33 @@ flush.unwrap_spec = ['self', int, int] def move(self, dest, src, count): - self._check_valid() + self.check_valid() - self._check_writeable() + self.check_writeable() # check boundings - assert src >= 0; assert dest >= 0; assert count >= 0; assert self._size >= 0 - if (src + count > self._size) or (dest + count > self._size): + assert src >= 0; assert dest >= 0; assert count >= 0; assert self.size >= 0 + if (src + count > self.size) or (dest + count > self.size): raise OperationError(self.space.w_ValueError, self.space.wrap("source or destination out of range")) - - data_dest = c_char_p("".join([self._data[i] for i in range(dest, self._size)])) - data_src = c_char_p("".join([self._data[i] for i in range(src, src+count)])) - libc.memmove(data_dest, data_src, size_t(count)) + + XXXXXXX + data_dest = c_char_p("".join([self.data[i] for i in range(dest, self.size)])) + data_src = c_char_p("".join([self.data[i] for i in range(src, src+count)])) + libc.memmove XXX (data_dest, data_src, size_t(count)) assert dest >= 0 - str_left = self.space.str_w(self._to_str())[0:dest] + str_left = self.space.str_w(self.to_str())[0:dest] final_str = "%s%s" % (str_left, data_dest.value) p = c_char_p(final_str) - libc.memcpy(self._data, p, len(final_str)) + libc.memcpy(self.data, p, len(final_str)) move.unwrap_spec = ['self', int, int, int] def resize(self, newsize): - self._check_valid() + self.check_valid() - self._check_resizeable() + self.check_resizeable() if _POSIX: if not has_mremap: @@ -496,19 +475,19 @@ self.space.wrap(msg)) # resize the underlying file first - res = libc.ftruncate(self._fd, newsize) + res = libc.ftruncate(self.fd, newsize) if res == -1: raise OperationError(self.space.w_EnvironmentError, self.space.wrap(_get_error_msg())) # now resize the mmap MREMAP_MAYMOVE = 1 - libc.mremap(self._data, self._size, newsize, MREMAP_MAYMOVE) - self._size = newsize + libc.mremap(self.data, self.size, newsize, MREMAP_MAYMOVE) + self.size = newsize elif _MS_WINDOWS: # disconnect the mapping - self._unmapview() - CloseHandle(self._map_handle) + self.unmapview() + CloseHandle(self.map_handle) # move to the desired EOF position if _64BIT: @@ -519,22 +498,21 @@ newsize_low = c_int(newsize) FILE_BEGIN = c_int(0) - SetFilePointer(self._file_handle, newsize_low, byref(newsize_high), + SetFilePointer(self.file_handle, newsize_low, byref(newsize_high), FILE_BEGIN) # resize the file - SetEndOfFile(self._file_handle) + SetEndOfFile(self.file_handle) # create another mapping object and remap the file view - res = CreateFileMapping(self._file_handle, c_void_p(0), PAGE_READWRITE, - newsize_high, newsize_low, self._tagname) - self._map_handle = c_int(res) + res = CreateFileMapping(self.file_handle, NULL, PAGE_READWRITE, + newsize_high, newsize_low, self.tagname) + self.map_handle = c_int(res) dwErrCode = DWORD(0) - if self._map_handle: - data = MapViewOfFile(self._map_handle, FILE_MAP_WRITE, + if self.map_handle: + data = MapViewOfFile(self.map_handle, FILE_MAP_WRITE, 0, 0, 0) if data: - self._data = cast(data, POINTER(c_char)) - self._size = newsize + self.setdata(data, newsize) return else: dwErrCode = GetLastError() @@ -546,26 +524,26 @@ resize.unwrap_spec = ['self', int] def __len__(self): - self._check_valid() + self.check_valid() - return self.space.wrap(self._size) + return self.space.wrap(self.size) __len__.unwrap_spec = ['self'] def __getitem__(self, index): - self._check_valid() + self.check_valid() # XXX this does not support slice() instances try: - return self.space.wrap(self.space.str_w(self._to_str())[index]) + return self.space.wrap(self.space.str_w(self.to_str())[index]) except IndexError: raise OperationError(self.space.w_IndexError, self.space.wrap("mmap index out of range")) __getitem__.unwrap_spec = ['self', int] def __setitem__(self, index, value): - self._check_valid() - self._check_writeable() + self.check_valid() + self.check_writeable() # XXX this does not support slice() instances @@ -575,20 +553,21 @@ str_data = "" try: - str_data = self.space.str_w(self._to_str()) + str_data = self.space.str_w(self.to_str()) str_data_lst = [i for i in str_data] str_data_lst[index] = value str_data = "".join(str_data_lst) except IndexError: raise OperationError(self.space.w_IndexError, self.space.wrap("mmap index out of range")) - + + XXXXXXXXXX p = c_char_p(str_data) - libc.memcpy(self._data, p, len(str_data)) + libc.memcpy(self.data, p, len(str_data)) __setitem__.unwrap_spec = ['self', int, str] def __delitem__(self, index): - self._check_valid() + self.check_valid() # XXX this does not support slice() instances (does it matter?) @@ -597,61 +576,48 @@ __delitem__.unwrap_spec = ['self', int] def __add__(self, w_other): - self._check_valid() + self.check_valid() raise OperationError(self.space.w_SystemError, self.space.wrap("mmaps don't support concatenation")) __add__.unwrap_spec = ['self', W_Root] def __mul__(self, w_other): - self._check_valid() + self.check_valid() raise OperationError(self.space.w_SystemError, self.space.wrap("mmaps don't support repeat operation")) __mul__.unwrap_spec = ['self', W_Root] -_mmap.typedef = TypeDef("_mmap", - _to_str = interp2app(_mmap._to_str, unwrap_spec=_mmap._to_str.unwrap_spec), - _check_valid = interp2app(_mmap._check_valid, - unwrap_spec=_mmap._check_valid.unwrap_spec), - _check_writeable = interp2app(_mmap._check_writeable, - unwrap_spec=_mmap._check_writeable.unwrap_spec), - _check_resizeable = interp2app(_mmap._check_resizeable, - unwrap_spec=_mmap._check_resizeable.unwrap_spec), - close = interp2app(_mmap.close, unwrap_spec=_mmap.close.unwrap_spec), - read_byte = interp2app(_mmap.read_byte, - unwrap_spec=_mmap.read_byte.unwrap_spec), - readline = interp2app(_mmap.readline, - unwrap_spec=_mmap.readline.unwrap_spec), - read = interp2app(_mmap.read, unwrap_spec=_mmap.read.unwrap_spec), - find = interp2app(_mmap.find, unwrap_spec=_mmap.find.unwrap_spec), - seek = interp2app(_mmap.seek, unwrap_spec=_mmap.seek.unwrap_spec), - tell = interp2app(_mmap.tell, unwrap_spec=_mmap.tell.unwrap_spec), - size = interp2app(_mmap.size, unwrap_spec=_mmap.size.unwrap_spec), - write = interp2app(_mmap.write, unwrap_spec=_mmap.write.unwrap_spec), - write_byte = interp2app(_mmap.write_byte, - unwrap_spec=_mmap.write_byte.unwrap_spec), - flush = interp2app(_mmap.flush, unwrap_spec=_mmap.flush.unwrap_spec), - move = interp2app(_mmap.move, unwrap_spec=_mmap.move.unwrap_spec), - resize = interp2app(_mmap.resize, unwrap_spec=_mmap.resize.unwrap_spec), - - __len__ = interp2app(_mmap.__len__, unwrap_spec=_mmap.__len__.unwrap_spec), - __getitem__ = interp2app(_mmap.__getitem__, - unwrap_spec=_mmap.__getitem__.unwrap_spec), - __setitem__ = interp2app(_mmap.__setitem__, - unwrap_spec=_mmap.__setitem__.unwrap_spec), - __delitem__ = interp2app(_mmap.__delitem__, - unwrap_spec=_mmap.__delitem__.unwrap_spec), - __add__ = interp2app(_mmap.__add__, unwrap_spec=_mmap.__add__.unwrap_spec), - __mul__ = interp2app(_mmap.__mul__, unwrap_spec=_mmap.__mul__.unwrap_spec), +W_MMap.typedef = TypeDef("mmap", + close = interp2app(W_MMap.close), + read_byte = interp2app(W_MMap.read_byte), + readline = interp2app(W_MMap.readline), + read = interp2app(W_MMap.read), + find = interp2app(W_MMap.find), + seek = interp2app(W_MMap.seek), + tell = interp2app(W_MMap.tell), + size = interp2app(W_MMap.size), + write = interp2app(W_MMap.write), + write_byte = interp2app(W_MMap.write_byte), + flush = interp2app(W_MMap.flush), + move = interp2app(W_MMap.move), + resize = interp2app(W_MMap.resize), + + __len__ = interp2app(W_MMap.__len__), + __getitem__ = interp2app(W_MMap.__getitem__), + __setitem__ = interp2app(W_MMap.__setitem__), + __delitem__ = interp2app(W_MMap.__delitem__), + __add__ = interp2app(W_MMap.__add__), + __mul__ = interp2app(W_MMap.__mul__), ) def _check_map_size(space, size): if size < 0: raise OperationError(space.w_TypeError, space.wrap("memory mapped size must be positive")) - if size == sys.maxint: + if size_t(size).value != size: raise OperationError(space.w_OverflowError, space.wrap("memory mapped size is too large (limited by C int)")) @@ -690,40 +656,35 @@ try: st = os.fstat(fd) except OSError: - raise OperationError(space.w_EnvironmentError, - space.wrap("bad file descriptor")) - MODE_BIT, SIZE_BIT = 0, 6 # cannot use st.st_mode and st.st_size - mode = st[MODE_BIT] - size = st[SIZE_BIT] - if stat.S_ISREG(mode): - if map_size == 0: - map_size = size - elif map_size > size: - raise OperationError(space.w_ValueError, - space.wrap("mmap length is greater than file size")) + pass # ignore errors and trust map_size + else: + mode = st[stat.ST_MODE] + size = st[stat.ST_SIZE] + if stat.S_ISREG(mode): + if map_size == 0: + map_size = size + elif map_size > size: + raise OperationError(space.w_ValueError, + space.wrap("mmap length is greater than file size")) - m = _mmap(space) - m._size = map_size + m = W_MMap(space, access) if fd == -1: # Assume the caller wants to map anonymous memory. # This is the same behaviour as Windows. mmap.mmap(-1, size) # on both Windows and Unix map anonymous memory. - m._fd = -1 + m.fd = -1 flags |= MAP_ANONYMOUS else: - m._fd = os.dup(fd) - if m._fd == -1: - raise OperationError(space.w_EnvironmentError, - space.wrap(_get_error_msg())) + m.fd = os.dup(fd) - res = libc.mmap(c_void_p(0), map_size, prot, flags, fd, 0) - if not res: + res = libc.mmap(NULL, map_size, prot, flags, fd, 0) + if cast(res, c_void_p).value == -1: raise OperationError(space.w_EnvironmentError, space.wrap(_get_error_msg())) - m._data = cast(res, POINTER(c_char)) - m._access = access + + m.setdata(res, map_size) return space.wrap(m) mmap.unwrap_spec = [ObjSpace, int, int, int, int, int] @@ -733,19 +694,19 @@ _check_map_size(space, length) map_size = length - flProtect = c_int() - dwDesiredAccess = WORD() + flProtect = 0 + dwDesiredAccess = 0 fh = 0 if access == ACCESS_READ: - flProtect = c_int(PAGE_READONLY) - dwDesiredAccess = DWORD(FILE_MAP_READ) + flProtect = PAGE_READONLY + dwDesiredAccess = FILE_MAP_READ elif access == _ACCESS_DEFAULT or access == ACCESS_WRITE: - flProtect = c_int(PAGE_READWRITE) - dwDesiredAccess = DWORD(FILE_MAP_WRITE) + flProtect = PAGE_READWRITE + dwDesiredAccess = FILE_MAP_WRITE elif access == ACCESS_COPY: - flProtect = c_int(PAGE_WRITECOPY) - dwDesiredAccess = DWORD(FILE_MAP_COPY) + flProtect = PAGE_WRITECOPY + dwDesiredAccess = FILE_MAP_COPY else: raise OperationError(space.w_ValueError, space.wrap("mmap invalid access parameter.")) @@ -761,20 +722,20 @@ # SEEK_SET = 0 # libc._lseek(fileno, 0, SEEK_SET) - m = _mmap(space) - m._file_handle = c_int(INVALID_c_int_VALUE) - m._map_handle = c_int(INVALID_c_int_VALUE) + m = W_MMap(space, access) + # XXX the following two attributes should be plain RPython ints + m.file_handle = c_int(INVALID_c_int_VALUE) + m.map_handle = c_int(INVALID_c_int_VALUE) if fh: - res = BOOL() # it is necessary to duplicate the handle, so the # Python code can close it on us res = DuplicateHandle(GetCurrentProcess(), # source process handle fh, # handle to be duplicated GetCurrentProcess(), # target process handle - byref(m._file_handle), # result + byref(m.file_handle), # result 0, # access - ignored due to options value - wintypes.BOOL(False), # inherited by child procs? + False, # inherited by child procs? DUPLICATE_SAME_ACCESS) # options if not res: raise OperationError(space.w_EnvironmentError, @@ -783,38 +744,33 @@ if not map_size: low, high = _get_file_size(space, c_int(fh)) if _64BIT: - m._size = c_int((low << 32) + 1).value + map_size = c_int((low << 32) + 1).value else: if high: # file is too large to map completely - m._size = -1 + map_size = -1 else: - m._size = low - else: - m._size = map_size - else: - m._size = map_size + map_size = low if tagname: - m._tagname = tagname - m._access = access + m.tagname = tagname # DWORD is a 4-byte int. If int > 4-byte it must be divided if _64BIT: - size_hi = DWORD(m._size >> 32) - size_lo = DWORD(m._size & 0xFFFFFFFF) + size_hi = DWORD(map_size >> 32) + size_lo = DWORD(map_size & 0xFFFFFFFF) else: size_hi = c_int(0) - size_lo = c_int(m._size) + size_lo = c_int(map_size) - m._map_handle = c_int(CreateFileMapping(m._file_handle, c_void_p(0), flProtect, - size_hi, size_lo, m._tagname)) + m.map_handle = c_int(CreateFileMapping(m.file_handle, NULL, flProtect, + size_hi, size_lo, m.tagname)) - if m._map_handle: - res = MapViewOfFile(m._map_handle, dwDesiredAccess, + if m.map_handle: + res = MapViewOfFile(m.map_handle, dwDesiredAccess, 0, 0, 0) if res: - m._data = cast(res, POINTER(c_char)) + m.setdata(res, map_size) return space.wrap(m) else: dwErr = GetLastError() From mwh at codespeak.net Wed Sep 13 14:46:10 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 13 Sep 2006 14:46:10 +0200 (CEST) Subject: [pypy-svn] r32259 - in pypy/branch/kill-keepalives/pypy: jit/timeshifter translator translator/backendopt translator/backendopt/test translator/c translator/stackless Message-ID: <20060913124610.5F9CD1007B@code0.codespeak.net> Author: mwh Date: Wed Sep 13 14:46:06 2006 New Revision: 32259 Modified: pypy/branch/kill-keepalives/pypy/jit/timeshifter/timeshift.py pypy/branch/kill-keepalives/pypy/translator/backendopt/constfold.py pypy/branch/kill-keepalives/pypy/translator/backendopt/inline.py pypy/branch/kill-keepalives/pypy/translator/backendopt/support.py pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_support.py pypy/branch/kill-keepalives/pypy/translator/c/exceptiontransform.py pypy/branch/kill-keepalives/pypy/translator/stackless/transform.py pypy/branch/kill-keepalives/pypy/translator/unsimplify.py Log: remove split_blocks_with_keepalive. Modified: pypy/branch/kill-keepalives/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/branch/kill-keepalives/pypy/jit/timeshifter/timeshift.py Wed Sep 13 14:46:06 2006 @@ -10,8 +10,7 @@ from pypy.jit.timeshifter import rtimeshift from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype from pypy.jit.timeshifter.rtyper import GreenRepr, RedRepr, HintLowLevelOpList -from pypy.translator.unsimplify import varoftype, copyvar -from pypy.translator.backendopt import support +from pypy.translator.unsimplify import varoftype, copyvar, split_block from pypy.translator.c import exceptiontransform from pypy.jit.codegen import model as cgmodel @@ -406,9 +405,8 @@ # simple non-merging and non-returning case: nothing to do return - support.split_block_with_keepalive(block, 0, - annotator=self.hannotator, - dontshuffle=True) + split_block(annotator=self.hannotator, block, 0, + dontshuffle=True) before_block = block newinputargs = before_block.inputargs llops = HintLowLevelOpList(self) @@ -712,8 +710,7 @@ if (op.opname in ('direct_call', 'indirect_call') and hrtyper.guess_call_kind(op) == 'red'): - link = support.split_block_with_keepalive(block, i+1, - annotator=self.hannotator) + link = split_block(self.hannotator, block, i+1) # the 'save_locals' pseudo-operation is used to save all # alive local variables into the current JITState Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/constfold.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/constfold.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/constfold.py Wed Sep 13 14:46:06 2006 @@ -1,9 +1,8 @@ from pypy.objspace.flow.model import Constant, Variable, SpaceOperation from pypy.objspace.flow.model import c_last_exception -from pypy.translator.backendopt.support import split_block_with_keepalive from pypy.translator.backendopt.support import log from pypy.translator.simplify import eliminate_empty_blocks -from pypy.translator.unsimplify import insert_empty_block +from pypy.translator.unsimplify import insert_empty_block, split_block from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.lltypesystem import lltype @@ -186,7 +185,7 @@ splitlink = block.exits[0] else: # split the block at the given position - splitlink = split_block_with_keepalive(block, position) + splitlink = split_block(None, block, position) assert list(block.exits) == [splitlink] assert link.target is block assert splitlink.prevblock is block Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/inline.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/inline.py Wed Sep 13 14:46:06 2006 @@ -1,7 +1,7 @@ import sys from pypy.translator.simplify import join_blocks, cleanup_graph from pypy.translator.simplify import get_graph -from pypy.translator.unsimplify import copyvar +from pypy.translator.unsimplify import copyvar, split_block from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, c_last_exception from pypy.objspace.flow.model import FunctionGraph @@ -11,8 +11,8 @@ from pypy.rpython.lltypesystem.lltype import normalizeptr from pypy.rpython import rmodel from pypy.tool.algo import sparsemat -from pypy.translator.backendopt.support import log, split_block_with_keepalive -from pypy.translator.backendopt.support import generate_keepalive, find_backedges, find_loop_blocks +from pypy.translator.backendopt.support import log +from pypy.translator.backendopt.support import find_backedges, find_loop_blocks from pypy.translator.backendopt.canraise import RaiseAnalyzer BASE_INLINE_THRESHOLD = 32.4 # just enough to inline add__Int_Int() @@ -316,7 +316,6 @@ for exceptionlink in afterblock.exits[1:]: if exc_match(vtable, exceptionlink.llexitcase): passon_vars = self.passon_vars(link.prevblock) - copiedblock.operations += generate_keepalive(passon_vars) copiedlink.target = exceptionlink.target linkargs = self.find_args_in_exceptional_case( exceptionlink, link.prevblock, var_etype, var_evalue, afterblock, passon_vars) @@ -364,11 +363,10 @@ del blocks[-1].exits[0].llexitcase linkargs = copiedexceptblock.inputargs copiedexceptblock.closeblock(Link(linkargs, blocks[0])) - copiedexceptblock.operations += generate_keepalive(linkargs) def do_inline(self, block, index_operation): - splitlink = split_block_with_keepalive(block, index_operation) + splitlink = split_block(None, block, index_operation) afterblock = splitlink.target # these variables have to be passed along all the links in the inlined # graph because the original function needs them in the blocks after Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/support.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/support.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/support.py Wed Sep 13 14:46:06 2006 @@ -36,77 +36,7 @@ else: # assume PyObjPtr return True - -def needs_conservative_livevar_calculation(block): - from pypy.rpython.lltypesystem import rclass - vars = block.getvariables() - assert len(block.exits) == 1 - exitingvars = block.exits[0].args - for var in vars: - TYPE = getattr(var, "concretetype", lltype.Ptr(lltype.PyObject)) - if isinstance(TYPE, lltype.Ptr) and not var_needsgc(var): - if isinstance(TYPE.TO, lltype.FuncType): - continue - try: - lltype.castable(TYPE, rclass.CLASSTYPE) - except lltype.InvalidCast: - if var in exitingvars: - return True - else: - return False - -def generate_keepalive(vars, annotator=None): - keepalive_ops = [] - for v in vars: - if isinstance(v, Constant): - continue - if v.concretetype._is_atomic(): - continue - v_keepalive = Variable() - v_keepalive.concretetype = lltype.Void - if annotator is not None: - annotator.setbinding(v_keepalive, s_ImpossibleValue) - keepalive_ops.append(SpaceOperation('keepalive', [v], v_keepalive)) - return keepalive_ops - -def split_block_with_keepalive(block, index_operation, - keep_alive_op_args=True, - annotator=None, - dontshuffle=False): - splitlink = split_block(annotator, block, index_operation, - dontshuffle=dontshuffle) - afterblock = splitlink.target - conservative_keepalives = needs_conservative_livevar_calculation(block) - if conservative_keepalives: - keep_alive_vars = [var for var in block.getvariables() - if var_needsgc(var)] - # XXX you could maybe remove more, if the variables are kept - # alive by something else. but this is sometimes hard to know - for i, var in enumerate(keep_alive_vars): - try: - index = splitlink.args.index(var) - newvar = afterblock.inputargs[index] - except ValueError: - splitlink.args.append(var) - newvar = copyvar(annotator, var) - afterblock.inputargs.append(newvar) - keep_alive_vars[i] = newvar - elif keep_alive_op_args and afterblock.operations: - keep_alive_vars = [var for var in afterblock.operations[0].args - if isinstance(var, Variable) and var_needsgc(var)] - if len(afterblock.operations) > 1 or afterblock.exitswitch != c_last_exception: - afterblock.operations[1:1] = generate_keepalive(keep_alive_vars, - annotator=annotator) - keep_alive_vars = [] - else: - keep_alive_vars = [] - pos = len(afterblock.operations) - if afterblock.exitswitch == c_last_exception: - pos -= 1 # insert the keepalives just before the last operation - # in case of exception-catching - afterblock.operations[pos:pos] = generate_keepalive(keep_alive_vars) - return splitlink - + def calculate_call_graph(translator): calls = {} for graph in translator.graphs: Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_support.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_support.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_support.py Wed Sep 13 14:46:06 2006 @@ -1,94 +1,12 @@ from pypy.translator.unsimplify import varoftype from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.support import \ - needs_conservative_livevar_calculation, split_block_with_keepalive, \ find_loop_blocks, find_backedges from pypy.rpython.rtyper import LowLevelOpList from pypy.rpython.lltypesystem import lltype from pypy.objspace.flow import model -NonGcB = lltype.Struct("B", ('x', lltype.Signed)) -GcA = lltype.GcStruct("A", ('b', NonGcB), ('c', lltype.Ptr(lltype.FuncType([], lltype.Void)))) - -def test_nclc_should_be_true(): - # this is testing a block like: - # +--- inputargs: pointer_to_gc - # | v0 <- op_getsubstruct pointer_to_gc 'b' - # +--- exitargs: v0 (i.e. pointer to non-gc) - llops = LowLevelOpList() - ptr_a = varoftype(lltype.Ptr(GcA)) - v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)], - resulttype=lltype.Ptr(NonGcB)) - block = model.Block([ptr_a]) - block.operations.extend(llops) - block.closeblock(model.Link([v_res], None)) - assert needs_conservative_livevar_calculation(block) - -def test_nclc_nongc_not_passed_on(): - # +--- inputargs: pointer_to_gc - # | v0 <- op_getsubstruct pointer_to_gc 'b' - # +--- exitargs: pointer_to_gc (i.e. the pointer to non-gc doesn't leave the block) - llops = LowLevelOpList() - ptr_a = varoftype(lltype.Ptr(GcA)) - v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)], - resulttype=lltype.Ptr(NonGcB)) - block = model.Block([ptr_a]) - block.operations.extend(llops) - block.closeblock(model.Link([ptr_a], None)) - assert not needs_conservative_livevar_calculation(block) - -def test_nclc_ignore_functype(): - # +--- inputargs: pointer_to_gc - # | v0 <- op_getfield pointer_to_gc 'c' - # +--- exitargs: v0 (i.e. a pointer to function) - # pointers to functions are 'not gc' but functions are also - # immortal so you don't need to muck around inserting keepalives - # so *they* don't die! - llops = LowLevelOpList() - ptr_a = varoftype(lltype.Ptr(GcA)) - v_res = llops.genop("getfield", [ptr_a, model.Constant('c', lltype.Void)], - resulttype=GcA.c) - block = model.Block([ptr_a]) - block.operations.extend(llops) - block.closeblock(model.Link([v_res], None)) - assert not needs_conservative_livevar_calculation(block) - -def test_sbwk_should_insert_keepalives(): - # this is testing something like: - # v0 <- op_producing_non_gc - # v1 <- op_using_v0 <- split here - llops = LowLevelOpList() - ptr_a = varoftype(lltype.Ptr(GcA)) - v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)], - resulttype=lltype.Ptr(NonGcB)) - llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res], - resulttype=lltype.Void) - block = model.Block([ptr_a]) - block.operations.extend(llops) - block.closeblock(model.Link([], None)) - link = split_block_with_keepalive(block, 1) - assert 'keepalive' in [op.opname for op in link.target.operations] - -def test_sbwk_should_insert_keepalives_2(): - # this is testing something like: - # v0 <- op_producing_non_gc - # v1 <- op_not_using_v0 <- split here - # v2 <- op_using_v0 - llops = LowLevelOpList() - ptr_a = varoftype(lltype.Ptr(GcA)) - v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)], - resulttype=lltype.Ptr(NonGcB)) - llops.genop("direct_call", [model.Constant(None, lltype.Void)], - resulttype=lltype.Void) - llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res], - resulttype=lltype.Void) - block = model.Block([ptr_a]) - block.operations.extend(llops) - block.closeblock(model.Link([], None)) - link = split_block_with_keepalive(block, 1) - assert 'keepalive' in [op.opname for op in link.target.operations] - #__________________________________________________________ # test loop detection Modified: pypy/branch/kill-keepalives/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/exceptiontransform.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/exceptiontransform.py Wed Sep 13 14:46:06 2006 @@ -1,7 +1,7 @@ from pypy.translator.simplify import join_blocks, cleanup_graph from pypy.translator.unsimplify import copyvar, varoftype -from pypy.translator.unsimplify import insert_empty_block -from pypy.translator.backendopt import canraise, inline, support, removenoops +from pypy.translator.unsimplify import insert_empty_block, split_block +from pypy.translator.backendopt import canraise, inline, removenoops from pypy.objspace.flow.model import Block, Constant, Variable, Link, \ c_last_exception, SpaceOperation, checkgraph, FunctionGraph from pypy.rpython.lltypesystem import lltype, llmemory @@ -206,7 +206,7 @@ if not self.raise_analyzer.can_raise(op): continue - splitlink = support.split_block_with_keepalive(block, i+1, False) + splitlink = split_block(None, block, i+1, False) afterblock = splitlink.target if lastblock is block: lastblock = afterblock Modified: pypy/branch/kill-keepalives/pypy/translator/stackless/transform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/stackless/transform.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/stackless/transform.py Wed Sep 13 14:46:06 2006 @@ -582,7 +582,7 @@ link = block.exits[0] nextblock = None else: - link = support.split_block_with_keepalive(block, i+1) + link = unsimplify.split_block(None, block, i+1) i = 0 nextblock = link.target @@ -746,7 +746,7 @@ exitcases = dict.fromkeys(l.exitcase for l in block.exits) nextblock = None else: - link = support.split_block_with_keepalive(block, i+1) + link = unsimplify.split_block(None, block, i+1) nextblock = link.target block.exitswitch = model.c_last_exception link.llexitcase = None Modified: pypy/branch/kill-keepalives/pypy/translator/unsimplify.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/unsimplify.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/unsimplify.py Wed Sep 13 14:46:06 2006 @@ -59,8 +59,7 @@ def split_block(annotator, block, index, dontshuffle=False): """return a link where prevblock is the block leading up but excluding the index'th operation and target is a new block with the neccessary variables - passed on. NOTE: if you call this after rtyping, you WILL need to worry - about keepalives, you may use backendopt.support.split_block_with_keepalive. + passed on. """ assert 0 <= index <= len(block.operations) if block.exitswitch == c_last_exception: From pedronis at codespeak.net Wed Sep 13 15:46:14 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Sep 2006 15:46:14 +0200 (CEST) Subject: [pypy-svn] r32262 - in pypy/dist/pypy: jit/timeshifter translator translator/backendopt Message-ID: <20060913134614.07C411007B@code0.codespeak.net> Author: pedronis Date: Wed Sep 13 15:46:12 2006 New Revision: 32262 Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/translator/backendopt/support.py pypy/dist/pypy/translator/unsimplify.py Log: kill the strange dontshuffle kw argument, instead use a different helper split_block_at_start, that reuses the other through a "private" kw argument. Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Wed Sep 13 15:46:12 2006 @@ -10,7 +10,7 @@ from pypy.jit.timeshifter import rtimeshift from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype from pypy.jit.timeshifter.rtyper import GreenRepr, RedRepr, HintLowLevelOpList -from pypy.translator.unsimplify import varoftype, copyvar +from pypy.translator.unsimplify import varoftype, copyvar, split_block_at_start from pypy.translator.backendopt import support from pypy.translator.c import exceptiontransform from pypy.jit.codegen import model as cgmodel @@ -406,9 +406,7 @@ # simple non-merging and non-returning case: nothing to do return - support.split_block_with_keepalive(block, 0, - annotator=self.hannotator, - dontshuffle=True) + split_block_at_start(self.hannotator, block) before_block = block newinputargs = before_block.inputargs llops = HintLowLevelOpList(self) Modified: pypy/dist/pypy/translator/backendopt/support.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/support.py (original) +++ pypy/dist/pypy/translator/backendopt/support.py Wed Sep 13 15:46:12 2006 @@ -71,10 +71,8 @@ def split_block_with_keepalive(block, index_operation, keep_alive_op_args=True, - annotator=None, - dontshuffle=False): - splitlink = split_block(annotator, block, index_operation, - dontshuffle=dontshuffle) + annotator=None): + splitlink = split_block(annotator, block, index_operation) afterblock = splitlink.target conservative_keepalives = needs_conservative_livevar_calculation(block) if conservative_keepalives: Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Wed Sep 13 15:46:12 2006 @@ -56,7 +56,7 @@ graph.startblock = graph.startblock.exits[0].target graph.startblock.isstartblock = True -def split_block(annotator, block, index, dontshuffle=False): +def split_block(annotator, block, index, _forcelink=None): """return a link where prevblock is the block leading up but excluding the index'th operation and target is a new block with the neccessary variables passed on. NOTE: if you call this after rtyping, you WILL need to worry @@ -100,14 +100,12 @@ exitswitch = get_new_name(block.exitswitch) #the new block gets all the attributes relevant to outgoing links #from block the old block - if not dontshuffle: - linkargs = varmap.keys() - newinputargs = varmap.values() - else: + if _forcelink is not None: assert index == 0 - linkargs = list(block.inputargs) - newinputargs = [get_new_name(v) for v in linkargs] - newblock = Block(newinputargs) + linkargs = list(_forcelink) + else: + linkargs = varmap.keys() + newblock = Block([get_new_name(v) for v in linkargs]) newblock.operations = moved_operations newblock.recloseblock(*links) newblock.exitswitch = exitswitch @@ -119,6 +117,11 @@ block.exc_handler = False return link +def split_block_at_start(annotator, block): + # split before the first op, preserve order and inputargs + # in the second block! + return split_block(annotator, block, 0, _forcelink=block.inputargs) + def remove_direct_loops(annotator, graph): """This is useful for code generators: it ensures that no link has common input and output variables, which could occur if a block's exit From fijal at codespeak.net Wed Sep 13 16:31:25 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 13 Sep 2006 16:31:25 +0200 (CEST) Subject: [pypy-svn] r32264 - in pypy/dist/pypy/translator/js: . jssrc test Message-ID: <20060913143125.7A7C01007B@code0.codespeak.net> Author: fijal Date: Wed Sep 13 16:31:22 2006 New Revision: 32264 Modified: pypy/dist/pypy/translator/js/helper.py pypy/dist/pypy/translator/js/jsbuiltin.py pypy/dist/pypy/translator/js/jssrc/misc.js pypy/dist/pypy/translator/js/test/test_seq.py pypy/dist/pypy/translator/js/test/test_transformer.py Log: Fixed substring, added test for that. Modified: pypy/dist/pypy/translator/js/helper.py ============================================================================== --- pypy/dist/pypy/translator/js/helper.py (original) +++ pypy/dist/pypy/translator/js/helper.py Wed Sep 13 16:31:22 2006 @@ -11,6 +11,7 @@ def create_debug_div(): debug_div = get_document().createElement("div") + debug_div.setAttribute("id", "debug_div") # XXX attach it somewhere... #body = get_document().getElementsByTagName('body')[0] get_document().childNodes[0].childNodes[1].appendChild(debug_div) Modified: pypy/dist/pypy/translator/js/jsbuiltin.py ============================================================================== --- pypy/dist/pypy/translator/js/jsbuiltin.py (original) +++ pypy/dist/pypy/translator/js/jsbuiltin.py Wed Sep 13 16:31:22 2006 @@ -43,7 +43,8 @@ 'll_startswith' : CallBuiltin('startswith'), 'll_endswith' : CallBuiltin('endswith'), 'll_split_chr' : CallBuiltin('splitchr'), - 'll_substring' : lambda g,op: Call._render_builtin_method(g, 'substring', [op.args[1], op.args[2], op.args[3]]), + #'ll_substring' : lambda g,op: Call._render_builtin_method(g, 'substring', [op.args[1], op.args[2], op.args[3]]), + 'll_substring' : CallBuiltin('substring'), 'll_lower' : lambda g, op: Call._render_builtin_method(g, 'toLowerCase', [op.args[1]]), 'll_upper' : lambda g, op: Call._render_builtin_method(g, 'toUpperCase', [op.args[1]]), }, Modified: pypy/dist/pypy/translator/js/jssrc/misc.js ============================================================================== --- pypy/dist/pypy/translator/js/jssrc/misc.js (original) +++ pypy/dist/pypy/translator/js/jssrc/misc.js Wed Sep 13 16:31:22 2006 @@ -158,4 +158,8 @@ return 0; } } + +function substring(s, l, c) { + return (s.substring(l, l+c)); +} // ends hand written code Modified: pypy/dist/pypy/translator/js/test/test_seq.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_seq.py (original) +++ pypy/dist/pypy/translator/js/test/test_seq.py Wed Sep 13 16:31:22 2006 @@ -112,6 +112,18 @@ fn = compile_function(upperlower, []) assert fn() == "ABAFabaf" + + def test_slice(self): + def one_slice(s): + return s[1:] + + def two_slice(s): + return s[2:] + + fn = compile_function(one_slice, [str]) + assert fn("dupa") == "upa" + fn = compile_function(two_slice, [str]) + assert fn("kupa") == "pa" def test_simple_seq(): def fun(i): Modified: pypy/dist/pypy/translator/js/test/test_transformer.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_transformer.py (original) +++ pypy/dist/pypy/translator/js/test/test_transformer.py Wed Sep 13 16:31:22 2006 @@ -158,3 +158,4 @@ lst = retval.split("|") assert len(lst) == 1 assert lst[0] == '' + From arigo at codespeak.net Wed Sep 13 17:49:16 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 17:49:16 +0200 (CEST) Subject: [pypy-svn] r32268 - pypy/dist/pypy/interpreter Message-ID: <20060913154916.5D4ED1007B@code0.codespeak.net> Author: arigo Date: Wed Sep 13 17:49:15 2006 New Revision: 32268 Modified: pypy/dist/pypy/interpreter/mixedmodule.py Log: Don't eat the traceback here... Modified: pypy/dist/pypy/interpreter/mixedmodule.py ============================================================================== --- pypy/dist/pypy/interpreter/mixedmodule.py (original) +++ pypy/dist/pypy/interpreter/mixedmodule.py Wed Sep 13 17:49:15 2006 @@ -3,7 +3,7 @@ from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root -import os +import os, sys import inspect @@ -131,8 +131,14 @@ raise # propagate the NameError try: d[name] = __import__(pkgroot+'.'+name, None, None, [name]) - except ImportError: - d[name] = __import__(name, None, None, [name]) + except ImportError: + etype, evalue, etb = sys.exc_info() + try: + d[name] = __import__(name, None, None, [name]) + except ImportError: + # didn't help, re-raise the original exception for + # clarity + raise etype, evalue, etb else: #print spec, "->", value if hasattr(value, 'func_code'): # semi-evil From arigo at codespeak.net Wed Sep 13 17:56:52 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 17:56:52 +0200 (CEST) Subject: [pypy-svn] r32269 - pypy/dist/pypy/translator/asm/ppcgen/test Message-ID: <20060913155652.05BCD1007B@code0.codespeak.net> Author: arigo Date: Wed Sep 13 17:56:50 2006 New Revision: 32269 Modified: pypy/dist/pypy/translator/asm/ppcgen/test/test_field.py Log: The maximum value for a PPC int is not always sys.maxint. Modified: pypy/dist/pypy/translator/asm/ppcgen/test/test_field.py ============================================================================== --- pypy/dist/pypy/translator/asm/ppcgen/test/test_field.py (original) +++ pypy/dist/pypy/translator/asm/ppcgen/test/test_field.py Wed Sep 13 17:56:50 2006 @@ -4,23 +4,24 @@ from py.test import raises import random -import sys + +maxppcint = 0x7fffffff class TestFields(object): def test_decode(self): # this test is crappy field = Field("test", 0, 31) for i in range(100): - j = random.randrange(sys.maxint) + j = random.randrange(maxppcint) assert field.decode(j) == j field = Field("test", 0, 31-4) for i in range(100): - j = random.randrange(sys.maxint) + j = random.randrange(maxppcint) assert field.decode(j) == j>>4 assert field.decode(j) == j>>4 field = Field("test", 3, 31-4) for i in range(100): - j = random.randrange(sys.maxint>>3) + j = random.randrange(maxppcint>>3) assert field.decode(j) == j>>4 From arigo at codespeak.net Wed Sep 13 18:03:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Sep 2006 18:03:36 +0200 (CEST) Subject: [pypy-svn] r32270 - pypy/dist/pypy/translator/test Message-ID: <20060913160336.224441007E@code0.codespeak.net> Author: arigo Date: Wed Sep 13 18:03:35 2006 New Revision: 32270 Modified: pypy/dist/pypy/translator/test/rpystone.py Log: Avoid a division by zero. Modified: pypy/dist/pypy/translator/test/rpystone.py ============================================================================== --- pypy/dist/pypy/translator/test/rpystone.py (original) +++ pypy/dist/pypy/translator/test/rpystone.py Wed Sep 13 18:03:35 2006 @@ -146,6 +146,8 @@ i += 1 benchtime = clock() - starttime - nulltime + if benchtime < 1E-8: + benchtime = 1E-8 # time too short, meaningless results anyway return benchtime, (loops / benchtime) def Proc1(PtrParIn): From rhymes at codespeak.net Thu Sep 14 09:52:19 2006 From: rhymes at codespeak.net (rhymes at codespeak.net) Date: Thu, 14 Sep 2006 09:52:19 +0200 (CEST) Subject: [pypy-svn] r32292 - in pypy/dist/pypy/module/rctime: . test Message-ID: <20060914075219.570D610074@code0.codespeak.net> Author: rhymes Date: Thu Sep 14 09:52:17 2006 New Revision: 32292 Modified: pypy/dist/pypy/module/rctime/interp_time.py pypy/dist/pypy/module/rctime/test/test_rctime.py Log: fixed tuple length checking in strftime and asctime Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Thu Sep 14 09:52:17 2006 @@ -342,8 +342,7 @@ if not space.is_w(w_tup, space.w_None): tuple_len = space.int_w(space.len(w_tup)) - # if space.is_w(w_tup, space.w_None) or 1 < tuple_len < 9: - if 1 < tuple_len < 9: + if tuple_len < 9: raise OperationError(space.w_TypeError, space.wrap("argument must be 9-item sequence")) @@ -483,8 +482,7 @@ if not space.is_w(w_tup, space.w_None): tuple_len = space.int_w(space.len(w_tup)) - #if space.is_w(w_tup, space.w_None) or 1 < tuple_len < 9: - if 1 < tuple_len < 9: + if tuple_len < 9: raise OperationError(space.w_TypeError, space.wrap("argument must be 9-item sequence")) Modified: pypy/dist/pypy/module/rctime/test/test_rctime.py ============================================================================== --- pypy/dist/pypy/module/rctime/test/test_rctime.py (original) +++ pypy/dist/pypy/module/rctime/test/test_rctime.py Thu Sep 14 09:52:17 2006 @@ -108,6 +108,9 @@ import rctime rctime.asctime() # raises(TypeError, rctime.asctime, None) + raises(TypeError, rctime.asctime, ()) + raises(TypeError, rctime.asctime, (1,)) + raises(TypeError, rctime.asctime, range(8)) raises(TypeError, rctime.asctime, (1, 2)) raises(TypeError, rctime.asctime, (1, 2, 3, 4, 5, 6, 'f', 8, 9)) raises(TypeError, rctime.asctime, "foo") @@ -205,6 +208,10 @@ 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = ' %' + directive rctime.strftime(format, tt) + + raises(TypeError, rctime.strftime, ()) + raises(TypeError, rctime.strftime, (1,)) + raises(TypeError, rctime.strftime, range(8)) def test_strftime_bounds_checking(self): import rctime From arigo at codespeak.net Thu Sep 14 11:04:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Sep 2006 11:04:43 +0200 (CEST) Subject: [pypy-svn] r32295 - pypy/dist/pypy/annotation Message-ID: <20060914090443.92FA410063@code0.codespeak.net> Author: arigo Date: Thu Sep 14 11:04:40 2006 New Revision: 32295 Modified: pypy/dist/pypy/annotation/binaryop.py Log: Forgot to check this in with the rctypes array slicing code. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Sep 14 11:04:40 2006 @@ -810,9 +810,8 @@ return s_result.return_annotation() class __extend__(pairtype(SomeCTypesObject, SomeSlice)): - # XXX ctypes array slicing not really supported for now def setitem((s_cto, s_slice), s_iterable): - pass + raise NotImplementedError("ctypes array slice assignment") def getitem((s_cto, s_slice)): result_ctype = s_cto.knowntype._type_ @@ -820,8 +819,8 @@ list_item = s_result.return_annotation() if isinstance(list_item, SomeChar): return SomeString() - listdef = ListDef(None, list_item) - return SomeList(listdef) + raise NotImplementedError("ctypes array slicing: " + "only for arrays of char") class __extend__(pairtype(SomeCTypesObject, SomeCTypesObject)): def union((s_cto1, s_cto2)): From arigo at codespeak.net Thu Sep 14 11:06:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Sep 2006 11:06:07 +0200 (CEST) Subject: [pypy-svn] r32296 - in pypy/dist/pypy: jit/hintannotator jit/timeshifter rpython Message-ID: <20060914090607.BBACA10063@code0.codespeak.net> Author: arigo Date: Thu Sep 14 11:06:05 2006 New Revision: 32296 Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/rpython/normalizecalls.py Log: (pedronis, arigo) Started to normalize the annotations of multiply-called graphs in the hintannotator. Tests missing. (Intermediate check-in before I upgrade subversion) Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Thu Sep 14 11:06:05 2006 @@ -2,6 +2,7 @@ from pypy.objspace.flow.model import copygraph, SpaceOperation from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype +from pypy.tool.algo.unionfind import UnionFind TLS = tlsobject() @@ -47,6 +48,14 @@ return graph +class TsGraphCallFamily: + def __init__(self, tsgraph): + self.tsgraphs = {tsgraph: True} + + def update(self, other): + self.tsgraphs.update(other.tsgraphs) + + class HintBookkeeper(object): def __init__(self, hannotator): @@ -54,6 +63,7 @@ self.originflags = {} self.virtual_containers = {} self.descs = {} + self.tsgraph_maximal_call_families = UnionFind(TsGraphCallFamily) self.annotator = hannotator # circular imports hack global hintmodel @@ -170,9 +180,11 @@ graph = desc.specialize(args_hs, key=key, alt_name=alt_name) return graph - def graph_call(self, graph, fixed, args_hs): + def graph_call(self, graph, fixed, args_hs, tsgraph_accum=None): input_args_hs = list(args_hs) graph = self.get_graph_for_call(graph, fixed, input_args_hs) + if tsgraph_accum is not None: + tsgraph_accum.append(graph) # save this if the caller cares # propagate fixing of arguments in the function to the caller for inp_arg_hs, arg_hs in zip(input_args_hs, args_hs): @@ -200,6 +212,18 @@ hs_res = hintmodel.reorigin(hs_res, *deps_hs) return hs_res + def graph_family_call(self, graph, fixed, args_hs): + tsgraphs = [] + results_hs = [] + for graph in graph_list: + results_hs.append(self.graph_call(graph, fixed, args_hs, tsgraphs)) + # put the tsgraphs in the same call family + call_families = self.tsgraph_maximal_call_families + _, rep, callfamily = call_families.find(tsgraphs[0]) + for tsgraph in tsgraphs[1:]: + _, rep, callfamily = call_families.union(rep, tsgraph) + return annmodel.unionof(*results_hs) + # get current bookkeeper def getbookkeeper(): Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Thu Sep 14 11:06:05 2006 @@ -280,9 +280,7 @@ bookkeeper = getbookkeeper() fixed = bookkeeper.myorigin().read_fixed() - results_hs = [bookkeeper.graph_call(graph, fixed, args_hs) - for graph in graph_list] - hs_res = annmodel.unionof(*results_hs) + hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs) if isinstance(hs_res, SomeLLAbstractConstant): hs_res.myorigin = bookkeeper.myorigin() Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 14 11:06:05 2006 @@ -17,8 +17,19 @@ offers_exceptiondata = False - def perform_normalizations(self, rtyper): - pass # for now + def perform_normalizations(self, hrtyper): + from pypy.rpython import normalizecalls + hannotator = hrtyper.annotator + call_families = hannotator.bookkeeper.tsgraph_maximal_call_families + while True: + progress = False + for callfamily in call_families.infos(): + graphs = callfamily.tsgraphs.keys() + progress |= normalizecalls.normalize_calltable_row_annotation( + hannotator, + graphs) + if not progress: + break # done HintTypeSystem.instance = HintTypeSystem() Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Thu Sep 14 11:06:05 2006 @@ -39,7 +39,8 @@ progress = False for shape, table in callfamily.calltables.items(): for row in table: - progress |= normalize_calltable_row_annotation(annotator, row) + progress |= normalize_calltable_row_annotation(annotator, + row.values()) if not progress: return # done assert not callfamily.normalized, "change in call family normalisation" @@ -126,10 +127,9 @@ did_something = True return did_something -def normalize_calltable_row_annotation(annotator, row): - if len(row) <= 1: +def normalize_calltable_row_annotation(annotator, graphs): + if len(graphs) <= 1: return False # nothing to do - graphs = row.values() graph_bindings = {} for graph in graphs: graph_bindings[graph] = [annotator.binding(v) From fijal at codespeak.net Thu Sep 14 11:16:54 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 11:16:54 +0200 (CEST) Subject: [pypy-svn] r32297 - in pypy/dist/pypy/translator/js: . modules Message-ID: <20060914091654.46F9B1006E@code0.codespeak.net> Author: fijal Date: Thu Sep 14 11:16:51 2006 New Revision: 32297 Modified: pypy/dist/pypy/translator/js/commproxy.py pypy/dist/pypy/translator/js/database.py pypy/dist/pypy/translator/js/modules/_dom.py Log: Add a possibility for URL mapping (will evolve in future to dict kind of stuff), added possibility of having XML requests instead of JSON (but who'll use them anyway?) Modified: pypy/dist/pypy/translator/js/commproxy.py ============================================================================== --- pypy/dist/pypy/translator/js/commproxy.py (original) +++ pypy/dist/pypy/translator/js/commproxy.py Thu Sep 14 11:16:51 2006 @@ -46,6 +46,18 @@ } """ +CALLBACK_XML_BODY = """ +function %(real_callback)s (x, cb) { + if (x.readyState == 4) { + if (x.responseXML) { + cb(x.responseXML.documentElement); + } else { + cb(null); + } + } +} +""" + MOCHIKIT_BODY = """ %(class)s.prototype.%(method)s = function ( %(args)s ) { var data,str; @@ -72,9 +84,11 @@ """ Class for rendering xmlhttp request communication over normal js code """ - def __init__(self, ext_obj, name): + def __init__(self, ext_obj, name, use_xml=False, base_url=""): self.ext_obj = ext_obj self.name = name + self.use_xml = use_xml + self.base_url = base_url def render(self, ilasm): self.render_body(ilasm) @@ -93,11 +107,22 @@ # FIXME: dirty JS here data = "{%s}" % ",".join(["'%s':%s" % (i,i) for i in real_args if i != 'callback']) real_callback = Variable("callback").name + if len(self.base_url) > 0 and not self.base_url.endswith("/"): + url = self.base_url + "/" +method_name + else: + url = self.base_url + method_name + + if USE_MOCHIKIT and self.use_xml: + assert 0, "Cannot use mochikit and xml requests at the same time" if USE_MOCHIKIT: - ilasm.codegenerator.write(MOCHIKIT_BODY % {'class':self.name, 'method':method_name,\ + ilasm.codegenerator.write(MOCHIKIT_BODY % {'class':self.name, 'method':url,\ 'args':','.join(real_args), 'data':data, 'call':method_name}) else: - ilasm.codegenerator.write(CALLBACK_BODY % {'real_callback':real_callback}) + if not self.use_xml: + callback_body = CALLBACK_BODY + else: + callback_body = CALLBACK_XML_BODY + ilasm.codegenerator.write(callback_body % {'real_callback':real_callback}) ilasm.codegenerator.write(METHOD_BODY % {'class':self.name, 'method':method_name,\ - 'args':",".join(real_args), 'data':data, 'call':method_name,\ + 'args':",".join(real_args), 'data':data, 'call':url,\ 'real_callback':real_callback}) Modified: pypy/dist/pypy/translator/js/database.py ============================================================================== --- pypy/dist/pypy/translator/js/database.py (original) +++ pypy/dist/pypy/translator/js/database.py Thu Sep 14 11:16:51 2006 @@ -95,11 +95,11 @@ def record_class(self, classdef, name): self.classes[classdef] = name - def register_comm_proxy(self, proxy_const, name): + def register_comm_proxy(self, proxy_const, name, use_xml, base_url): """ Register external object which should be rendered as method call """ - self.proxies.append(XmlHttp(proxy_const, name)) + self.proxies.append(XmlHttp(proxy_const, name, use_xml, base_url)) def graph_name(self, graph): return self.functions.get(graph, None) @@ -461,8 +461,12 @@ return self.const._TYPE._name.split('.')[-1][:-2] def init(self, ilasm): - if getattr(self.const._TYPE._class_, '_render_xmlhttp', False): - self.db.register_comm_proxy(self.const, self.name) + _class = self.const._TYPE._class_ + if getattr(_class, '_render_xmlhttp', False): + use_xml = getattr(_class, '_use_xml', False) + base_url = getattr(_class, '_base_url', "") # XXX: should be + # on per-method basis + self.db.register_comm_proxy(self.const, self.name, use_xml, base_url) ilasm.new(self.get_name()) else: # Otherwise they just exist, or it's not implemented Modified: pypy/dist/pypy/translator/js/modules/_dom.py ============================================================================== --- pypy/dist/pypy/translator/js/modules/_dom.py (original) +++ pypy/dist/pypy/translator/js/modules/_dom.py Thu Sep 14 11:16:51 2006 @@ -7,7 +7,7 @@ import time from pypy.rpython.ootypesystem.bltregistry import BasicExternal, MethodDesc -#from pypy.translator.stackless.test.test_transform import one +from pypy.translator.stackless.test.test_transform import one class Attribute(BasicExternal): pass From fijal at codespeak.net Thu Sep 14 11:36:46 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 11:36:46 +0200 (CEST) Subject: [pypy-svn] r32298 - pypy/dist/pypy/rpython Message-ID: <20060914093646.F3E2710071@code0.codespeak.net> Author: fijal Date: Thu Sep 14 11:36:44 2006 New Revision: 32298 Modified: pypy/dist/pypy/rpython/rexternalobj.py Log: Added ll_str method for BasicExternal Modified: pypy/dist/pypy/rpython/rexternalobj.py ============================================================================== --- pypy/dist/pypy/rpython/rexternalobj.py (original) +++ pypy/dist/pypy/rpython/rexternalobj.py Thu Sep 14 11:36:44 2006 @@ -32,6 +32,7 @@ def __init__(self, knowntype): self.knowntype = knowntype self.lowleveltype = knowntype + self.name = "" % self.knowntype._class_.__name__ def convert_const(self, value): from pypy.rpython.ootypesystem.bltregistry import ExternalType,_external_type @@ -66,7 +67,9 @@ def rtype_is_true(self, hop): vlist = hop.inputargs(self) return hop.genop('is_true', vlist, resulttype=lltype.Bool) - + + def ll_str(self, val): + return ootype.oostring(self.name, -1) def __getattr__(self, attr): if attr.startswith("rtype_method_"): From fijal at codespeak.net Thu Sep 14 11:39:39 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 11:39:39 +0200 (CEST) Subject: [pypy-svn] r32299 - in pypy/dist/pypy/jit/tl: . test Message-ID: <20060914093939.DC69C10071@code0.codespeak.net> Author: fijal Date: Thu Sep 14 11:39:37 2006 New Revision: 32299 Added: pypy/dist/pypy/jit/tl/braininterp.py (contents, props changed) pypy/dist/pypy/jit/tl/test/test_brainfuck.py (contents, props changed) Log: Added brainfuck interpreter (just to raise number of languages that can be JITed I suppose...) Added: pypy/dist/pypy/jit/tl/braininterp.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/tl/braininterp.py Thu Sep 14 11:39:37 2006 @@ -0,0 +1,52 @@ + +class BrainInterpreter(object): + def __init__(self): + self.table = [0] * 30000 + self.pointer = 0 + + def interp_char(self, code, code_pointer, input, output): + char_code = code[code_pointer] + if char_code == '>': + self.pointer += 1 + elif char_code == '<': + self.pointer -= 1 + elif char_code == '+': + self.table[self.pointer] += 1 + elif char_code == '-': + self.table[self.pointer] -= 1 + elif char_code == '.': + output.write(chr(self.table[self.pointer])) + elif char_code == ',': + self.table[self.pointer] = ord(input.read(1)) + elif char_code == '[': + # find corresponding ] + if self.table[self.pointer] == 0: + need = 1 + p = code_pointer + 1 + while need > 0: + if code[p] == ']': + need -= 1 + elif code[p] == '[': + need += 1 + p += 1 + return p + elif char_code == ']': + if self.table[self.pointer] != 0: + need = 1 + p = code_pointer - 1 + while need > 0: + if code[p] == ']': + need += 1 + elif code[p] == '[': + need -= 1 + p -= 1 + return p + 2 + return code_pointer + 1 + + def interpret(self, code, input_string, output_io): + code_pointer = 0 + while code_pointer < len(code): + code_pointer = self.interp_char(code, code_pointer, + input_string, output_io) + #print code_pointer, self.table[:5] + return output_io Added: pypy/dist/pypy/jit/tl/test/test_brainfuck.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/tl/test/test_brainfuck.py Thu Sep 14 11:39:37 2006 @@ -0,0 +1,45 @@ + +from pypy.jit.tl.braininterp import BrainInterpreter + +from StringIO import StringIO + +def run_code(code, inp): + inp_s = StringIO(inp) + out = StringIO() + b = BrainInterpreter() + b.interpret(code, inp_s, out) + return out.getvalue() + +def test_braintone(): + assert run_code("+++.","") == chr(3) + assert run_code("+++>+++.","") == chr(3) + assert run_code("""++++++++++ +[ The initial loop to set up useful values in the array + >+++++++>++++++++++>+++>+<<<<- +] +>++. print 'H' +>+. print 'e' ++++++++. 'l' +. 'l' ++++. 'o' +>++. space +<<+++++++++++++++. 'W' +>. 'o' ++++. 'r' +------. 'l' +--------. 'd' +>+. '!' +>. newline +""", "") == "Hello World!\n" + + code = ",----------[----------------------.,----------]" + assert run_code(code, "\x0a") == "" + assert run_code(code, "a\x0a") == "A" + assert run_code(code, "aa\x0a") == "AA" + assert run_code(code, "lowercase\x0a") == "LOWERCASE" + + add_code = ",>++++++[<-------->-],[<+>-],<.>." + + assert run_code(add_code, "43 ") == "7 " + assert run_code(add_code, "12 ") == "3 " + From mwh at codespeak.net Thu Sep 14 12:47:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 12:47:47 +0200 (CEST) Subject: [pypy-svn] r32301 - pypy/branch/kill-keepalives/pypy/translator/backendopt Message-ID: <20060914104747.2288110071@code0.codespeak.net> Author: mwh Date: Thu Sep 14 12:47:44 2006 New Revision: 32301 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Log: a tiny amount of support in malloc removal for get/setinteriorfield i think (hope) that malloc removal can become a fair bit less complicated in the end. Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Thu Sep 14 12:47:44 2006 @@ -176,6 +176,14 @@ return False # non-constant array index if op.opname in FIELD_ACCESS: pass # ok + elif op.opname == 'getinteriorfield': + for arg in op.args[1:]: + if not isinstance(arg, Constant): + return False + elif op.opname == 'setinteriorfield': + for arg in op.args[1:-1]: + if not isinstance(arg, Constant): + return False elif op.opname in SUBSTRUCT_ACCESS: S = op.args[0].concretetype.TO name = op.args[1].value @@ -298,6 +306,19 @@ op.result) newops.append(newop) last_removed_access = len(newops) + elif op.opname == "getinteriorfield": + S = op.args[0].concretetype.TO + key = tuple([S] + [a.value for a in op.args[1:]]) + newop = SpaceOperation("same_as", + [newvarsmap[key]], + op.result) + newops.append(newop) + last_removed_access = len(newops) + elif op.opname == "setinteriorfield": + S = op.args[0].concretetype.TO + key = tuple([S] + [a.value for a in op.args[1:-1]]) + newvarsmap[key] = op.args[-1] + last_removed_access = len(newops) elif op.opname in ("setfield", "setarrayitem"): S = op.args[0].concretetype.TO fldname = op.args[1].value From pedronis at codespeak.net Thu Sep 14 14:34:36 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Sep 2006 14:34:36 +0200 (CEST) Subject: [pypy-svn] r32305 - in pypy/dist/pypy/jit/hintannotator: . test Message-ID: <20060914123436.C437010071@code0.codespeak.net> Author: pedronis Date: Thu Sep 14 14:34:34 2006 New Revision: 32305 Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/container.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Log: simple tests about methods. fix a small bug in graph_family_call. The abstract container test is skipped: it explodes because our cast logic for abstract containers doesn't even try to do anything sane for dynamic casts from a small to a larger structs. Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Thu Sep 14 14:34:34 2006 @@ -212,7 +212,7 @@ hs_res = hintmodel.reorigin(hs_res, *deps_hs) return hs_res - def graph_family_call(self, graph, fixed, args_hs): + def graph_family_call(self, graph_list, fixed, args_hs): tsgraphs = [] results_hs = [] for graph in graph_list: Modified: pypy/dist/pypy/jit/hintannotator/container.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/container.py (original) +++ pypy/dist/pypy/jit/hintannotator/container.py Thu Sep 14 14:34:34 2006 @@ -104,6 +104,7 @@ else: for n in range(-down_or_up): vstruct = vstruct.vparent + assert vstruct return vstruct def fieldtype(self, name): Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Thu Sep 14 14:34:34 2006 @@ -531,3 +531,45 @@ assert isinstance(hs, SomeLLAbstractConstant) assert hs.is_green() assert not hs.is_fixed() + +def test_blue_simple_meth(): + py.test.skip("with abstract containers this test explode in the cast_pointer annotation logic") + class Base(object): + + def m(self): + raise NotImplementedError + + class Concrete(Base): + + def m(self): + return 42 + + def f(flag): + if flag: + o = Base() + else: + o = Concrete() + return o.m() + + hs = hannotate(f, [bool], policy=P_OOPSPEC) + + +def test_simple_meth(): + class Base(object): + + def m(self): + raise NotImplementedError + + class Concrete(Base): + + def m(self): + return 42 + + def f(flag): + if flag: + o = Base() + else: + o = Concrete() + return o.m() + + hs = hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL) From mwh at codespeak.net Thu Sep 14 15:08:14 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 15:08:14 +0200 (CEST) Subject: [pypy-svn] r32308 - pypy/branch/kill-keepalives/pypy/translator/backendopt Message-ID: <20060914130814.1B4CB10071@code0.codespeak.net> Author: mwh Date: Thu Sep 14 15:08:11 2006 New Revision: 32308 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Log: two more malloc removal tests pass Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Thu Sep 14 15:08:11 2006 @@ -164,6 +164,21 @@ "setarrayitem", "getarraysubstruct"]) accessed_substructs = {} + interior_fields = {} + + def add_interior_access(CONTAINER, FIELD_TYPE, args): + assert not isinstance(FIELD_TYPE, lltype.ContainerType) + assert isinstance(CONTAINER, lltype.ContainerType) + for arg in args: + if not isinstance(arg, Constant): + return False + key = tuple([CONTAINER] + [a.value for a in args]) + if key in interior_fields: + assert interior_fields[key] == FIELD_TYPE + else: + interior_fields[key] = FIELD_TYPE + return True + for up in info.usepoints: if up[0] != "op": @@ -177,13 +192,15 @@ if op.opname in FIELD_ACCESS: pass # ok elif op.opname == 'getinteriorfield': - for arg in op.args[1:]: - if not isinstance(arg, Constant): - return False + if not add_interior_access(op.args[0].concretetype.TO, + op.result.concretetype, + op.args[1:]): + return False elif op.opname == 'setinteriorfield': - for arg in op.args[1:-1]: - if not isinstance(arg, Constant): - return False + if not add_interior_access(op.args[0].concretetype.TO, + op.args[-1].concretetype, + op.args[1:-1]): + return False elif op.opname in SUBSTRUCT_ACCESS: S = op.args[0].concretetype.TO name = op.args[1].value @@ -253,6 +270,11 @@ #else: # the inlined substructure is never accessed, drop it + for key, T in interior_fields.iteritems(): + flatconstants[key] = Constant(T._defl(), T) + flatnames.append(key) + newvarstype[key] = T + flatten(STRUCT) assert len(direct_fieldptr_key) <= 1 From mwh at codespeak.net Thu Sep 14 15:43:05 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 15:43:05 +0200 (CEST) Subject: [pypy-svn] r32311 - in pypy/branch/kill-keepalives/pypy/translator/backendopt: . test Message-ID: <20060914134305.CD53710071@code0.codespeak.net> Author: mwh Date: Thu Sep 14 15:43:04 2006 New Revision: 32311 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Log: constant fold in between runs of remove_mallocs_once. remove recreation of remove_mallocs_once in test_malloc in favour of having a callback argument to remove_simple_mallocs Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Thu Sep 14 15:43:04 2006 @@ -4,6 +4,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.translator.simplify import remove_identical_vars from pypy.translator.backendopt.support import log +from pypy.translator.backendopt.constfold import constant_fold_graph class LifeTime: @@ -479,13 +480,16 @@ progress += _try_inline_malloc(info) return progress -def remove_simple_mallocs(graph): +def remove_simple_mallocs(graph, callback=None): """Iteratively remove (inline) the mallocs that can be simplified away.""" tot = 0 while True: count = remove_mallocs_once(graph) if count: log.malloc('%d simple mallocs removed in %r' % (count, graph.name)) + constant_fold_graph(graph) + if callback: + callback() tot += count else: break Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Thu Sep 14 15:43:04 2006 @@ -1,5 +1,5 @@ import py -from pypy.translator.backendopt.malloc import remove_mallocs_once +from pypy.translator.backendopt.malloc import remove_simple_mallocs from pypy.translator.backendopt.malloc import union_wrapper from pypy.translator.backendopt.inline import inline_function from pypy.translator.backendopt.all import backend_optimizations @@ -33,19 +33,15 @@ graph = graphof(t, fn) if option.view: t.view() - # to detect missing keepalives and broken intermediate graphs, - # we do the loop ourselves instead of calling remove_simple_mallocs() - while True: - progress = remove_mallocs_once(graph) - simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks())) + def callback(progress=True): if progress and option.view: t.view() if expected_result is not Ellipsis: interp = LLInterpreter(t.rtyper) res = interp.eval_graph(graph, args) assert res == expected_result - if not progress: - break + remove_simple_mallocs(graph, callback) + callback(False) if must_be_removed: check_malloc_removed(graph) From mwh at codespeak.net Thu Sep 14 15:49:59 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 15:49:59 +0200 (CEST) Subject: [pypy-svn] r32312 - pypy/branch/kill-keepalives/pypy/translator/backendopt/test Message-ID: <20060914134959.C15441006C@code0.codespeak.net> Author: mwh Date: Thu Sep 14 15:49:58 2006 New Revision: 32312 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Log: add a call to checkgraph in the malloc removal loop while testing Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Thu Sep 14 15:49:58 2006 @@ -34,6 +34,7 @@ if option.view: t.view() def callback(progress=True): + checkgraph(graph) if progress and option.view: t.view() if expected_result is not Ellipsis: From fijal at codespeak.net Thu Sep 14 16:12:58 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 16:12:58 +0200 (CEST) Subject: [pypy-svn] r32313 - in pypy/dist/pypy: annotation translator/js/test Message-ID: <20060914141258.5AA4210071@code0.codespeak.net> Author: fijal Date: Thu Sep 14 16:12:56 2006 New Revision: 32313 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/js/test/test_basicexternal.py Log: Fixed listdefs/dictdefs for annotation_from_example Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Sep 14 16:12:56 2006 @@ -455,22 +455,32 @@ elif tp is float: result = SomeFloat() elif tp is list: - result = SomeList(ListDef(self, s_ImpossibleValue)) - for e in x: - result.listdef.generalize(self.annotation_from_example(e)) + # try to get listdef + try: + listdef = self.listdefs[self.position_key] + except KeyError: + listdef = ListDef(self, s_ImpossibleValue) + for e in x: + listdef.generalize(self.annotation_from_example(e)) + self.listdefs[self.position_key] = listdef + result = SomeList(listdef) elif tp is dict or tp is r_dict: - result = SomeDict(DictDef(self, - s_ImpossibleValue, - s_ImpossibleValue, - is_r_dict = tp is r_dict)) - if tp is r_dict: - s_eqfn = self.immutablevalue(x.key_eq) - s_hashfn = self.immutablevalue(x.key_hash) - result.dictdef.dictkey.update_rdict_annotations(s_eqfn, + try: + dictdef = self.dictdefs[self.position_key] + except KeyError: + dictdef = DictDef(self, + s_ImpossibleValue, + s_ImpossibleValue, + is_r_dict = tp is r_dict) + if tp is r_dict: + s_eqfn = self.immutablevalue(x.key_eq) + s_hashfn = self.immutablevalue(x.key_hash) + dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) - for ek, ev in x.iteritems(): - result.dictdef.generalize_key(self.annotation_from_example(ek)) - result.dictdef.generalize_value(self.annotation_from_example(ev)) + for ek, ev in x.iteritems(): + dictdef.generalize_key(self.annotation_from_example(ek)) + dictdef.generalize_value(self.annotation_from_example(ev)) + result = SomeDict(dictdef) elif ishashable(x) and x in BUILTIN_ANALYZERS: _module = getattr(x,"__module__","unknown") result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__)) Modified: pypy/dist/pypy/translator/js/test/test_basicexternal.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_basicexternal.py (original) +++ pypy/dist/pypy/translator/js/test/test_basicexternal.py Thu Sep 14 16:12:56 2006 @@ -63,3 +63,22 @@ fun = compile_function(raising_method_call, []) assert len(C._methods) == 1 assert 'f' in C._methods + +class D(BasicExternal): + _fields = { + 'a': {"aa":"aa"}, + 'b': ["aa"], + } + +d = D() + +def test_basicexternal_list(): + def return_dict(): + return d.a + + def return_list(): + return d.b + + fun1 = compile_function(return_dict, []) + fun2 = compile_function(return_list, []) + From cfbolz at codespeak.net Thu Sep 14 16:22:22 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 14 Sep 2006 16:22:22 +0200 (CEST) Subject: [pypy-svn] r32314 - pypy/dist/pypy/doc/js Message-ID: <20060914142222.7440310071@code0.codespeak.net> Author: cfbolz Date: Thu Sep 14 16:22:19 2006 New Revision: 32314 Added: pypy/dist/pypy/doc/js/style.css Log: add css to js dir to get the nice rendering Added: pypy/dist/pypy/doc/js/style.css ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/js/style.css Thu Sep 14 16:22:19 2006 @@ -0,0 +1,1090 @@ +body,body.editor,body.body { + font: 90% "Times New Roman", Arial, Verdana, Helvetica, serif; + background: White; + color: Black; +} + +a, a.reference { + text-decoration: none; +} +a[href]:hover { text-decoration: underline; } + +img { + border: none; + vertical-align: middle; +} + +p, div.text { + text-align: left; + line-height: 1.5em; + margin: 0.5em 0em 0em 0em; +} + + + +p a:active { + color: Red; + background-color: transparent; +} + +p img { + border: 0; + margin: 0; +} + +img.inlinephoto { + padding: 0; + padding-right: 1em; + padding-top: 0.7em; + float: left; +} + +hr { + clear: both; + height: 1px; + color: #8CACBB; + background-color: transparent; +} + + +ul { + line-height: 1.5em; + /*list-style-image: url("bullet.gif"); */ + margin-left: 1.5em; + padding:0; +} + +ol { + line-height: 1.5em; + margin-left: 1.5em; + padding:0; +} + +ul a, ol a { + text-decoration: underline; +} + +dl { +} + +dt { + font-weight: bold; +} + +dd { + line-height: 1.5em; + margin-bottom: 1em; +} + +blockquote { + font-family: Times, "Times New Roman", serif; + font-style: italic; + font-size: 120%; +} + +code { + color: Black; + /*background-color: #dee7ec;*/ + background-color: #cccccc; +} + +pre { + padding: 1em; + border: 1px solid #8cacbb; + color: Black; + background-color: #dee7ec; + background-color: #cccccc; + overflow: auto; +} + + +.netscape4 { + display: none; +} + +/* main page styles */ + +/*a[href]:hover { color: black; text-decoration: underline; } +a[href]:link { color: black; text-decoration: underline; } +a[href] { color: black; text-decoration: underline; } +*/ + +span.menu_selected { + color: black; + font: 120% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; + padding-right: 0.3em; + background-color: #cccccc; +} + + +a.menu { + /*color: #3ba6ec; */ + font: 120% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; + padding-right: 0.3em; +} + +a.menu[href]:visited, a.menu[href]:link{ + /*color: #3ba6ec; */ + font: 120% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; +} + +a.menu[href]:hover { + /*color: black;*/ +} + +div.project_title{ + /*border-spacing: 20px;*/ + font: 160% Verdana, Helvetica, Arial, sans-serif; + color: #3ba6ec; + vertical-align: center; + padding-bottom: 0.3em; +} + +a.wikicurrent { + font: 100% Verdana, Helvetica, Arial, sans-serif; + color: #3ba6ec; + vertical-align: middle; +} + + +table.body { + border: 0; + /*padding: 0; + border-spacing: 0px; + border-collapse: separate; + */ +} + +td.page-header-left { + padding: 5px; + /*border-bottom: 1px solid #444444;*/ +} + +td.page-header-top { + padding: 0; + + /*border-bottom: 1px solid #444444;*/ +} + +td.sidebar { + padding: 1 0 0 1; +} + +td.sidebar p.classblock { + padding: 0 5 0 5; + margin: 1 1 1 1; + border: 1px solid #444444; + background-color: #eeeeee; +} + +td.sidebar p.userblock { + padding: 0 5 0 5; + margin: 1 1 1 1; + border: 1px solid #444444; + background-color: #eeeeff; +} + +td.content { + padding: 1 5 1 5; + vertical-align: top; + width: 100%; +} + +p.ok-message { + background-color: #22bb22; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} +p.error-message { + background-color: #bb2222; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} + +p:first-child { + margin: 0 ; + padding: 0; +} + +/* style for forms */ +table.form { + padding: 2; + border-spacing: 0px; + border-collapse: separate; +} + +table.form th { + color: #333388; + text-align: right; + vertical-align: top; + font-weight: normal; +} +table.form th.header { + font-weight: bold; + background-color: #eeeeff; + text-align: left; +} + +table.form th.required { + font-weight: bold; +} + +table.form td { + color: #333333; + empty-cells: show; + vertical-align: top; +} + +table.form td.optional { + font-weight: bold; + font-style: italic; +} + +table.form td.html { + color: #777777; +} + +/* style for lists */ +table.list { + border-spacing: 0px; + border-collapse: separate; + vertical-align: top; + padding-top: 0; + width: 100%; +} + +table.list th { + padding: 0 4 0 4; + color: #404070; + background-color: #eeeeff; + border-right: 1px solid #404070; + border-top: 1px solid #404070; + border-bottom: 1px solid #404070; + vertical-align: top; + empty-cells: show; +} +table.list th a[href]:hover { color: #404070 } +table.list th a[href]:link { color: #404070 } +table.list th a[href] { color: #404070 } +table.list th.group { + background-color: #f4f4ff; + text-align: center; + font-size: 120%; +} + +table.list td { + padding: 0 4 0 4; + border: 0 2 0 2; + border-right: 1px solid #404070; + color: #404070; + background-color: white; + vertical-align: top; + empty-cells: show; +} + +table.list tr.normal td { + background-color: white; + white-space: nowrap; +} + +table.list tr.alt td { + background-color: #efefef; + white-space: nowrap; +} + +table.list td:first-child { + border-left: 1px solid #404070; + border-right: 1px solid #404070; +} + +table.list th:first-child { + border-left: 1px solid #404070; + border-right: 1px solid #404070; +} + +table.list tr.navigation th { + text-align: right; +} +table.list tr.navigation th:first-child { + border-right: none; + text-align: left; +} + + +/* style for message displays */ +table.messages { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.messages th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.messages th { + font-weight: bold; + color: black; + text-align: left; + border-bottom: 1px solid #afafaf; +} + +table.messages td { + font-family: monospace; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + color: black; + empty-cells: show; + border-right: 1px solid #afafaf; + vertical-align: top; + padding: 2 5 2 5; +} + +table.messages td:first-child { + border-left: 1px solid #afafaf; + border-right: 1px solid #afafaf; +} + +/* style for file displays */ +table.files { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.files th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.files th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +table.files td { + font-family: monospace; + empty-cells: show; +} + +/* style for history displays */ +table.history { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.history th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; + font-size: 100%; +} + +table.history th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; + font-size: 90%; +} + +table.history td { + font-size: 90%; + vertical-align: top; + empty-cells: show; +} + + +/* style for class list */ +table.classlist { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.classlist th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.classlist th { + font-weight: bold; + text-align: left; +} + + +/* style for class help display */ +table.classhelp { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.classhelp th { + font-weight: bold; + text-align: left; + color: #707040; +} + +table.classhelp td { + padding: 2 2 2 2; + border: 1px solid black; + text-align: left; + vertical-align: top; + empty-cells: show; +} + + +/* style for "other" displays */ +table.otherinfo { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.otherinfo th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.otherinfo th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +input { + border: 1px solid #8cacbb; + color: Black; + background-color: white; + vertical-align: middle; + margin-bottom: 1px; /* IE bug fix */ + padding: 0.1em; +} + +select { + border: 1px solid #8cacbb; + color: Black; + background-color: white; + vertical-align: middle; + margin-bottom: 1px; /* IE bug fix */ + padding: 0.1em; +} + + +a.nonexistent { + color: #FF2222; +} +a.nonexistent:visited { + color: #FF2222; +} +a.external { + color: #AA6600; +} + +/* +dl,ul,ol { + margin-top: 1pt; +} +tt,pre { + font-family: Lucida Console,Courier New,Courier,monotype; + font-size: 12pt; +} +pre.code { + margin-top: 8pt; + margin-bottom: 8pt; + background-color: #FFFFEE; + white-space:pre; + border-style:solid; + border-width:1pt; + border-color:#999999; + color:#111111; + padding:5px; + width:100%; +} +*/ +div.diffold { + background-color: #FFFF80; + border-style:none; + border-width:thin; + width:100%; +} +div.diffnew { + background-color: #80FF80; + border-style:none; + border-width:thin; + width:100%; +} +div.message { + margin-top: 6pt; + background-color: #E8FFE8; + border-style:solid; + border-width:1pt; + border-color:#999999; + color:#440000; + padding:5px; + width:100%; +} +strong.highlight { + background-color: #FFBBBB; +/* as usual, NetScape fucks up with innocent CSS + border-color: #FFAAAA; + border-style: solid; + border-width: 1pt; +*/ +} + +table.navibar { + background-color: #C8C8C8; + border-spacing: 3px; +} +td.navibar { + background-color: #E8E8E8; + vertical-align: top; + text-align: right; + padding: 0px; +} + +div.pagename { + font-size: 140%; + color: blue; + text-align: center; + font-weight: bold; + background-color: white; + padding: 0 ; +} + +a.wikiaction, input.wikiaction { + color: black; + text-decoration: None; + text-align: center; + color: black; + /*border: 1px solid #3ba6ec; */ + margin: 4px; + padding: 5; + padding-bottom: 0; + white-space: nowrap; +} + +a.wikiaction[href]:hover { + color: black; + text-decoration: none; + /*background-color: #dddddd; */ +} + +span.wikiuserpref { + padding-top: 1em; + font-size: 120%; +} + +div.wikitrail { + vertical-align: bottom; + /*font-size: -1;*/ + padding-top: 1em; + display: none; +} + +div.wikiaction { + vertical-align: middle; + /*border-bottom: 1px solid #8cacbb;*/ + padding-bottom:1em; + text-align: left; + width: 100%; +} + +div.wikieditmenu { + text-align: right; +} + +form.wikiedit { + border: 1px solid #8cacbb; + background-color: #f0f0f0; + background-color: #fabf00; + padding: 1em; + padding-right: 0em; +} + +div.legenditem { + padding-top: 0.5em; + padding-left: 0.3em; +} + +span.wikitoken { + background-color: #eeeeee; +} + + +div#contentspace h1:first-child, div.heading:first-child { + padding-top: 0; + margin-top: 0; +} +div#contentspace h2:first-child { + padding-top: 0; + margin-top: 0; +} + +/* heading and paragraph text */ + +div.heading, h1 { + font-family: Verdana, Helvetica, Arial, sans-serif; + background-color: #58b3ef; + background-color: #FFFFFF; + /*color: #4893cf;*/ + color: black; + padding-top: 1.0em; + padding-bottom:0.2em; + text-align: left; + margin-top: 0em; + /*margin-bottom:8pt;*/ + font-weight: bold; + font-size: 115%; + border-bottom: 1px solid #8CACBB; +} + + +h1, h2, h3, h4, h5, h6 { + color: Black; + clear: left; + font: 100% Verdana, Helvetica, Arial, sans-serif; + margin: 0; + padding-left: 0em; + padding-top: 1em; + padding-bottom: 0.2em; + /*border-bottom: 1px solid #8CACBB;*/ +} +/* h1,h2 { padding-top: 0; }*/ + + +h1 { font-size: 145%; } +h2 { font-size: 135%; } +h3 { font-size: 125%; } +h4 { font-size: 120%; } +h5 { font-size: 110%; } +h6 { font-size: 80%; } + +h1 a { text-decoration: None;} + +div.exception { + background-color: #bb2222; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} +pre.exception { + font-size: 110%; + padding: 1em; + border: 1px solid #8cacbb; + color: Black; + background-color: #dee7ec; + background-color: #cccccc; +} + +/* defines for navgiation bar (documentation) */ + + +div.direntry { + padding-top: 0.3em; + padding-bottom: 0.3em; + margin-right: 1em; + font-weight: bold; + background-color: #dee7ec; + font-size: 110%; +} + +div.fileentry { + font-family: Verdana, Helvetica, Arial, sans-serif; + padding-bottom: 0.3em; + white-space: nowrap; + line-height: 150%; +} + +a.fileentry { + white-space: nowrap; +} + + +span.left { + text-align: left; +} +span.right { + text-align: right; +} + +div.navbar { + /*margin: 0;*/ + font-size: 80% /*smaller*/; + font-weight: bold; + text-align: left; + /* position: fixed; */ + top: 100pt; + left: 0pt; /* auto; */ + width: 120pt; + /* right: auto; + right: 0pt; 2em; */ +} + + +div.history a { + /* font-size: 70%; */ +} + +div.wikiactiontitle { + font-weight: bold; +} + +/* REST defines */ + +div.document { + margin: 0; +} + +h1.title { + margin: 0; +} + +td.toplist { + vertical-align: top; +} + +img#pyimg { + position: absolute; + top: 4px; + left: 4px; +} + +img#extraimg { + position: absolute; + right: 14px; + top: 4px; +} + +div#navspace { + position: absolute; + top: 130px; + left: 11px; + font-size: 100%; + width: 150px; + overflow: hidden; /* scroll; */ +} + +div#metaspace { + position: absolute; + top: 40px; + left: 170px; +} + +div#errorline { + position: relative; + top: 5px; + float: right; +} + +div#contentspace { + position: absolute; + /* font: 120% "Times New Roman", serif;*/ + font: 110% Verdana, Helvetica, Arial, sans-serif; + top: 130px; + left: 170px; + margin-right: 5px; +} + +div#menubar { +/* width: 400px; */ + float: left; +} + +/* for the documentation page */ +div#docinfoline { + position: relative; + top: 5px; + left: 0px; + + /*background-color: #dee7ec; */ + padding: 5pt; + padding-bottom: 1em; + color: black; + /*border-width: 1pt; + border-style: solid;*/ + +} + +div#docnavlist { + /*background-color: #dee7ec; */ + padding: 5pt; + padding-bottom: 2em; + color: black; + border-width: 1pt; + /*border-style: solid;*/ +} + + +/* text markup */ + +div.listtitle { + color: Black; + clear: left; + font: 120% Verdana, Helvetica, Arial, sans-serif; + margin: 0; + padding-left: 0em; + padding-top: 0em; + padding-bottom: 0.2em; + margin-right: 0.5em; + border-bottom: 1px solid #8CACBB; +} + +div.actionbox h3 { + padding-top: 0; + padding-right: 0.5em; + padding-left: 0.5em; + background-color: #fabf00; + text-align: center; + border: 1px solid black; /* 8cacbb; */ +} + +div.actionbox a { + display: block; + padding-bottom: 0.5em; + padding-top: 0.5em; + margin-left: 0.5em; +} + +div.actionbox a.history { + display: block; + padding-bottom: 0.5em; + padding-top: 0.5em; + margin-left: 0.5em; + font-size: 90%; +} + +div.actionbox { + margin-bottom: 2em; + padding-bottom: 1em; + overflow: hidden; /* scroll; */ +} + +/* taken from docutils (oh dear, a bit senseless) */ +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + + +/* +:Author: David Goodger +:Contact: goodger at users.sourceforge.net +:date: $Date: 2003/01/22 22:26:48 $ +:version: $Revision: 1.29 $ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ +/* +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } +*/ + +div.section { + margin-top: 1.0em ; +} + +div.abstract { + margin: 2em 4em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } From fijal at codespeak.net Thu Sep 14 17:14:22 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 17:14:22 +0200 (CEST) Subject: [pypy-svn] r32318 - pypy/dist/pypy/annotation Message-ID: <20060914151422.3073A1006E@code0.codespeak.net> Author: fijal Date: Thu Sep 14 17:14:19 2006 New Revision: 32318 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: Reverted stupid fix. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Sep 14 17:14:19 2006 @@ -455,31 +455,24 @@ elif tp is float: result = SomeFloat() elif tp is list: - # try to get listdef - try: - listdef = self.listdefs[self.position_key] - except KeyError: - listdef = ListDef(self, s_ImpossibleValue) - for e in x: - listdef.generalize(self.annotation_from_example(e)) - self.listdefs[self.position_key] = listdef + listdef = ListDef(self, s_ImpossibleValue) + for e in x: + listdef.generalize(self.annotation_from_example(e)) + self.listdefs[self.position_key] = listdef result = SomeList(listdef) elif tp is dict or tp is r_dict: - try: - dictdef = self.dictdefs[self.position_key] - except KeyError: - dictdef = DictDef(self, - s_ImpossibleValue, - s_ImpossibleValue, - is_r_dict = tp is r_dict) - if tp is r_dict: - s_eqfn = self.immutablevalue(x.key_eq) - s_hashfn = self.immutablevalue(x.key_hash) - dictdef.dictkey.update_rdict_annotations(s_eqfn, - s_hashfn) - for ek, ev in x.iteritems(): - dictdef.generalize_key(self.annotation_from_example(ek)) - dictdef.generalize_value(self.annotation_from_example(ev)) + dictdef = DictDef(self, + s_ImpossibleValue, + s_ImpossibleValue, + is_r_dict = tp is r_dict) + if tp is r_dict: + s_eqfn = self.immutablevalue(x.key_eq) + s_hashfn = self.immutablevalue(x.key_hash) + dictdef.dictkey.update_rdict_annotations(s_eqfn, + s_hashfn) + for ek, ev in x.iteritems(): + dictdef.generalize_key(self.annotation_from_example(ek)) + dictdef.generalize_value(self.annotation_from_example(ev)) result = SomeDict(dictdef) elif ishashable(x) and x in BUILTIN_ANALYZERS: _module = getattr(x,"__module__","unknown") From fijal at codespeak.net Thu Sep 14 17:15:01 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 17:15:01 +0200 (CEST) Subject: [pypy-svn] r32319 - pypy/dist/pypy/rpython/ootypesystem Message-ID: <20060914151501.930B81006E@code0.codespeak.net> Author: fijal Date: Thu Sep 14 17:15:00 2006 New Revision: 32319 Modified: pypy/dist/pypy/rpython/ootypesystem/bltregistry.py Log: Fixed caching of s_values. Modified: pypy/dist/pypy/rpython/ootypesystem/bltregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/bltregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/bltregistry.py Thu Sep 14 17:15:00 2006 @@ -106,7 +106,7 @@ described = BasicExternal.described class Analyzer(object): - def __init__(self, name, value): + def __init__(self, name, value, s_retval, s_args): self.name = name # dirty hack # FIXME: to replace in future @@ -114,24 +114,17 @@ # itervalues = value.args[:-1] #else: # itervalues = value.args - self.args, self.retval = [i.example for i in value.args], value.retval.example + self.args, self.retval = value.args, value.retval + self.s_retval = s_retval + self.s_args = s_args self.value = value def __call__(self, *args): - #for i in xrange(len(args)): - # assert getbookkeeper().valueoftype(self.args[i]).contains(args[i]) - #if self.retval is None: - # return None - ann_retval = getbookkeeper().annotation_from_example(self.retval) - for i in args: if isinstance(i, annmodel.SomePBC): bookkeeper = getbookkeeper() - #import pdb;pdb.set_trace() - #bookkeeper.pbc_call(i, bookkeeper.build_args("simple_call", [bookkeeper.annotation_from_example(arg) for arg in self.args])) - - bookkeeper.pbc_call(i, bookkeeper.build_args("simple_call", (ann_retval,))) - return ann_retval + bookkeeper.pbc_call(i, bookkeeper.build_args("simple_call", (self.s_retval,))) + return self.s_retval class ExternalType(ootype.OOType): class_dict = {} @@ -165,8 +158,9 @@ for i, val in _methods.iteritems(): retval = getbookkeeper().annotation_from_example(val.retval.example) values = [arg.example for arg in val.args] - _signs[i] = MethodDesc(tuple([getbookkeeper().annotation_from_example(j) for j in values]), retval) - next = annmodel.SomeBuiltin(Analyzer(i, val), s_self = annmodel.SomeExternalBuiltin(self), methodname = i) + s_args = [getbookkeeper().annotation_from_example(j) for j in values] + _signs[i] = MethodDesc(tuple(s_args), retval) + next = annmodel.SomeBuiltin(Analyzer(i, val, retval, s_args), s_self = annmodel.SomeExternalBuiltin(self), methodname = i) next.const = True self._fields[i] = next self._methods = frozendict(_signs) From fijal at codespeak.net Thu Sep 14 17:15:28 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 17:15:28 +0200 (CEST) Subject: [pypy-svn] r32320 - in pypy/dist/pypy/translator/js: . test Message-ID: <20060914151528.E011E10071@code0.codespeak.net> Author: fijal Date: Thu Sep 14 17:15:26 2006 New Revision: 32320 Modified: pypy/dist/pypy/translator/js/commproxy.py pypy/dist/pypy/translator/js/database.py pypy/dist/pypy/translator/js/test/test_basicexternal.py pypy/dist/pypy/translator/js/test/test_bltn.py Log: Added some tests for external objects. Added possibility to run POST method. Modified: pypy/dist/pypy/translator/js/commproxy.py ============================================================================== --- pypy/dist/pypy/translator/js/commproxy.py (original) +++ pypy/dist/pypy/translator/js/commproxy.py Thu Sep 14 17:15:26 2006 @@ -6,7 +6,7 @@ from pypy.objspace.flow.model import Variable, Constant from pypy.rpython.ootypesystem.bltregistry import ArgDesc -METHOD_BODY = """ +GET_METHOD_BODY = """ %(class)s.prototype.%(method)s = function ( %(args)s ) { var data,str; var x = new XMLHttpRequest(); @@ -32,6 +32,32 @@ } """ +POST_METHOD_BODY = """ +%(class)s.prototype.%(method)s = function ( %(args)s ) { + var data,str; + var x = new XMLHttpRequest(); + data = %(data)s; + str = "" + for(i in data) { + if (data[i]) { + if (str.length == 0) { + str += "?"; + } else { + str += "&"; + } + str += i + "=" + data[i].toString(); + } + } + //logDebug('%(call)s'+str); + x.open("POST", '%(call)s', true); + //x.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + x.onreadystatechange = function () { %(real_callback)s(x, callback) }; + //x.setRequestHeader("Connection", "close"); + x.send(str); + x.send(null); +} +""" + CALLBACK_BODY = """ function %(real_callback)s (x, cb) { var d; @@ -84,11 +110,12 @@ """ Class for rendering xmlhttp request communication over normal js code """ - def __init__(self, ext_obj, name, use_xml=False, base_url=""): + def __init__(self, ext_obj, name, use_xml=False, base_url="", method="GET"): self.ext_obj = ext_obj self.name = name self.use_xml = use_xml self.base_url = base_url + self.method = method def render(self, ilasm): self.render_body(ilasm) @@ -112,6 +139,7 @@ else: url = self.base_url + method_name + METHOD_BODY = globals()[self.method + "_METHOD_BODY"] if USE_MOCHIKIT and self.use_xml: assert 0, "Cannot use mochikit and xml requests at the same time" if USE_MOCHIKIT: Modified: pypy/dist/pypy/translator/js/database.py ============================================================================== --- pypy/dist/pypy/translator/js/database.py (original) +++ pypy/dist/pypy/translator/js/database.py Thu Sep 14 17:15:26 2006 @@ -95,11 +95,11 @@ def record_class(self, classdef, name): self.classes[classdef] = name - def register_comm_proxy(self, proxy_const, name, use_xml, base_url): + def register_comm_proxy(self, proxy_const, *args): """ Register external object which should be rendered as method call """ - self.proxies.append(XmlHttp(proxy_const, name, use_xml, base_url)) + self.proxies.append(XmlHttp(proxy_const, *args)) def graph_name(self, graph): return self.functions.get(graph, None) @@ -465,8 +465,9 @@ if getattr(_class, '_render_xmlhttp', False): use_xml = getattr(_class, '_use_xml', False) base_url = getattr(_class, '_base_url', "") # XXX: should be + method = getattr(_class, '_use_method', 'GET') # on per-method basis - self.db.register_comm_proxy(self.const, self.name, use_xml, base_url) + self.db.register_comm_proxy(self.const, self.name, use_xml, base_url, method) ilasm.new(self.get_name()) else: # Otherwise they just exist, or it's not implemented Modified: pypy/dist/pypy/translator/js/test/test_basicexternal.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_basicexternal.py (original) +++ pypy/dist/pypy/translator/js/test/test_basicexternal.py Thu Sep 14 17:15:26 2006 @@ -70,15 +70,25 @@ 'b': ["aa"], } +D._fields['c'] = [D(),D()] + d = D() def test_basicexternal_list(): + def getaa(item): + return d.c[item] + + def return_list(i): + one = getaa(i) + if one: + two = getaa(i + 3) + return two + return one + + fun2 = compile_function(return_list, [int]) + +def test_basicextenal_dict(): def return_dict(): return d.a - def return_list(): - return d.b - fun1 = compile_function(return_dict, []) - fun2 = compile_function(return_list, []) - Modified: pypy/dist/pypy/translator/js/test/test_bltn.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_bltn.py (original) +++ pypy/dist/pypy/translator/js/test/test_bltn.py Thu Sep 14 17:15:26 2006 @@ -50,3 +50,22 @@ fn = compile_function(callback_stuff, []) assert check_source_contains(fn, "\.some_callback = callback") + +def test_get_elements(): + from pypy.translator.js.modules import _dom as dom + + def getaa(tname): + return dom.get_document().getElementsByTagName(tname)[0].nodeValue + + def some_stuff(): + one = getaa("some") + if one: + two = getaa("other") + return two + # if two: + # return one + two + # else: + # return one + return one + + fn = compile_function(some_stuff, []) From mwh at codespeak.net Thu Sep 14 17:27:20 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 17:27:20 +0200 (CEST) Subject: [pypy-svn] r32321 - pypy/branch/kill-keepalives/pypy/translator/backendopt/test Message-ID: <20060914152720.F029B1006E@code0.codespeak.net> Author: mwh Date: Thu Sep 14 17:27:19 2006 New Revision: 32321 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py Log: fix a test. not entirely sure how come this wasn't constant folded away before... Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py Thu Sep 14 17:27:19 2006 @@ -180,7 +180,7 @@ def fn(): return s1.sub.x graph, t = get_graph(fn, []) - assert summary(graph) == {'getsubstruct': 1, 'getfield': 1} + assert summary(graph) == {'getinteriorfield': 1} constant_fold_graph(graph) # kill all references to 's1' @@ -188,7 +188,7 @@ del graph.func import gc; gc.collect() - assert summary(graph) == {'getfield': 1} + assert summary(graph) == {} check_graph(graph, [], 1234, t) From fijal at codespeak.net Thu Sep 14 17:31:05 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 14 Sep 2006 17:31:05 +0200 (CEST) Subject: [pypy-svn] r32322 - pypy/dist/pypy/annotation Message-ID: <20060914153105.F122F1006E@code0.codespeak.net> Author: fijal Date: Thu Sep 14 17:31:04 2006 New Revision: 32322 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: Ooops... Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Sep 14 17:31:04 2006 @@ -458,7 +458,6 @@ listdef = ListDef(self, s_ImpossibleValue) for e in x: listdef.generalize(self.annotation_from_example(e)) - self.listdefs[self.position_key] = listdef result = SomeList(listdef) elif tp is dict or tp is r_dict: dictdef = DictDef(self, From mwh at codespeak.net Thu Sep 14 17:38:16 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 17:38:16 +0200 (CEST) Subject: [pypy-svn] r32323 - in pypy/branch/kill-keepalives/pypy: rpython rpython/lltypesystem translator/backendopt/test Message-ID: <20060914153816.043DF1006E@code0.codespeak.net> Author: mwh Date: Thu Sep 14 17:38:14 2006 New Revision: 32323 Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py Log: oops, getinteriorfield shouldn't be always foldable Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/llinterp.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Thu Sep 14 17:38:14 2006 @@ -486,6 +486,17 @@ op_bare_setfield = op_setfield + def op_getinteriorfield(self, obj, *offsets): + checkptr(obj) + ob = obj + for o in offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[o] + assert not isinstance(ob, lltype._interior_ptr) + return ob + def op_setinteriorfield(self, obj, *fieldnamesval): prefields, finalfield, fieldvalue = fieldnamesval[:-2], fieldnamesval[-2], fieldnamesval[-1] for o in prefields: Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py Thu Sep 14 17:38:14 2006 @@ -303,7 +303,7 @@ 'getarrayitem': LLOp(sideeffects=False, canrun=True), 'getarraysize': LLOp(canfold=True), 'getsubstruct': LLOp(canfold=True), - 'getinteriorfield': LLOp(canfold=True), # XXX not sure about the foldability... + 'getinteriorfield': LLOp(sideeffects=False, canrun=True), 'getinteriorarraysize': LLOp(canfold=True), 'getarraysubstruct': LLOp(canfold=True), 'setfield': LLOp(), Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/opimpl.py Thu Sep 14 17:38:14 2006 @@ -126,17 +126,6 @@ lltype.ContainerType) return getattr(obj, field) -def op_getinteriorfield(obj, *offsets): - checkptr(obj) - ob = obj - for o in offsets: - if isinstance(o, str): - ob = getattr(ob, o) - else: - ob = ob[o] - assert not isinstance(ob, lltype._interior_ptr) - return ob - def op_getinteriorarraysize(obj, *offsets): checkptr(obj) ob = obj @@ -370,6 +359,21 @@ raise TypeError("cannot fold getfield on mutable struct") return getattr(p, name) +def op_getinteriorfield(obj, *offsets): + checkptr(obj) + ob = obj + T = lltype.typeOf(obj).TO + for o in offsets: + if not T._hints.get('immutable'): + raise TypeError("cannot fold getinteriorfield on mutable struct") + if isinstance(o, str): + ob = getattr(ob, o) + T = getattr(T, o) + else: + raise TypeError("cannot fold getfield on mutable struct") + assert not isinstance(ob, lltype._interior_ptr) + return ob + def op_getarrayitem(p, index): checkptr(p) if not lltype.typeOf(p).TO._hints.get('immutable'): Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py Thu Sep 14 17:38:14 2006 @@ -173,6 +173,7 @@ def test_keepalive_const_substruct(): + py.test.skip("do we want partial folding of getinteriorfield?") S2 = lltype.Struct('S2', ('x', lltype.Signed)) S1 = lltype.GcStruct('S1', ('sub', S2)) s1 = lltype.malloc(S1) @@ -188,7 +189,7 @@ del graph.func import gc; gc.collect() - assert summary(graph) == {} + assert summary(graph) == {'getfield':1} check_graph(graph, [], 1234, t) From mwh at codespeak.net Thu Sep 14 17:39:53 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 17:39:53 +0200 (CEST) Subject: [pypy-svn] r32324 - pypy/branch/kill-keepalives/pypy/translator/backendopt/test Message-ID: <20060914153953.D75561006E@code0.codespeak.net> Author: mwh Date: Thu Sep 14 17:39:52 2006 New Revision: 32324 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py Log: doh! Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_constfold.py Thu Sep 14 17:39:52 2006 @@ -5,6 +5,7 @@ from pypy.rpython import objectmodel from pypy.translator.backendopt.constfold import constant_fold_graph from pypy import conftest +import py def get_graph(fn, signature): t = TranslationContext() From mwh at codespeak.net Thu Sep 14 17:56:10 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 17:56:10 +0200 (CEST) Subject: [pypy-svn] r32325 - pypy/branch/kill-keepalives/pypy/translator/backendopt/test Message-ID: <20060914155610.B83201006E@code0.codespeak.net> Author: mwh Date: Thu Sep 14 17:56:08 2006 New Revision: 32325 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_escape.py Log: add something for --view to do Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_escape.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_escape.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_escape.py Thu Sep 14 17:56:08 2006 @@ -3,6 +3,7 @@ from pypy.translator.backendopt.support import find_backedges, find_loop_blocks from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.objectmodel import instantiate +from pypy import conftest def build_adi(function, types): t = TranslationContext() @@ -12,6 +13,8 @@ graph = graphof(t, function) adi.schedule_function(graph) adi.complete() + if conftest.option.view: + t.view() return t, adi, graph def check_malloc_removal(function, types, args, expected_result, must_remove=True): From arigo at codespeak.net Thu Sep 14 18:44:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Sep 2006 18:44:03 +0200 (CEST) Subject: [pypy-svn] r32329 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20060914164403.AD90810063@code0.codespeak.net> Author: arigo Date: Thu Sep 14 18:44:02 2006 New Revision: 32329 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py Log: Make codebuf_posix independent from module/mmap/. Systematically avoid using c_void_p for its broken return-value behavior. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf.py Thu Sep 14 18:44:02 2006 @@ -1,11 +1,13 @@ import os -from ctypes import * +from ctypes import POINTER, cast, c_char, c_void_p, CFUNCTYPE, c_int from ri386 import AbstractCodeBuilder modname = 'pypy.jit.codegen.i386.codebuf_' + os.name memhandler = __import__(modname, globals(), locals(), ['__doc__']) +PTR = memhandler.PTR + class CodeBlockOverflow(Exception): pass @@ -32,7 +34,7 @@ return baseaddr + self._pos def __del__(self): - memhandler.free(cast(self._data, c_void_p), self._size) + memhandler.free(cast(self._data, PTR), self._size) def execute(self, arg1, arg2): fnptr = cast(self._data, binaryfn) Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Thu Sep 14 18:44:02 2006 @@ -18,8 +18,8 @@ globals().update(ctypes_platform.configure(CConfig)) -LPVOID = ctypes.c_void_p - +# cannot use c_void_p as return value of functions :-( +LPVOID = ctypes.POINTER(ctypes.c_char) VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc VirtualAlloc.argtypes = [LPVOID, SIZE_T, DWORD, DWORD] Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py Thu Sep 14 18:44:02 2006 @@ -1,16 +1,45 @@ -import mmap -from pypy.module.mmap import interp_mmap -from ctypes import c_void_p +import pypy.rpython.rctypes.implementation # register rctypes types +from pypy.rpython.rctypes.tool import ctypes_platform +from pypy.rpython.rctypes.tool.libc import libc +from ctypes import POINTER, c_char, c_int -libcmmap = interp_mmap.libc.mmap -libcmunmap = interp_mmap.libc.munmap +class CConfig: + _includes_ = ("sys/types.h", "sys/mman.h") + size_t = ctypes_platform.SimpleType("size_t", c_int) + off_t = ctypes_platform.SimpleType("off_t", c_int) + + MAP_PRIVATE = ctypes_platform.DefinedConstantInteger("MAP_PRIVATE") + MAP_ANON = ctypes_platform.DefinedConstantInteger("MAP_ANON") + MAP_ANONYMOUS = ctypes_platform.DefinedConstantInteger("MAP_ANONYMOUS") + PROT_READ = ctypes_platform.DefinedConstantInteger("PROT_READ") + PROT_WRITE = ctypes_platform.DefinedConstantInteger("PROT_WRITE") + PROT_EXEC = ctypes_platform.DefinedConstantInteger("PROT_EXEC") + +globals().update(ctypes_platform.configure(CConfig)) +if MAP_ANONYMOUS is None: + MAP_ANONYMOUS = MAP_ANON + assert MAP_ANONYMOUS is not None +del MAP_ANON + +# ____________________________________________________________ + +PTR = POINTER(c_char) # cannot use c_void_p as return value of functions :-( + +mmap_ = libc.mmap +mmap_.argtypes = [PTR, size_t, c_int, c_int, c_int, off_t] +mmap_.restype = PTR +mmap_.includes = ("sys/mman.h",) +munmap_ = libc.munmap +munmap_.argtypes = [PTR, size_t] +munmap_.restype = c_int +munmap_.includes = ("sys/mman.h",) def alloc(map_size): - flags = mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS - prot = mmap.PROT_EXEC | mmap.PROT_READ | mmap.PROT_WRITE - res = libcmmap(c_void_p(), map_size, prot, flags, -1, 0) + flags = MAP_PRIVATE | MAP_ANONYMOUS + prot = PROT_EXEC | PROT_READ | PROT_WRITE + res = mmap_(PTR(), map_size, prot, flags, -1, 0) if not res: raise MemoryError return res -free = libcmunmap +free = munmap_ From mwh at codespeak.net Thu Sep 14 19:43:58 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Sep 2006 19:43:58 +0200 (CEST) Subject: [pypy-svn] r32334 - pypy/branch/kill-keepalives/pypy/rpython/lltypesystem Message-ID: <20060914174358.EAF0A1006C@code0.codespeak.net> Author: mwh Date: Thu Sep 14 19:43:57 2006 New Revision: 32334 Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py Log: fix slip found in the traditional way -- targetpypystandalone.py :/ Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/rdict.py Thu Sep 14 19:43:57 2006 @@ -452,9 +452,9 @@ key = entry.key # careful about destructor side effects: # keep key alive until entry.value has also # been zeroed (if it must be) - entry.key = lltype.nullptr(DICT.entries.OF.key.TO) + entry.key = lltype.nullptr(DICT.entries.TO.OF.key.TO) if DICT.must_clear_value: - entry.value = lltype.nullptr(DICT.entries.OF.value.TO) + entry.value = lltype.nullptr(DICT.entries.TO.OF.value.TO) num_entries = len(d.entries) if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4: ll_dict_resize(d) From arigo at codespeak.net Thu Sep 14 20:42:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Sep 2006 20:42:25 +0200 (CEST) Subject: [pypy-svn] r32335 - pypy/branch/malloc-cleanup Message-ID: <20060914184225.387D81006C@code0.codespeak.net> Author: arigo Date: Thu Sep 14 20:42:23 2006 New Revision: 32335 Added: pypy/branch/malloc-cleanup/ - copied from r32334, pypy/dist/ Log: While we're in branch-happy mode, here is one in which to sort out the situtation of the zoo of mallocs. From arigo at codespeak.net Fri Sep 15 10:24:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 10:24:54 +0200 (CEST) Subject: [pypy-svn] r32344 - pypy/dist/pypy/translator/goal Message-ID: <20060915082454.5D44B10071@code0.codespeak.net> Author: arigo Date: Fri Sep 15 10:24:52 2006 New Revision: 32344 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: 'svn info' output format has a new line in svn 1.4. Use the py lib's cleaner method to get at the current revision number. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Fri Sep 15 10:24:52 2006 @@ -113,7 +113,7 @@ os.chdir(homedir + '/projects/pypy-dist') try: - revision = os.popen('svn info 2>&1').readlines()[3].split()[1] + revision = '%d' % (py.path.svnwc('.').info().rev,) except: revision = 'unknown' basename = homedir + '/projects/pypy-dist/pypy/translator/goal/' + 'pypy-' + backend From mwh at codespeak.net Fri Sep 15 11:52:29 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 15 Sep 2006 11:52:29 +0200 (CEST) Subject: [pypy-svn] r32348 - in pypy/branch/kill-keepalives/pypy/translator/backendopt: . test Message-ID: <20060915095229.28C3910077@code0.codespeak.net> Author: mwh Date: Fri Sep 15 11:52:27 2006 New Revision: 32348 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Log: support for malloc removing structures with a special kind of destructor. Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Fri Sep 15 11:52:27 2006 @@ -3,6 +3,7 @@ from pypy.tool.algo.unionfind import UnionFind from pypy.rpython.lltypesystem import lltype from pypy.translator.simplify import remove_identical_vars +from pypy.translator.unsimplify import varoftype from pypy.translator.backendopt.support import log from pypy.translator.backendopt.constfold import constant_fold_graph @@ -211,12 +212,17 @@ else: return False - # must not remove mallocs of structures that have a RTTI with a destructor + # must not remove mallocs of structures that have a RTTI with a + # destructor, unless there's a hint that tells us what the + # destructor does. + + fields_to_raw_free = () try: destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr - if destr_ptr: + if destr_ptr and 'autofree_fields' not in STRUCT._hints: return False + fields_to_raw_free = STRUCT._hints['autofree_fields'] except (ValueError, AttributeError), e: pass @@ -422,16 +428,25 @@ assert block.exitswitch not in vars + var_exits = False for link in block.exits: newargs = [] for arg in link.args: if arg in vars: newargs += list_newvars() insert_keepalive = False # kept alive by the link + var_exits = True else: newargs.append(arg) link.args[:] = newargs + if not var_exits: + for field in fields_to_raw_free: + newops.append(SpaceOperation("flavored_free", + [Constant("raw", lltype.Void), + newvarsmap[key_for_field_access(STRUCT, field)]], + varoftype(lltype.Void))) + if insert_keepalive and last_removed_access is not None: keepalives = [] for v in list_newvars(): Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Fri Sep 15 11:52:27 2006 @@ -5,7 +5,7 @@ from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.translator import TranslationContext, graphof from pypy.translator import simplify -from pypy.objspace.flow.model import checkgraph, flatten, Block +from pypy.objspace.flow.model import checkgraph, flatten, Block, summary from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.lltypesystem import lltype from pypy.conftest import option @@ -45,6 +45,7 @@ callback(False) if must_be_removed: check_malloc_removed(graph) + return graph def test_fn1(): @@ -277,3 +278,21 @@ x.u2.b = 6 return x.u1.b * x.u2.a check(fn, [], [], Ellipsis) + +def test_simple_destructor(): + R = lltype.Struct("R", ("x", lltype.Signed)) + G = lltype.GcStruct("G", ("p", lltype.Ptr(R)), + hints={'autofree_fields':('p',)}) + def destr(g): + lltype.raw_free(g.p) + destrptr = lltype.functionptr(lltype.FuncType([lltype.Ptr(G)], lltype.Void), + "destr", + _callable=destr) + lltype.attachRuntimeTypeInfo(G, destrptr=destrptr) + def f(): + g = lltype.malloc(G) + g.p = lltype.malloc(R, flavor='raw') + g.p.x = 1 + return g.p.x + graph = check(f, [], [], 1) + assert 'flavored_free' in summary(graph) From mwh at codespeak.net Fri Sep 15 12:03:55 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 15 Sep 2006 12:03:55 +0200 (CEST) Subject: [pypy-svn] r32349 - pypy/branch/kill-keepalives/pypy/translator/backendopt Message-ID: <20060915100355.D0CC910079@code0.codespeak.net> Author: mwh Date: Fri Sep 15 12:03:53 2006 New Revision: 32349 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Log: remove some code duplication Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Fri Sep 15 12:03:53 2006 @@ -285,15 +285,17 @@ flatten(STRUCT) assert len(direct_fieldptr_key) <= 1 - def key_for_field_access(S, fldname): + def key_for_field_access(S, *fldnames): if isinstance(S, lltype.FixedSizeArray): + assert len(fldnames) == 1, "embedded FixedSizeArrays should be accessed by getinteriorfield" + fldname, = fldnames if not isinstance(fldname, str): # access by index fldname = 'item%d' % (fldname,) try: return direct_fieldptr_key[S, fldname] except KeyError: pass - return S, fldname + return (S,) + fldnames variables_by_block = {} for block, var in info.variables: @@ -320,10 +322,10 @@ for arg in op.args[1:]: # should be the first arg only assert arg not in vars if op.args and op.args[0] in vars: - if op.opname in ("getfield", "getarrayitem"): + if op.opname in ("getfield", "getarrayitem", "getinteriorfield"): S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = key_for_field_access(S, fldname) + fldnames = [a.value for a in op.args[1:]] + key = key_for_field_access(S, *fldnames) if key in accessed_substructs: c_name = Constant('data', lltype.Void) newop = SpaceOperation("getfield", @@ -335,23 +337,10 @@ op.result) newops.append(newop) last_removed_access = len(newops) - elif op.opname == "getinteriorfield": - S = op.args[0].concretetype.TO - key = tuple([S] + [a.value for a in op.args[1:]]) - newop = SpaceOperation("same_as", - [newvarsmap[key]], - op.result) - newops.append(newop) - last_removed_access = len(newops) - elif op.opname == "setinteriorfield": + elif op.opname in ("setfield", "setarrayitem", "setinteriorfield"): S = op.args[0].concretetype.TO - key = tuple([S] + [a.value for a in op.args[1:-1]]) - newvarsmap[key] = op.args[-1] - last_removed_access = len(newops) - elif op.opname in ("setfield", "setarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = key_for_field_access(S, fldname) + fldnames = [a.value for a in op.args[1:-1]] + key = key_for_field_access(S, *fldnames) assert key in newvarsmap if key in accessed_substructs: c_name = Constant('data', lltype.Void) @@ -360,7 +349,7 @@ op.result) newops.append(newop) else: - newvarsmap[key] = op.args[2] + newvarsmap[key] = op.args[-1] last_removed_access = len(newops) elif op.opname in ("same_as", "cast_pointer"): assert op.result not in vars From arigo at codespeak.net Fri Sep 15 12:44:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 12:44:07 +0200 (CEST) Subject: [pypy-svn] r32351 - in pypy/branch/kill-keepalives/pypy: annotation rpython rpython/lltypesystem rpython/memory rpython/rctypes Message-ID: <20060915104407.AC2D81006F@code0.codespeak.net> Author: arigo Date: Fri Sep 15 12:44:04 2006 New Revision: 32351 Modified: pypy/branch/kill-keepalives/pypy/annotation/builtin.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py pypy/branch/kill-keepalives/pypy/rpython/rbuiltin.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/astringbuf.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Log: Intermediate check-in: * a more complete llmemory.raw_memclear() * finally allow ll helpers to call the llmemory.raw_*() interface instead of the lladdress.raw_*() one * progress on rctypes in the direction of raw_malloc/raw_free of the C data, instead of keeping it inside the GcStruct boxes. Modified: pypy/branch/kill-keepalives/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/annotation/builtin.py (original) +++ pypy/branch/kill-keepalives/pypy/annotation/builtin.py Fri Sep 15 12:44:04 2006 @@ -556,6 +556,7 @@ # memory address from pypy.rpython.memory import lladdress +from pypy.rpython.lltypesystem import llmemory def raw_malloc(s_size): assert isinstance(s_size, SomeInteger) #XXX add noneg...? @@ -587,11 +588,15 @@ BUILTIN_ANALYZERS[lladdress.raw_memclear] = raw_memclear BUILTIN_ANALYZERS[lladdress.raw_memcopy] = raw_memcopy +BUILTIN_ANALYZERS[llmemory.raw_malloc] = raw_malloc +BUILTIN_ANALYZERS[llmemory.raw_malloc_usage] = raw_malloc_usage +BUILTIN_ANALYZERS[llmemory.raw_free] = raw_free +BUILTIN_ANALYZERS[llmemory.raw_memclear] = raw_memclear +BUILTIN_ANALYZERS[llmemory.raw_memcopy] = raw_memcopy + #_________________________________ # offsetof/sizeof -from pypy.rpython.lltypesystem import llmemory - def offsetof(TYPE, fldname): return SomeInteger() Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py Fri Sep 15 12:44:04 2006 @@ -21,7 +21,7 @@ return NotImplemented return CompositeOffset(self, other) - def raw_malloc(self, rest): + def raw_malloc(self, rest, zero=False): raise NotImplementedError("raw_malloc(%r, %r)" % (self, rest)) @@ -51,16 +51,16 @@ index = firstitemref.index + self.repeat return _arrayitemref(array, index) - def raw_malloc(self, rest): + def raw_malloc(self, rest, zero=False): assert not rest if (isinstance(self.TYPE, lltype.ContainerType) and self.TYPE._gckind == 'gc'): assert self.repeat == 1 - p = lltype.malloc(self.TYPE, flavor='raw') + p = lltype.malloc(self.TYPE, flavor='raw', zero=zero) return cast_ptr_to_adr(p) else: T = lltype.FixedSizeArray(self.TYPE, self.repeat) - p = lltype.malloc(T, flavor='raw') + p = lltype.malloc(T, flavor='raw', zero=zero) array_adr = cast_ptr_to_adr(p) return array_adr + ArrayItemsOffset(T) @@ -80,11 +80,13 @@ struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct) return _structfieldref(struct, self.fldname) - def raw_malloc(self, rest, parenttype=None): + def raw_malloc(self, rest, parenttype=None, zero=False): if self.fldname != self.TYPE._arrayfld: - return AddressOffset.raw_malloc(self, rest) # for the error msg + return AddressOffset.raw_malloc(self, rest, # for the error msg + zero=zero) assert rest - return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE) + return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE, + zero=zero) class CompositeOffset(AddressOffset): @@ -122,8 +124,8 @@ ref = item.ref(ref) return ref - def raw_malloc(self, rest): - return self.offsets[0].raw_malloc(self.offsets[1:] + rest) + def raw_malloc(self, rest, zero=False): + return self.offsets[0].raw_malloc(self.offsets[1:] + rest, zero=zero) class ArrayItemsOffset(AddressOffset): @@ -139,7 +141,7 @@ assert lltype.rawTypeOf(array).TO == self.TYPE return _arrayitemref(array, index=0) - def raw_malloc(self, rest, parenttype=None): + def raw_malloc(self, rest, parenttype=None, zero=False): if rest: assert len(rest) == 1 assert isinstance(rest[0], ItemOffset) @@ -149,7 +151,7 @@ count = 0 if self.TYPE._hints.get('isrpystring'): count -= 1 # because malloc() will give us the extra char for free - p = lltype.malloc(parenttype or self.TYPE, count, + p = lltype.malloc(parenttype or self.TYPE, count, zero=zero, immortal = self.TYPE._gckind == 'raw') return cast_ptr_to_adr(p) @@ -183,11 +185,11 @@ gcptr = self.gcheaderbuilder.object_from_header(header) return _obref(gcptr) - def raw_malloc(self, rest): + def raw_malloc(self, rest, zero=False): assert rest if isinstance(rest[0], GCHeaderAntiOffset): - return rest[1].raw_malloc(rest[2:]) # just for fun - gcobjadr = rest[0].raw_malloc(rest[1:]) + return rest[1].raw_malloc(rest[2:], zero=zero) # just for fun + gcobjadr = rest[0].raw_malloc(rest[1:], zero=zero) headerptr = self.gcheaderbuilder.new_header(gcobjadr.get()) return cast_ptr_to_adr(headerptr) @@ -207,10 +209,10 @@ headerptr = self.gcheaderbuilder.header_of_object(gcptr) return _obref(headerptr) - def raw_malloc(self, rest): + def raw_malloc(self, rest, zero=False): assert len(rest) >= 2 assert isinstance(rest[0], GCHeaderOffset) - return rest[1].raw_malloc(rest[2:]) + return rest[1].raw_malloc(rest[2:], zero=zero) class _arrayitemref(object): @@ -560,15 +562,11 @@ return size def raw_memclear(adr, size): - # hack hack hack - # stab stab stab - assert (adr.offset is None or - (isinstance(adr.offset, ArrayItemsOffset) - and isinstance(lltype.typeOf(adr.ob).TO, lltype.FixedSizeArray))) - TYPE = lltype.typeOf(adr.ob) - fresh = lltype.malloc(TYPE.TO, zero=True, flavor='raw') + if not isinstance(size, AddressOffset): + raise NotImplementedError(size) + fresh = size.raw_malloc([], zero=True) from pypy.rpython.rctypes.rmodel import reccopy - reccopy(fresh, adr.ob) + reccopy(fresh.get(), adr.get()) def raw_memcopy(source, dest, size): source = source.get() @@ -603,8 +601,9 @@ self.unitsize = unitsize self.n = n - def raw_malloc(self, rest): + def raw_malloc(self, rest, zero=False): assert not rest + assert not zero # for now return fakeaddress(_arena(self), ArenaItem(0)) def arena(TYPE, n): Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Fri Sep 15 12:44:04 2006 @@ -1018,6 +1018,7 @@ if ARRAY.OF != lltype.Void: info["ofstovar"] = ofs1 + llmemory.itemoffsetof(ARRAY, 0) else: + # XXX ? info["fixedsize"] = ofs1 + llmemory.sizeof(lltype.Signed) if ARRAY._hints.get('isrpystring'): info["fixedsize"] = llmemory.sizeof(TYPE, 1) @@ -1034,6 +1035,7 @@ info["varofstoptrs"] = self.offsets2table(offsets, ARRAY.OF) info["varitemsize"] = llmemory.sizeof(ARRAY.OF) else: + # XXX ? info["varofstoptrs"] = self.offsets2table((), lltype.Void) info["varitemsize"] = llmemory.sizeof(ARRAY.OF) return type_id Modified: pypy/branch/kill-keepalives/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rbuiltin.py Fri Sep 15 12:44:04 2006 @@ -577,6 +577,12 @@ BUILTIN_TYPER[lladdress.raw_memclear] = rtype_raw_memclear BUILTIN_TYPER[lladdress.raw_memcopy] = rtype_raw_memcopy +BUILTIN_TYPER[llmemory.raw_malloc] = rtype_raw_malloc +BUILTIN_TYPER[llmemory.raw_malloc_usage] = rtype_raw_malloc_usage +BUILTIN_TYPER[llmemory.raw_free] = rtype_raw_free +BUILTIN_TYPER[llmemory.raw_memclear] = rtype_raw_memclear +BUILTIN_TYPER[llmemory.raw_memcopy] = rtype_raw_memcopy + def rtype_offsetof(hop): TYPE, field = hop.inputargs(lltype.Void, lltype.Void) return hop.inputconst(lltype.Signed, Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/astringbuf.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/astringbuf.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/astringbuf.py Fri Sep 15 12:44:04 2006 @@ -34,11 +34,7 @@ [v_length] = hop.inputargs(lltype.Signed) r_stringbuf = hop.r_result hop.exception_cannot_occur() - return hop.genop("zero_malloc_varsize", [ - hop.inputconst(lltype.Void, r_stringbuf.lowleveltype.TO), - v_length, - ], resulttype=r_stringbuf.lowleveltype, - ) + return r_stringbuf.allocate_instance_varsize(hop.llops, v_length) class ObjEntry(CTypesObjEntry): Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py Fri Sep 15 12:44:04 2006 @@ -1,5 +1,5 @@ from pypy.rpython.rmodel import inputconst -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.rstr import AbstractStringRepr from pypy.rpython.lltypesystem.rstr import string_repr from pypy.rpython.rctypes.rmodel import CTypesValueRepr, C_ZERO @@ -12,6 +12,8 @@ class CCharPRepr(CTypesValueRepr): + autofree_fields = ("keepalive",) + def return_c_data(self, llops, v_c_data): """Read out the RPython string from a raw C pointer. Used when the data is returned from an operation or C function call. @@ -25,8 +27,8 @@ return llops.gendirectcall(ll_charp2str, v_value) def get_content_keepalive_type(self): - "An extra keepalive used for the RPython string." - return string_repr.lowleveltype + "An extra keepalive used for the raw copy the RPython string." + return lltype.Ptr(CHARSCOPY) # raw_malloc'ed, automatically raw_free'd def getstring(self, llops, v_box): return llops.gendirectcall(ll_getstring, v_box) @@ -111,9 +113,6 @@ i += 1 return i -def ll_str2charp(s): - return lltype.direct_arrayitems(s.chars) - def ll_charp2str(p): if not p: return lltype.nullptr(string_repr.lowleveltype.TO) @@ -127,14 +126,7 @@ def ll_getstring(box): p = box.c_data[0] if p: - if box.keepalive and ll_str2charp(box.keepalive) == p: - maxlen = len(box.keepalive.chars) - length = ll_strnlen(p, maxlen) - if length == maxlen: - # no embedded zero in the string - return box.keepalive - else: - length = ll_strlen(p) + length = ll_strlen(p) newstr = lltype.malloc(string_repr.lowleveltype.TO, length) newstr.hash = 0 for i in range(length): @@ -144,8 +136,24 @@ return lltype.nullptr(string_repr.lowleveltype.TO) def ll_setstring(box, string): - if string: - box.c_data[0] = ll_str2charp(string) - else: - box.c_data[0] = lltype.nullptr(CCHARP.TO) - box.keepalive = string + # XXX the copying of the string is often not needed, but it is + # very hard to avoid in the general case of a moving GC that can + # move 'string' around unpredictably. + n = len(string.chars) + buffer = llmemory.raw_malloc(NULL_HEADER + SIZEOF_CHAR * (n+1)) + charscopy = llmemory.cast_adr_to_ptr(buffer, PCHARSCOPY) + for i in range(n): + charscopy[i] = string.chars[i] + charscopy[n] = '\x00' + # store a 'char *' pointer in the box.c_data + box.c_data[0] = lltype.direct_arrayitems(charscopy) + # keep the ownership of the buffer in the box.keepalive field + prev = box.keepalive + box.keepalive = charscopy + if prev: + llmemory.raw_free(llmemory.cast_ptr_to_adr(prev)) + +CHARSCOPY = lltype.Array(lltype.Char, hints={'nolength': True}) +PCHARSCOPY = lltype.Ptr(CHARSCOPY) +NULL_HEADER = llmemory.itemoffsetof(CHARSCOPY) +SIZEOF_CHAR = llmemory.sizeof(lltype.Char) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Fri Sep 15 12:44:04 2006 @@ -29,6 +29,8 @@ # * 'r_memoryowner.lowleveltype' is the lowleveltype of the repr for the # same ctype but for ownsmemory=True. + autofree_fields = () + def __init__(self, rtyper, s_ctypesobject, ll_type): # s_ctypesobject: the annotation to represent # ll_type: the low-level type representing the raw @@ -42,33 +44,58 @@ self.c_data_type = self.get_c_data_type(ll_type) - fields = [] + fields = [("c_data", lltype.Ptr(self.c_data_type))] content_keepalive_type = self.get_content_keepalive_type() if content_keepalive_type: fields.append(( "keepalive", content_keepalive_type )) if self.ownsmemory: + self.autofree_fields = ("c_data",) + self.__class__.autofree_fields self.r_memoryowner = self - fields.append(( "c_data", self.c_data_type )) else: s_memoryowner = SomeCTypesObject(ctype, ownsmemory=True) self.r_memoryowner = rtyper.getrepr(s_memoryowner) - fields += [ - ( "c_data_owner_keepalive", self.r_memoryowner.lowleveltype ), - ( "c_data", lltype.Ptr(self.c_data_type) ), - ] + fields.append( + ( "c_data_owner_keepalive", self.r_memoryowner.lowleveltype )) + + keywords = {'hints': {'autofree_fields': self.autofree_fields}} self.lowleveltype = lltype.Ptr( lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,), - *fields + *fields, + **keywords ) ) + if self.autofree_fields: + lltype.attachRuntimeTypeInfo(self.lowleveltype.TO) self.const_cache = {} # store generated const values+original value + def _setup_repr_final(self): + if self.autofree_fields: + # XXX should be done by the gctransform from the GcStruct hint + from pypy.annotation import model as annmodel + from pypy.rpython.unroll import unrolling_iterable + autofree_fields = unrolling_iterable(self.autofree_fields) + + def ll_rctypes_free(box): + for fieldname in autofree_fields: + p = getattr(box, fieldname) + if p: + llmemory.raw_free(llmemory.cast_ptr_to_adr(p)) + + args_s = [annmodel.SomePtr(self.lowleveltype)] + graph = self.rtyper.annotate_helper(ll_rctypes_free, args_s) + destrptr = self.rtyper.getcallable(graph) + lltype.attachRuntimeTypeInfo(self.lowleveltype.TO, + destrptr = destrptr) + def get_content_keepalive_type(self): """Return the type of the extra keepalive field used for the content of this object.""" return None + def get_extra_autofree_fields(self): + return [] + def ctypecheck(self, value): return isinstance(value, self.ctype) @@ -86,28 +113,29 @@ return self.const_cache[key][0] except KeyError: self.setup() - p = lltype.malloc(self.r_memoryowner.lowleveltype.TO, zero=True) + p = lltype.malloc(self.r_memoryowner.lowleveltype.TO, + immortal = True) + p.c_data = lltype.malloc(self.r_memoryowner.c_data_type, + immortal = True, + zero = True) self.initialize_const(p, value) if self.ownsmemory: result = p else: # we must return a non-memory-owning box that keeps the # memory-owning box alive - result = lltype.malloc(self.lowleveltype.TO, zero=True) + result = lltype.malloc(self.lowleveltype.TO, + immortal = True, + zero = True) result.c_data = p.c_data # initialize c_data pointer result.c_data_owner_keepalive = p self.const_cache[key] = result, keepalive return result def get_c_data(self, llops, v_box): - if self.ownsmemory: - inputargs = [v_box, inputconst(lltype.Void, "c_data")] - return llops.genop('getsubstruct', inputargs, - lltype.Ptr(self.c_data_type) ) - else: - inputargs = [v_box, inputconst(lltype.Void, "c_data")] - return llops.genop('getfield', inputargs, - lltype.Ptr(self.c_data_type) ) + inputargs = [v_box, inputconst(lltype.Void, "c_data")] + return llops.genop('getfield', inputargs, + lltype.Ptr(self.c_data_type)) def get_c_data_owner(self, llops, v_box): if self.ownsmemory: @@ -120,18 +148,55 @@ def allocate_instance(self, llops): TYPE = self.lowleveltype.TO + c1 = inputconst(lltype.Void, TYPE) + v_box = llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype) + # XXX don't use zero_malloc, but just make sure there is a NULL + # in the autofreed field(s) + + TYPE = self.c_data_type if TYPE._is_varsize(): raise TyperError("allocating array with unknown length") - c1 = inputconst(lltype.Void, TYPE) - return llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype) + if self.ownsmemory: + # XXX use zero=True instead, and malloc instead of raw_malloc? + c_size = inputconst(lltype.Signed, llmemory.sizeof(TYPE)) + v_rawaddr = llops.genop("raw_malloc", [c_size], + resulttype=llmemory.Address) + llops.genop("raw_memclear", [v_rawaddr, c_size]) + v_rawdata = llops.genop("cast_adr_to_ptr", [v_rawaddr], + resulttype=lltype.Ptr(TYPE)) + c_datafieldname = inputconst(lltype.Void, "c_data") + llops.genop("setfield", [v_box, c_datafieldname, v_rawdata]) + return v_box def allocate_instance_varsize(self, llops, v_length): TYPE = self.lowleveltype.TO - if not TYPE._is_varsize(): - raise TyperError("allocating non-array with a specified length") c1 = inputconst(lltype.Void, TYPE) - return llops.genop("zero_malloc_varsize", [c1, v_length], - resulttype=self.lowleveltype) + v_box = llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype) + # XXX don't use zero_malloc, but just make sure there is a NULL + # in the autofreed field(s) + + TYPE = self.c_data_type + if not TYPE._is_varsize(): + raise TyperError("allocating non-array with specified length") + if self.ownsmemory: + # XXX use zero=True instead, and malloc instead of raw_malloc? + assert isinstance(TYPE, lltype.Array) + c_fixedsize = inputconst(lltype.Signed, llmemory.sizeof(TYPE, 0)) + c_itemsize = inputconst(lltype.Signed, llmemory.sizeof(TYPE.OF)) + v_varsize = llops.genop("int_mul", [c_itemsize, v_length], + resulttype=lltype.Signed) + v_size = llops.genop("int_add", [c_fixedsize, v_varsize], + resulttype=lltype.Signed) + v_rawaddr = llops.genop("raw_malloc", [v_size], + resulttype=llmemory.Address) + llops.genop("raw_memclear", [v_rawaddr, v_size]) + v_rawdata = llops.genop("cast_adr_to_ptr", [v_rawaddr], + resulttype=lltype.Ptr(TYPE)) + c_datafieldname = inputconst(lltype.Void, "c_data") + llops.genop("setfield", [v_box, c_datafieldname, v_rawdata]) + else: + raise TyperError("allocate_instance_varsize on an alias box") + return v_box def allocate_instance_ref(self, llops, v_c_data, v_c_data_owner=None): """Only if self.ownsmemory is false. This allocates a new instance From cfbolz at codespeak.net Fri Sep 15 14:09:46 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 15 Sep 2006 14:09:46 +0200 (CEST) Subject: [pypy-svn] r32353 - pypy/extradoc/talk/23c3 Message-ID: <20060915120946.51FAE1006E@code0.codespeak.net> Author: cfbolz Date: Fri Sep 15 14:09:45 2006 New Revision: 32353 Added: pypy/extradoc/talk/23c3/ pypy/extradoc/talk/23c3/speaker-arminrigo.txt - copied, changed from r32244, pypy/extradoc/talk/22c3/speaker-arminrigo.txt pypy/extradoc/talk/23c3/speaker-carlfriedrichbolz.txt - copied, changed from r32244, pypy/extradoc/talk/22c3/speaker-carlfriedrichbolz.txt pypy/extradoc/talk/23c3/speaker-holgerkrekel.txt - copied, changed from r32244, pypy/extradoc/talk/22c3/speaker-holgerkrekel.txt pypy/extradoc/talk/23c3/talk-pypy-dev.txt Log: intermediate checkin for the 23c3 talk proposal. Added: pypy/extradoc/talk/23c3/talk-pypy-dev.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/23c3/talk-pypy-dev.txt Fri Sep 15 14:09:45 2006 @@ -0,0 +1,51 @@ +Reference/Call For Papers: http://www.ccc.de/congress/2006/cfp.html +DEADLINE: 30th September 2005 (friday) + +Title: The PyPy fireworks + +Subtitle: ??? + + +Section: Hacking + +Talkers: Holger Krekel, Carl Friedrich Bolz, Armin Rigo + +Abstract (max 250 letters): + + This talk describes cool and novel language features of the PyPy project (a + next generation Python interpreter) which are made possible by its flexible + architecture. The talk focuses mostly on showcasing interesting and useful + features together with example usages and less about their implementation. + +Description (250-500 words): + + PyPy is a reimplementation of Python written in Python itself, flexible and + easy to experiment with. Due to its flexibility it is easy to add language + features that are sometimes hard to implement in more traditional VM + implementations. We have implemented a number of such features, some of them + greatly enhancing the expressivity and flexibility of the language. + + XXX add more stuff + + Development of PyPy is partly funded by the European Union + during the 6th Research Framework programme. + +Statement: We intend to submit a paper (PDF) for the 23C3 proceedings. XXX do we? +Statement: We intend to submit the slides. + +Duration of your talk: 45 minutes + questions + +Language of your talk: english + +Links to background information on the talk: http://codespeak.net/pypy + +Target Group: Advanced Users, Pros + +Resources you need for your talk: digital projector, internet + +Related talks at 23C3 you know of: None + +A lecture logo, square format, min. 128x128 pixels (optional): + http://codespeak.net/pypy/img/py-web1.png + (please scale it down a bit :-) + From arigo at codespeak.net Fri Sep 15 14:17:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 14:17:41 +0200 (CEST) Subject: [pypy-svn] r32354 - pypy/branch/kill-keepalives/pypy/translator/c Message-ID: <20060915121741.3FC7F10074@code0.codespeak.net> Author: arigo Date: Fri Sep 15 14:17:38 2006 New Revision: 32354 Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py pypy/branch/kill-keepalives/pypy/translator/c/node.py Log: Fix funcgen for the corner case of getinteriorfield when the top-level container is a FixedSizeArray. Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Fri Sep 15 14:17:38 2006 @@ -476,18 +476,25 @@ def interior_expr(self, args, rettype=False): TYPE = args[0].concretetype.TO - expr = '(*(' + self.expr(args[0]) + '))' - for arg in args[1:]: + expr = self.expr(args[0]) + for i, arg in enumerate(args[1:]): defnode = self.db.gettypedefnode(TYPE) if arg.concretetype is Void: fieldname = arg.value - expr = defnode.access_expr(expr, fieldname) - TYPE = getattr(TYPE, fieldname) + if i == 0: + expr = defnode.ptr_access_expr(expr, fieldname) + else: + expr = defnode.access_expr(expr, fieldname) + if isinstance(TYPE, lltype.FixedSizeArray): + TYPE = TYPE.OF + else: + TYPE = getattr(TYPE, fieldname) else: - if not isinstance(TYPE, FixedSizeArray): - expr = '(%s).items[%s]'%(expr, self.expr(arg)) + indexexpr = self.expr(arg) + if i == 0: + expr = defnode.ptr_access_expr_varindex(expr, indexexpr) else: - expr = '(%s)[%s]'%(expr, self.expr(arg)) + expr = defnode.access_expr_varindex(expr, indexexpr) TYPE = TYPE.OF if rettype: return expr, TYPE Modified: pypy/branch/kill-keepalives/pypy/translator/c/node.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/node.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/node.py Fri Sep 15 14:17:38 2006 @@ -237,10 +237,13 @@ return 'struct %s @' % self.name def access_expr(self, baseexpr, index): - return '%s.items[%d]' % (baseexpr, index) + return '%s.items[%s]' % (baseexpr, index) def ptr_access_expr(self, baseexpr, index): - return '%s->items[%d]' % (baseexpr, index) + return '%s->items[%s]' % (baseexpr, index) + + access_expr_varindex = access_expr + ptr_access_expr_varindex = ptr_access_expr def definition(self): gcpolicy = self.db.gcpolicy @@ -318,13 +321,19 @@ return self.itemtypename.replace('@', '*@') def access_expr(self, baseexpr, index): - if not isinstance(index, int): - assert index.startswith('item') - index = int(index[4:]) + if isinstance(index, int): + return self.access_expr_varindex(baseexpr, str(index)) + assert index.startswith('item') + index = int(index[4:]) return '%s[%d]' % (baseexpr, index) ptr_access_expr = access_expr + def access_expr_varindex(self, baseexpr, indexexpr): + return '%s[%s]' % (baseexpr, indexexpr) + + ptr_access_expr_varindex = access_expr_varindex + def definition(self): return [] # no declaration is needed From arigo at codespeak.net Fri Sep 15 14:18:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 14:18:23 +0200 (CEST) Subject: [pypy-svn] r32355 - pypy/branch/kill-keepalives/pypy/rpython/rctypes Message-ID: <20060915121823.8777010077@code0.codespeak.net> Author: arigo Date: Fri Sep 15 14:18:21 2006 New Revision: 32355 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Log: More rctypes progress: a proper destructor, genreccopy() fixed and improved, ... Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py Fri Sep 15 14:18:21 2006 @@ -105,11 +105,7 @@ v_c_array = self.get_c_data(llops, v_array) genreccopy_arrayitem(llops, v_newvalue, v_c_array, v_index) # copy the keepalive information too - v_keepalive_array = self.getkeepalive(llops, v_array) - if v_keepalive_array is not None: - v_newkeepalive = self.r_item.getkeepalive(llops, v_item) - genreccopy_arrayitem(llops, v_newkeepalive, - v_keepalive_array, v_index) + self.r_item.copykeepalive(llops, v_item, v_array, (v_index,)) def initializeitems(self, llops, v_array, items_v): for i, v_item in enumerate(items_v): Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Fri Sep 15 14:18:21 2006 @@ -83,10 +83,14 @@ llmemory.raw_free(llmemory.cast_ptr_to_adr(p)) args_s = [annmodel.SomePtr(self.lowleveltype)] + graph = self.rtyper.annotate_helper(ll_rctypes_query, args_s) + queryptr = self.rtyper.getcallable(graph) + + args_s = [annmodel.SomePtr(self.lowleveltype)] graph = self.rtyper.annotate_helper(ll_rctypes_free, args_s) destrptr = self.rtyper.getcallable(graph) lltype.attachRuntimeTypeInfo(self.lowleveltype.TO, - destrptr = destrptr) + queryptr, destrptr) def get_content_keepalive_type(self): """Return the type of the extra keepalive field used for the content @@ -224,20 +228,19 @@ # XXX add v_c_data_owner return self.allocate_instance_ref(llops, v_c_data) - def getkeepalive(self, llops, v_box): + def copykeepalive(self, llops, v_box, v_destbox, destsuboffset=()): + # copy the 'keepalive' data over, unless it's an autofree + assert v_box.concretetype == self.lowleveltype try: TYPE = self.lowleveltype.TO.keepalive except AttributeError: - return None + pass else: - if isinstance(TYPE, lltype.ContainerType): - TYPE = lltype.Ptr(TYPE) - opname = 'getsubstruct' - else: - opname = 'getfield' - c_name = inputconst(lltype.Void, 'keepalive') - return llops.genop(opname, [v_box, c_name], - resulttype = TYPE) + if 'keepalive' not in self.autofree_fields: + c_keepalive = inputconst(lltype.Void, 'keepalive') + genreccopy_rel(llops, TYPE, + v_box, (c_keepalive,), + v_destbox, (c_keepalive,) + destsuboffset) class __extend__(pairtype(CTypesRepr, CTypesRepr)): @@ -249,11 +252,9 @@ r_from.ownsmemory and not r_to.ownsmemory): v_c_data = r_from.get_c_data(llops, v) v_result = r_to.allocate_instance_ref(llops, v_c_data, v) - # copy of the 'keepalive' field over - v_keepalive = r_from.getkeepalive(llops, v) - if v_keepalive is not None: - genreccopy_structfield(llops, v_keepalive, - v_result, 'keepalive') + # copy the 'keepalive' information + c_keepalive = inputconst(lltype.Void, 'keepalive') + r_from.copykeepalive(llops, v, v_result) return v_result else: return NotImplemented @@ -313,30 +314,27 @@ def rtype_is_true(self, hop): [v_box] = hop.inputargs(self) v_value = self.getvalue(hop.llops, v_box) - if v_value.concretetype == llmemory.Address: - llfn = ll_address_is_true - else: - llfn = ll_is_true - return hop.gendirectcall(llfn, v_value) + return hop.gendirectcall(ll_is_true, v_value) # ____________________________________________________________ def ll_is_true(x): return bool(x) -def ll_address_is_true(x): - return x != llmemory.NULL - C_ZERO = inputconst(lltype.Signed, 0) +def ll_rctypes_query(p): + S = lltype.typeOf(p).TO + return lltype.getRuntimeTypeInfo(S) + def reccopy(source, dest): # copy recursively a structure or array onto another. T = lltype.rawTypeOf(source).TO assert T == lltype.rawTypeOf(dest).TO if isinstance(T, (lltype.Array, lltype.FixedSizeArray)): - assert len(source) == len(dest) + assert source._obj.getlength() == dest._obj.getlength() ITEMTYPE = T.OF - for i in range(len(source)): + for i in range(source._obj.getlength()): if isinstance(ITEMTYPE, lltype.ContainerType): subsrc = source[i] subdst = dest[i] @@ -366,67 +364,86 @@ else: reccopy(source, destarray[destindex]) -def genreccopy(llops, v_source, v_dest): - # helper to generate the llops that copy recursively a structure - # or array onto another. 'v_source' and 'v_dest' can also be pairs - # (v, i) to mean the ith item of the array that v points to. - T = v_source.concretetype.TO - assert T == v_dest.concretetype.TO +def enum_interior_offsets(T, prefix=()): + # generate all (offsets-tuple, FIELD_TYPE) for all interior fields + # in TYPE and in substructs of TYPE. Not for arrays so far. + + if isinstance(T, lltype.ContainerType): + if isinstance(T, lltype.FixedSizeArray): + # XXX don't do that if the length is large + ITEMTYPE = T.OF + for i in range(T.length): + c_i = inputconst(lltype.Signed, i) + offsets = prefix + (c_i,) + for access in enum_interior_offsets(ITEMTYPE, offsets): + yield access + + elif isinstance(T, lltype.Array): + raise NotImplementedError("XXX genreccopy() for arrays") + + elif isinstance(T, lltype.Struct): + for name in T._names: + FIELDTYPE = getattr(T, name) + cname = inputconst(lltype.Void, name) + offsets = prefix + (cname,) + for access in enum_interior_offsets(FIELDTYPE, offsets): + yield access - if isinstance(T, lltype.FixedSizeArray): - # XXX don't do that if the length is large - ITEMTYPE = T.OF - for i in range(T.length): - c_i = inputconst(lltype.Signed, i) - if isinstance(ITEMTYPE, lltype.ContainerType): - RESTYPE = lltype.Ptr(ITEMTYPE) - v_subsrc = llops.genop('getarraysubstruct', [v_source, c_i], - resulttype = RESTYPE) - v_subdst = llops.genop('getarraysubstruct', [v_dest, c_i], - resulttype = RESTYPE) - genreccopy(llops, v_subsrc, v_subdst) - else: - v_value = llops.genop('getarrayitem', [v_source, c_i], - resulttype = ITEMTYPE) - llops.genop('setarrayitem', [v_dest, c_i, v_value]) + else: + raise TypeError(T) - elif isinstance(T, lltype.Array): - raise NotImplementedError("XXX genreccopy() for arrays") + else: + yield prefix, T - elif isinstance(T, lltype.Struct): - for name in T._names: - FIELDTYPE = getattr(T, name) - cname = inputconst(lltype.Void, name) - if isinstance(FIELDTYPE, lltype.ContainerType): - RESTYPE = lltype.Ptr(FIELDTYPE) - v_subsrc = llops.genop('getsubstruct', [v_source, cname], - resulttype = RESTYPE) - v_subdst = llops.genop('getsubstruct', [v_dest, cname], - resulttype = RESTYPE) - genreccopy(llops, v_subsrc, v_subdst) - else: - v_value = llops.genop('getfield', [v_source, cname], - resulttype = FIELDTYPE) - llops.genop('setfield', [v_dest, cname, v_value]) - else: - raise TypeError(T) +def genreccopy_rel(llops, TYPE, v_source, sourceoffsets, v_dest, destoffsets): + # helper to generate the llops that copy recursively a structure + # or array onto another. The copy starts at the given tuple-of-offsets + # prefixes, e.g. (Constant(5),) to mean the 5th sub-element of a + # fixed-size array. This function doesn't work for general arrays yet. + # It works with primitive types too, as long as destoffsets != (). + + for offsets, FIELDTYPE in enum_interior_offsets(TYPE): + if sourceoffsets or offsets: + args = [v_source] + args.extend(sourceoffsets) + args.extend(offsets) + v_value = llops.genop('getinteriorfield', args, + resulttype=FIELDTYPE) + else: + v_value = v_source + if destoffsets or offsets: + args = [v_dest] + args.extend(destoffsets) + args.extend(offsets) + args.append(v_value) + llops.genop('setinteriorfield', args) + else: + assert TYPE == v_dest.concretetype + raise TypeError("cannot copy into a v_dest of type %r" % (TYPE,)) + +def genreccopy(llops, v_source, v_dest): + TYPE = v_source.concretetype.TO + assert TYPE == v_dest.concretetype.TO + genreccopy_rel(llops, TYPE, v_source, (), v_dest, ()) def genreccopy_arrayitem(llops, v_source, v_destarray, v_destindex): ITEMTYPE = v_destarray.concretetype.TO.OF if isinstance(ITEMTYPE, lltype.ContainerType): - v_dest = llops.genop('getarraysubstruct', [v_destarray, v_destindex], - resulttype = lltype.Ptr(ITEMTYPE)) - genreccopy(llops, v_source, v_dest) + # copy into the array's substructure + assert ITEMTYPE == v_source.concretetype.TO else: - llops.genop('setarrayitem', [v_destarray, v_destindex, v_source]) + # copy a primitive or pointer value into the array item + assert ITEMTYPE == v_source.concretetype + genreccopy_rel(llops, ITEMTYPE, v_source, (), v_destarray, (v_destindex,)) def genreccopy_structfield(llops, v_source, v_deststruct, fieldname): c_name = inputconst(lltype.Void, fieldname) FIELDTYPE = getattr(v_deststruct.concretetype.TO, fieldname) if isinstance(FIELDTYPE, lltype.ContainerType): - v_dest = llops.genop('getsubstruct', [v_deststruct, c_name], - resulttype = lltype.Ptr(FIELDTYPE)) - genreccopy(llops, v_source, v_dest) + # copy into the substructure + assert FIELDTYPE == v_source.concretetype.TO else: - llops.genop('setfield', [v_deststruct, c_name, v_source]) + # copy a primitive or pointer value into the struct field + assert FIELDTYPE == v_source.concretetype + genreccopy_rel(llops, FIELDTYPE, v_source, (), v_deststruct, (c_name,)) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Fri Sep 15 14:18:21 2006 @@ -117,11 +117,8 @@ v_c_struct = self.get_c_data(llops, v_struct) genreccopy_structfield(llops, v_newvalue, v_c_struct, cmangle(name)) # copy the keepalive information too - v_newkeepalive = r_field.getkeepalive(llops, v_item) - if v_newkeepalive is not None: - v_keepalive_struct = self.getkeepalive(llops, v_struct) - genreccopy_structfield(llops, v_newkeepalive, - v_keepalive_struct, cmangle(name)) + c_name = inputconst(lltype.Void, cmangle(name)) + r_field.copykeepalive(llops, v_item, v_struct, (c_name,)) def cmangle(name): # obscure: names starting with '_' are not allowed in From fijal at codespeak.net Fri Sep 15 14:24:52 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 15 Sep 2006 14:24:52 +0200 (CEST) Subject: [pypy-svn] r32359 - pypy/dist/pypy/translator/js/test Message-ID: <20060915122452.771DB10074@code0.codespeak.net> Author: fijal Date: Fri Sep 15 14:24:51 2006 New Revision: 32359 Modified: pypy/dist/pypy/translator/js/test/test_bltn.py Log: Skip failing test (will cope later with that) Modified: pypy/dist/pypy/translator/js/test/test_bltn.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_bltn.py (original) +++ pypy/dist/pypy/translator/js/test/test_bltn.py Fri Sep 15 14:24:51 2006 @@ -52,6 +52,7 @@ assert check_source_contains(fn, "\.some_callback = callback") def test_get_elements(): + py.test.skip('"Should be working" - will investigate later') from pypy.translator.js.modules import _dom as dom def getaa(tname): From arigo at codespeak.net Fri Sep 15 15:06:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 15:06:06 +0200 (CEST) Subject: [pypy-svn] r32361 - pypy/branch/kill-keepalives/pypy/rpython/memory Message-ID: <20060915130606.4B64310071@code0.codespeak.net> Author: arigo Date: Fri Sep 15 15:06:04 2006 New Revision: 32361 Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Log: Reintroduced the hack removed in rev 31714, and fixed it with yet more hacks :-( The problem is that we cannot call annotate_helper while annotating, so we have to postpone such calls to after finish_annotate(). But such calls require another pass at finish_annotate()... So it's a fixpoint process again. Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Fri Sep 15 15:06:04 2006 @@ -291,7 +291,15 @@ def finish_helpers(self): if self.translator is not None: - self.mixlevelannotator.finish_annotate() + while 1: + self.do_before_rtyping = [] + self.mixlevelannotator.finish_annotate() + # anything more to annotate? + if not self.do_before_rtyping: + break # no, done + for fn, args in self.do_before_rtyping: + fn(*args) + del self.do_before_rtyping self.finished_helpers = True if self.translator is not None: self.mixlevelannotator.finish_rtype() @@ -324,14 +332,28 @@ Their calls are replaced by a simple operation of the GC transformer, e.g. ll_pop_alive. """ - def __init__(self, transformer_method): + def __init__(self, transformer, transformer_method, see_type=None): + self.transformer = transformer self.transformer_method = transformer_method + self.see_type = see_type class LLTransformerOpEntry(ExtRegistryEntry): "Annotation and specialization of LLTransformerOp() instances." _type_ = LLTransformerOp def compute_result_annotation(self, s_arg): + op = self.instance # the LLTransformerOp instance + if op.see_type is not None: + assert isinstance(s_arg, annmodel.SomePtr) + PTRTYPE = s_arg.ll_ptrtype + if PTRTYPE.TO is not lltype.PyObject: + # look for and annotate a dynamic deallocator if necessary; + # doing so implicitly in specialize_call() is too late. + # Note that we cannot do it *right now* because if + # annotation is required, we are already annotating + # ---> boom + delayed = (op.see_type, (PTRTYPE.TO,)) + op.transformer.do_before_rtyping.append(delayed) return annmodel.s_None def specialize_call(self, hop): @@ -562,7 +584,8 @@ body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) src = ('def ll_deallocator(addr):\n v = cast_adr_to_ptr(addr, PTR_TYPE)\n' + body + '\n llop.gc_free(lltype.Void, addr)\n') - d = {'pop_alive': LLTransformerOp(self.pop_alive), + d = {'pop_alive': LLTransformerOp(self, self.pop_alive, + self.dynamic_deallocation_funcptr_for_type), 'llop': llop, 'lltype': lltype, 'destrptr': destrptr, @@ -691,7 +714,7 @@ raise Exception("can't mix PyObjects and __del__ with Boehm") static_body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) - d = {'pop_alive': LLTransformerOp(self.pop_alive), + d = {'pop_alive': LLTransformerOp(self, self.pop_alive), 'PTR_TYPE':lltype.Ptr(TYPE), 'cast_adr_to_ptr': llmemory.cast_adr_to_ptr} src = ("def ll_finalizer(addr):\n" From arigo at codespeak.net Fri Sep 15 15:06:15 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 15:06:15 +0200 (CEST) Subject: [pypy-svn] r32362 - pypy/branch/kill-keepalives/pypy/translator/c Message-ID: <20060915130615.119FE10075@code0.codespeak.net> Author: arigo Date: Fri Sep 15 15:06:13 2006 New Revision: 32362 Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Log: Typo. Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Fri Sep 15 15:06:13 2006 @@ -485,7 +485,7 @@ expr = defnode.ptr_access_expr(expr, fieldname) else: expr = defnode.access_expr(expr, fieldname) - if isinstance(TYPE, lltype.FixedSizeArray): + if isinstance(TYPE, FixedSizeArray): TYPE = TYPE.OF else: TYPE = getattr(TYPE, fieldname) From arigo at codespeak.net Fri Sep 15 15:20:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 15:20:44 +0200 (CEST) Subject: [pypy-svn] r32363 - in pypy/branch/kill-keepalives/pypy/translator/c: . test Message-ID: <20060915132044.6BFA910071@code0.codespeak.net> Author: arigo Date: Fri Sep 15 15:20:41 2006 New Revision: 32363 Modified: pypy/branch/kill-keepalives/pypy/translator/c/node.py pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Log: Added missing support for prebuilt arrays that have the nolength hint. Modified: pypy/branch/kill-keepalives/pypy/translator/c/node.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/node.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/node.py Fri Sep 15 15:20:41 2006 @@ -510,15 +510,19 @@ '%sgcheader%d' % (decoration, i)) for line in lines: yield line + if self.T._hints.get('nolength', False): + length = '' + else: + length = '%d, ' % len(self.obj.items) if self.T.OF is Void or len(self.obj.items) == 0: - yield '\t%d' % len(self.obj.items) + yield '\t' + length[:-2] # skip the ', ' yield '}' elif self.T.OF == Char: - yield '\t%d, %s' % (len(self.obj.items), - c_char_array_constant(''.join(self.obj.items))) + yield '\t%s%s' % (length, + c_char_array_constant(''.join(self.obj.items))) yield '}' else: - yield '\t%d, {' % len(self.obj.items) + yield '\t%s{' % (length,) for j in range(len(self.obj.items)): value = self.obj.items[j] lines = generic_initializationexpr(self.db, value, Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Fri Sep 15 15:20:41 2006 @@ -79,6 +79,39 @@ fn = self.getcompiled(llf) fn() + def test_prebuilt_nolength_array(self): + A = Array(Signed, hints={'nolength': True}) + a = malloc(A, 5, immortal=True) + a[0] = 8 + a[1] = 5 + a[2] = 12 + a[3] = 12 + a[4] = 15 + def llf(): + s = '' + for i in range(5): + s += chr(64+a[i]) + assert s == "HELLO" + fn = self.getcompiled(llf) + fn() + + def test_prebuilt_nolength_char_array(self): + for lastchar in ('\x00', 'X'): + A = Array(Char, hints={'nolength': True}) + a = malloc(A, 5, immortal=True) + a[0] = '8' + a[1] = '5' + a[2] = '?' + a[3] = '!' + a[4] = lastchar + def llf(): + s = '' + for i in range(5): + s += a[i] + assert s == "85?!" + lastchar + fn = self.getcompiled(llf) + fn() + def test_call_with_fixedsizearray(self): A = FixedSizeArray(Struct('s1', ('x', Signed)), 5) S = GcStruct('s', ('a', Ptr(A))) From fijal at codespeak.net Fri Sep 15 15:32:04 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 15 Sep 2006 15:32:04 +0200 (CEST) Subject: [pypy-svn] r32364 - in pypy/dist/pypy: rpython/ootypesystem translator/js/test Message-ID: <20060915133204.2FB2B10071@code0.codespeak.net> Author: fijal Date: Fri Sep 15 15:32:01 2006 New Revision: 32364 Modified: pypy/dist/pypy/rpython/ootypesystem/bltregistry.py pypy/dist/pypy/translator/js/test/test_bltn.py Log: Fixed issue with remaining caches between tests. Modified: pypy/dist/pypy/rpython/ootypesystem/bltregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/bltregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/bltregistry.py Fri Sep 15 15:32:01 2006 @@ -250,3 +250,6 @@ _class = hop.r_result.lowleveltype._class_ return hop.genop('new', [Constant(ExternalType.get(_class), concretetype=ootype.Void)], \ resulttype = ExternalType.get(_class)) + +def rebuild_basic_external(): + ExternalType.class_dict = {} Modified: pypy/dist/pypy/translator/js/test/test_bltn.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_bltn.py (original) +++ pypy/dist/pypy/translator/js/test/test_bltn.py Fri Sep 15 15:32:01 2006 @@ -3,9 +3,13 @@ import py -from pypy.rpython.ootypesystem.bltregistry import BasicExternal, MethodDesc +from pypy.rpython.ootypesystem.bltregistry import BasicExternal, MethodDesc,\ + rebuild_basic_external from pypy.translator.js.test.runtest import compile_function, check_source_contains +def setup_function(fun): + rebuild_basic_external() + # check rendering _dom.get_document() def test_simple_builtin(): from pypy.translator.js.modules._dom import get_document @@ -52,7 +56,6 @@ assert check_source_contains(fn, "\.some_callback = callback") def test_get_elements(): - py.test.skip('"Should be working" - will investigate later') from pypy.translator.js.modules import _dom as dom def getaa(tname): From arigo at codespeak.net Fri Sep 15 15:49:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Sep 2006 15:49:45 +0200 (CEST) Subject: [pypy-svn] r32366 - pypy/branch/kill-keepalives/pypy/rpython/rctypes Message-ID: <20060915134945.77D5C10071@code0.codespeak.net> Author: arigo Date: Fri Sep 15 15:49:44 2006 New Revision: 32366 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py Log: Small fix. Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py Fri Sep 15 15:49:44 2006 @@ -37,8 +37,8 @@ llops.genop('setfield', inputargs) def initialize_const(self, p, ptr): - if ptr is None: # passed as argument to functions expecting pointers - return + if not ptr: # NULL pointer, or literal None passed as argument to + return # functions expecting pointers llcontents = self.r_contents.convert_const(ptr.contents) p.c_data[0] = llcontents.c_data # the following line is probably pointless, as 'llcontents' will be From mwh at codespeak.net Fri Sep 15 18:26:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 15 Sep 2006 18:26:47 +0200 (CEST) Subject: [pypy-svn] r32371 - in pypy/branch/kill-keepalives/pypy/translator/backendopt: . test Message-ID: <20060915162647.7D0CE10075@code0.codespeak.net> Author: mwh Date: Fri Sep 15 18:26:45 2006 New Revision: 32371 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Log: so i don't know how long this will be useful for, but support for removing zero_mallocs. Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Fri Sep 15 18:26:45 2006 @@ -137,7 +137,7 @@ if cp[0] != "op": return False op = cp[2] - if op.opname != "malloc": + if op.opname not in ("malloc", "zero_malloc"): return False lltypes[op.result.concretetype] = True @@ -393,7 +393,7 @@ else: raise AssertionError, op.opname elif op.result in vars: - assert op.opname == "malloc" + assert op.opname in ("malloc", "zero_malloc") assert vars == {var: True} progress = True # drop the "malloc" operation @@ -468,7 +468,7 @@ # look for variables created inside the block by a malloc vars_created_here = [] for op in block.operations: - if op.opname == "malloc" and op.result in vars: + if op.opname in ("malloc", "zero_malloc") and op.result in vars: vars_created_here.append(op.result) for var in vars_created_here: flowin(var, newvarsmap=None) Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/test/test_malloc.py Fri Sep 15 18:26:45 2006 @@ -17,7 +17,7 @@ for node in flatten(graph): if isinstance(node, Block): for op in node.operations: - if op.opname == 'malloc': + if op.opname in ('malloc', 'zero_malloc'): S = op.args[0].value if not union_wrapper(S): # union wrappers are fine count1 += 1 @@ -296,3 +296,10 @@ return g.p.x graph = check(f, [], [], 1) assert 'flavored_free' in summary(graph) + +def test_remove_zero_malloc(): + S = lltype.GcStruct("S", ("x", lltype.Signed)) + def f(): + s = lltype.malloc(S, zero=True) + return s.x + check(f, [], [], 0) From cfbolz at codespeak.net Sat Sep 16 01:12:22 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 16 Sep 2006 01:12:22 +0200 (CEST) Subject: [pypy-svn] r32380 - pypy/extradoc/talk/23c3 Message-ID: <20060915231222.EF96010070@code0.codespeak.net> Author: cfbolz Date: Sat Sep 16 01:12:21 2006 New Revision: 32380 Modified: pypy/extradoc/talk/23c3/talk-pypy-dev.txt Log: so we submitted this. let's see what's going to happen. Modified: pypy/extradoc/talk/23c3/talk-pypy-dev.txt ============================================================================== --- pypy/extradoc/talk/23c3/talk-pypy-dev.txt (original) +++ pypy/extradoc/talk/23c3/talk-pypy-dev.txt Sat Sep 16 01:12:21 2006 @@ -1,9 +1,9 @@ Reference/Call For Papers: http://www.ccc.de/congress/2006/cfp.html DEADLINE: 30th September 2005 (friday) -Title: The PyPy fireworks +Title: PyPy Fireworks -Subtitle: ??? +Subtitle: Python Stackless JIT javascript .net AJAX 3.0 no-xml inside Section: Hacking @@ -12,23 +12,45 @@ Abstract (max 250 letters): - This talk describes cool and novel language features of the PyPy project (a - next generation Python interpreter) which are made possible by its flexible - architecture. The talk focuses mostly on showcasing interesting and useful - features together with example usages and less about their implementation. +Some three years and two CCC talks later, we'd like to present +a variety of results and features of the PyPy project. Topics will +include lightweight threading, low-level and high level backends, +e type-inferencing extension compiler, lazy evaluation and +applications of the PyPy translation toolchain, writing custom +Garbage Collectors Description (250-500 words): - PyPy is a reimplementation of Python written in Python itself, flexible and - easy to experiment with. Due to its flexibility it is easy to add language - features that are sometimes hard to implement in more traditional VM - implementations. We have implemented a number of such features, some of them - greatly enhancing the expressivity and flexibility of the language. - - XXX add more stuff +PyPy is a reimplementation of Python written in a restricted subset of +Python itself, flexible and easy to experiment with. Due to its flexibility +it is easy to add language features that are sometimes hard to implement in +more traditional VM implementations. We have implemented a number of such +features, some of them enhancing the expressiveness and flexibility +of the language. In addition there are some interesting applications of the +translation toolchain that go beyond its original design goal of translating +the Python interpreter to low-level languages. + +One of the language features the talk will showcase is the use of +OS-independent microthreads. With PyPy we can run millions +of microthreads, their number limited only by memory. The scheduling +of these threads can be done in various ways. One of them is to +use Oz-like (and Prolog-like) dataflow variables for +synchronization. Another one is to explicitly state which +threadlet is supposed to run. + +Another interesting feature which is not common in other object oriented +languages is transparent lazy evaluation of functions. + +The translation toolchain has a variety of targets which Restricted Python +code can be translated to: C, LLVM, CLI/.NET, Javascript (and more to come). +The Javascript backend can be used to implement AJAX application in Python +and run them either in Python (for testing purposes) or translate them to +Javascript and run them in the browser. - Development of PyPy is partly funded by the European Union - during the 6th Research Framework programme. +We also intend to present some just-in-time efforts. + +Oh, and development of PyPy is actually partly funded by the +European Union during the 6th Research Framework programme. Statement: We intend to submit a paper (PDF) for the 23C3 proceedings. XXX do we? Statement: We intend to submit the slides. From arigo at codespeak.net Sat Sep 16 13:55:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 13:55:00 +0200 (CEST) Subject: [pypy-svn] r32384 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20060916115500.952951005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 13:54:58 2006 New Revision: 32384 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: Fix args_from_long() to cope with -sys.maxint-1. Unclean :-( Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Sat Sep 16 13:54:58 2006 @@ -615,22 +615,39 @@ #_________________________________________________________________ # Helper Functions -def args_from_long(l): - if l < 0: - sign = -1 - elif l > 0: - sign = 1 - else: - sign = 0 - l = abs(l) +def digits_from_nonneg_long(l): digits = [] - i = 0 - while l: - digits.append(intmask(l & MASK)) + while True: + digits.append(intmask(l) & MASK) l = l >> SHIFT - if sign == 0: - digits = [0] - return digits, sign + if not l: + return digits +digits_from_nonneg_long._annspecialcase_ = "specialize:argtype(0)" + +def digits_for_most_neg_long(l): + digits = [] + while (intmask(l) & MASK) == 0: + digits.append(0) + l = l >> SHIFT + l = intmask(l) + digits.append(((l^(l-1))+1) >> 1) + return digits +digits_for_most_neg_long._annspecialcase_ = "specialize:argtype(0)" + +def args_from_long(l): + if l > 0: + return digits_from_nonneg_long(l), 1 + elif l == 0: + return [0], 0 + else: + l = -l + if l >= 0: + # normal case + return digits_from_nonneg_long(l), -1 + else: + # the most negative integer! hacks needed... + # Note that this case is only reachable when translated + return digits_for_most_neg_long(l), -1 args_from_long._annspecialcase_ = "specialize:argtype(0)" # ^^^ specialized by the precise type of 'l', which is typically a r_xxx # instance from rpython.rarithmetic Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_longobject.py Sat Sep 16 13:54:58 2006 @@ -18,6 +18,20 @@ class TestW_LongObject: + def test_args_from_long(self): + BASE = 1 << lobj.SHIFT + assert lobj.args_from_long(0) == ([0], 0) + assert lobj.args_from_long(17) == ([17], 1) + assert lobj.args_from_long(BASE-1) == ([BASE-1], 1) + assert lobj.args_from_long(BASE) == ([0, 1], 1) + assert lobj.args_from_long(BASE**2) == ([0, 0, 1], 1) + assert lobj.args_from_long(-17) == ([17], -1) + assert lobj.args_from_long(-(BASE-1)) == ([BASE-1], -1) + assert lobj.args_from_long(-BASE) == ([0, 1], -1) + assert lobj.args_from_long(-(BASE**2)) == ([0, 0, 1], -1) + assert lobj.args_from_long(-sys.maxint-1) == ( + lobj.digits_for_most_neg_long(-sys.maxint-1), -1) + def test_add(self): x = 123456789123456789000000L y = 123858582373821923936744221L From arigo at codespeak.net Sat Sep 16 14:01:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 14:01:19 +0200 (CEST) Subject: [pypy-svn] r32385 - pypy/dist/pypy/objspace/std Message-ID: <20060916120119.1B67F1005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 14:01:18 2006 New Revision: 32385 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: Simplification and comments. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Sat Sep 16 14:01:18 2006 @@ -625,12 +625,18 @@ digits_from_nonneg_long._annspecialcase_ = "specialize:argtype(0)" def digits_for_most_neg_long(l): + # This helper only works if 'l' is the most negative integer of its + # type, which in base 2 looks like: 1000000..0000 digits = [] while (intmask(l) & MASK) == 0: digits.append(0) l = l >> SHIFT - l = intmask(l) - digits.append(((l^(l-1))+1) >> 1) + # now 'l' looks like: ...111100000 + # turn it into: ...000100000 + # to drop the extra unwanted 1's introduced by the signed right shift + l = -intmask(l) + assert l >= 0 + digits.append(l) return digits digits_for_most_neg_long._annspecialcase_ = "specialize:argtype(0)" From arigo at codespeak.net Sat Sep 16 14:43:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 14:43:43 +0200 (CEST) Subject: [pypy-svn] r32386 - pypy/branch/kill-keepalives/pypy/translator/c/src Message-ID: <20060916124343.4967F1005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 14:43:41 2006 New Revision: 32386 Modified: pypy/branch/kill-keepalives/pypy/translator/c/src/mem.h Log: Allow raw_free(NULL), and don't count it as a free. Modified: pypy/branch/kill-keepalives/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/src/mem.h (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/src/mem.h Sat Sep 16 14:43:41 2006 @@ -33,7 +33,7 @@ #endif -#define OP_RAW_FREE(p, r) PyObject_Free(p); COUNT_FREE; +#define OP_RAW_FREE(p, r) PyObject_Free(p); COUNT_FREE(p); #define OP_RAW_MEMCLEAR(p, size, r) memset((void*)p, 0, size) @@ -97,7 +97,7 @@ /*------------------------------------------------------------*/ #define COUNT_MALLOC /* nothing */ -#define COUNT_FREE /* nothing */ +#define COUNT_FREE(p) /* nothing */ /*------------------------------------------------------------*/ #else /*COUNT_OP_MALLOCS*/ @@ -106,7 +106,7 @@ static int count_mallocs=0, count_frees=0; #define COUNT_MALLOC count_mallocs++ -#define COUNT_FREE count_frees++ +#define COUNT_FREE(p) do { if (p) count_frees++; } while (0) PyObject* malloc_counters(PyObject* self, PyObject* args) { From arigo at codespeak.net Sat Sep 16 14:44:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 14:44:26 +0200 (CEST) Subject: [pypy-svn] r32387 - in pypy/branch/kill-keepalives/pypy/translator/c: . test Message-ID: <20060916124426.D9CD71005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 14:44:25 2006 New Revision: 32387 Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Log: Fix bad C code that produced a gcc warning. Very very corner-casish. Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Sat Sep 16 14:44:25 2006 @@ -522,9 +522,10 @@ items = self.expr(op.args[0]) if not isinstance(ARRAY, FixedSizeArray): items += '->items' - return '%s = %s + %s;' % (self.expr(op.result), - items, - self.expr(op.args[1])) + result = '%s + %s' % (items, self.expr(op.args[1])) + if isinstance(ARRAY.OF, FixedSizeArray): # more C blaming here + result = '*(%s)' % (result,) + return '%s = %s;' % (self.expr(op.result), result) def OP_PTR_NONZERO(self, op): return '%s = (%s != NULL);' % (self.expr(op.result), Modified: pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/test/test_lltyped.py Sat Sep 16 14:44:25 2006 @@ -48,7 +48,6 @@ assert a42[5][6] == -6 return len(a42)*100 + len(a42[4]) fn = self.getcompiled(llf) - res = fn() assert fn() == 607 def test_recursivearray(self): @@ -63,6 +62,19 @@ fn = self.getcompiled(llf) fn() + def test_array_of_array(self): + C = FixedSizeArray(Signed, 7) + B = Array(C) + A = FixedSizeArray(C, 6) + b = malloc(B, 5, immortal=True) + b[3][4] = 999 + a = malloc(A, immortal=True) + a[2][5] = 888000 + def llf(): + return b[3][4] + a[2][5] + fn = self.getcompiled(llf) + assert fn() == 888999 + def test_prebuilt_array(self): A = FixedSizeArray(Signed, 5) a = malloc(A, immortal=True) @@ -128,10 +140,9 @@ assert res == 123 def test_more_prebuilt_arrays(self): - py.test.skip("not allowed any more") A = FixedSizeArray(Struct('s1', ('x', Signed)), 5) - S = GcStruct('s', ('a1', Ptr(A)), ('a2', A)) - s = malloc(S, zero=True) + S = Struct('s', ('a1', Ptr(A)), ('a2', A)) + s = malloc(S, zero=True, immortal=True) s.a1 = malloc(A, immortal=True) s.a1[2].x = 50 s.a2[2].x = 60 From arigo at codespeak.net Sat Sep 16 14:44:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 14:44:58 +0200 (CEST) Subject: [pypy-svn] r32388 - pypy/branch/kill-keepalives/pypy/rpython/lltypesystem Message-ID: <20060916124458.202AB1005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 14:44:57 2006 New Revision: 32388 Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py Log: Support raw_free(NULL) here too. Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/llmemory.py Sat Sep 16 14:44:57 2006 @@ -550,6 +550,8 @@ return size.raw_malloc([]) def raw_free(adr): + if not adr: # ignore NULLs + return # xxx crash if you get only the header of a gc object assert isinstance(adr.ob._obj, lltype._parentable) adr.ob._as_obj()._free() From arigo at codespeak.net Sat Sep 16 14:46:47 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 14:46:47 +0200 (CEST) Subject: [pypy-svn] r32389 - in pypy/branch/kill-keepalives/pypy/rpython: lltypesystem rctypes rctypes/test Message-ID: <20060916124647.81FB21005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 14:46:44 2006 New Revision: 32389 Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/avoid_p.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rvoid_p.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py Log: Walking on thin ice adding all the necessary keepalives. The code starts to look like it should have been written as a bunch of RPython classes instead of generated by hand. Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lltype.py Sat Sep 16 14:46:44 2006 @@ -1292,7 +1292,8 @@ if parent is None: break T = typeOf(parent) - if not isinstance(T, Struct) or T._first_struct()[0] != index: + if (not isinstance(T, Struct) or T._first_struct()[0] != index + or isinstance(T, FixedSizeArray)): break container = parent return container Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/avoid_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/avoid_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/avoid_p.py Sat Sep 16 14:46:44 2006 @@ -96,5 +96,9 @@ # cast to pointer v_result = hop.genop('cast_adr_to_ptr', [v_adr], resulttype = hop.r_result.ll_type) + if isinstance(r_arg, PointerRepr): + v_content_owner = r_arg.getkeepalive(hop.llops, v_box) + else: + v_content_owner = None hop.exception_cannot_occur() - return hop.r_result.return_value(hop.llops, v_result) + return hop.r_result.return_value(hop.llops, v_result, v_content_owner) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py Sat Sep 16 14:46:44 2006 @@ -116,6 +116,7 @@ class __extend__(pairtype(ArrayRepr, IntegerRepr)): def rtype_getitem((r_array, r_int), hop): v_array, v_index = hop.inputargs(r_array, lltype.Signed) + v_owner = r_array.get_c_data_owner(hop.llops, v_array) hop.exception_cannot_occur() if isinstance(r_array.r_item, PrimitiveRepr): # primitive case (optimization; the below also works in this case) @@ -123,11 +124,11 @@ # example: a[0].contents = ... to change the first pointer of # an array of pointers. v_value = r_array.get_item_value(hop.llops, v_array, v_index) - return r_array.r_item.return_value(hop.llops, v_value) + return r_array.r_item.return_value(hop.llops, v_value, v_owner) else: # ByRef case v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index) - return r_array.r_item.return_c_data(hop.llops, v_c_data) + return r_array.r_item.return_c_data(hop.llops, v_c_data, v_owner) def rtype_setitem((r_array, r_int), hop): v_array, v_index, v_item = hop.inputargs(r_array, lltype.Signed, Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py Sat Sep 16 14:46:44 2006 @@ -14,14 +14,14 @@ autofree_fields = ("keepalive",) - def return_c_data(self, llops, v_c_data): + def return_c_data(self, llops, v_c_data, v_c_data_owner): """Read out the RPython string from a raw C pointer. Used when the data is returned from an operation or C function call. """ v_char_p = self.getvalue_from_c_data(llops, v_c_data) return llops.gendirectcall(ll_charp2str, v_char_p) - def return_value(self, llops, v_value): + def return_value(self, llops, v_value, v_content_owner=None): # like return_c_data(), but when the input is only the value # field instead of the c_data pointer return llops.gendirectcall(ll_charp2str, v_value) @@ -136,22 +136,26 @@ return lltype.nullptr(string_repr.lowleveltype.TO) def ll_setstring(box, string): - # XXX the copying of the string is often not needed, but it is - # very hard to avoid in the general case of a moving GC that can - # move 'string' around unpredictably. - n = len(string.chars) - buffer = llmemory.raw_malloc(NULL_HEADER + SIZEOF_CHAR * (n+1)) - charscopy = llmemory.cast_adr_to_ptr(buffer, PCHARSCOPY) - for i in range(n): - charscopy[i] = string.chars[i] - charscopy[n] = '\x00' + if not string: + new_c_data = lltype.nullptr(CCHARP.TO) + charscopy = lltype.nullptr(CHARSCOPY) + else: + # XXX the copying of the string is often not needed, but it is + # very hard to avoid in the general case of a moving GC that can + # move 'string' around unpredictably. + n = len(string.chars) + buffer = llmemory.raw_malloc(NULL_HEADER + SIZEOF_CHAR * (n+1)) + charscopy = llmemory.cast_adr_to_ptr(buffer, PCHARSCOPY) + for i in range(n): + charscopy[i] = string.chars[i] + charscopy[n] = '\x00' + new_c_data = lltype.direct_arrayitems(charscopy) # store a 'char *' pointer in the box.c_data - box.c_data[0] = lltype.direct_arrayitems(charscopy) + box.c_data[0] = new_c_data # keep the ownership of the buffer in the box.keepalive field prev = box.keepalive box.keepalive = charscopy - if prev: - llmemory.raw_free(llmemory.cast_ptr_to_adr(prev)) + llmemory.raw_free(llmemory.cast_ptr_to_adr(prev)) CHARSCOPY = lltype.Array(lltype.Char, hints={'nolength': True}) PCHARSCOPY = lltype.Ptr(CHARSCOPY) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Sat Sep 16 14:46:44 2006 @@ -5,6 +5,12 @@ from pypy.annotation.pairtype import pairtype +# header common to boxes with a destructor +RCBOX_HEADER = lltype.GcStruct('rcbox', + ('rtti', lltype.Ptr(lltype.RuntimeTypeInfo))) +P_RCBOX_HEADER = lltype.Ptr(RCBOX_HEADER) + + class CTypesRepr(Repr): "Base class for the Reprs representing ctypes object." @@ -55,8 +61,15 @@ else: s_memoryowner = SomeCTypesObject(ctype, ownsmemory=True) self.r_memoryowner = rtyper.getrepr(s_memoryowner) + # the box that really owns our C data - it is usually a box of + # type r_memoryowner.lowleveltype, but ocasionally it can be + # any larger struct or array type and we only point somewhere + # inside it fields.append( - ( "c_data_owner_keepalive", self.r_memoryowner.lowleveltype )) + ( "c_data_owner_keepalive", P_RCBOX_HEADER )) + + if self.autofree_fields: + fields.insert(0, ("header", RCBOX_HEADER)) keywords = {'hints': {'autofree_fields': self.autofree_fields}} self.lowleveltype = lltype.Ptr( @@ -79,10 +92,9 @@ def ll_rctypes_free(box): for fieldname in autofree_fields: p = getattr(box, fieldname) - if p: - llmemory.raw_free(llmemory.cast_ptr_to_adr(p)) + llmemory.raw_free(llmemory.cast_ptr_to_adr(p)) - args_s = [annmodel.SomePtr(self.lowleveltype)] + args_s = [annmodel.SomePtr(P_RCBOX_HEADER)] graph = self.rtyper.annotate_helper(ll_rctypes_query, args_s) queryptr = self.rtyper.getcallable(graph) @@ -103,6 +115,31 @@ def ctypecheck(self, value): return isinstance(value, self.ctype) + def basic_instantiate_prebuilt(self): + TYPE = self.lowleveltype.TO + result = lltype.malloc(TYPE, immortal = True, zero = True) + if self.autofree_fields: + result.header.rtti = lltype.getRuntimeTypeInfo(TYPE) + return result + + def genop_basic_instantiate(self, llops): + # XXX the whole rtti business is a bit over-obscure + TYPE = self.lowleveltype.TO + c1 = inputconst(lltype.Void, TYPE) + v_box = llops.genop("malloc", [c1], resulttype=self.lowleveltype) + if self.autofree_fields: + c_hdr = inputconst(lltype.Void, 'header') + c_rtti = inputconst(lltype.Void, 'rtti') + rtti = lltype.getRuntimeTypeInfo(TYPE) + v_rtti = inputconst(lltype.typeOf(rtti), rtti) + llops.genop("setinteriorfield", [v_box, c_hdr, c_rtti, v_rtti]) + for fieldname in self.autofree_fields: + FIELDTYPE = getattr(TYPE, fieldname) + c_name = inputconst(lltype.Void, fieldname) + v_null = inputconst(FIELDTYPE, lltype.nullptr(FIELDTYPE.TO)) + llops.genop("setfield", [v_box, c_name, v_null]) + return v_box + def convert_const(self, value): if self.ctypecheck(value): key = "by_id", id(value) @@ -117,8 +154,7 @@ return self.const_cache[key][0] except KeyError: self.setup() - p = lltype.malloc(self.r_memoryowner.lowleveltype.TO, - immortal = True) + p = self.r_memoryowner.basic_instantiate_prebuilt() p.c_data = lltype.malloc(self.r_memoryowner.c_data_type, immortal = True, zero = True) @@ -128,11 +164,9 @@ else: # we must return a non-memory-owning box that keeps the # memory-owning box alive - result = lltype.malloc(self.lowleveltype.TO, - immortal = True, - zero = True) + result = self.basic_instantiate_prebuilt() result.c_data = p.c_data # initialize c_data pointer - result.c_data_owner_keepalive = p + result.c_data_owner_keepalive = p.header self.const_cache[key] = result, keepalive return result @@ -143,20 +177,15 @@ def get_c_data_owner(self, llops, v_box): if self.ownsmemory: - return v_box + return llops.genop('cast_pointer', [v_box], + resulttype=P_RCBOX_HEADER) else: - inputargs = [v_box, inputconst(lltype.Void, - "c_data_owner_keepalive")] - return llops.genop('getfield', inputargs, - self.r_memoryowner.lowleveltype) + c_name = inputconst(lltype.Void, "c_data_owner_keepalive") + return llops.genop('getfield', [v_box, c_name], + resulttype=P_RCBOX_HEADER) def allocate_instance(self, llops): - TYPE = self.lowleveltype.TO - c1 = inputconst(lltype.Void, TYPE) - v_box = llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype) - # XXX don't use zero_malloc, but just make sure there is a NULL - # in the autofreed field(s) - + v_box = self.genop_basic_instantiate(llops) TYPE = self.c_data_type if TYPE._is_varsize(): raise TyperError("allocating array with unknown length") @@ -173,12 +202,7 @@ return v_box def allocate_instance_varsize(self, llops, v_length): - TYPE = self.lowleveltype.TO - c1 = inputconst(lltype.Void, TYPE) - v_box = llops.genop("zero_malloc", [c1], resulttype=self.lowleveltype) - # XXX don't use zero_malloc, but just make sure there is a NULL - # in the autofreed field(s) - + v_box = self.genop_basic_instantiate(llops) TYPE = self.c_data_type if not TYPE._is_varsize(): raise TyperError("allocating non-array with specified length") @@ -202,7 +226,7 @@ raise TyperError("allocate_instance_varsize on an alias box") return v_box - def allocate_instance_ref(self, llops, v_c_data, v_c_data_owner=None): + def allocate_instance_ref(self, llops, v_c_data, v_c_data_owner): """Only if self.ownsmemory is false. This allocates a new instance and initialize its c_data pointer.""" if self.ownsmemory: @@ -211,22 +235,17 @@ v_box = self.allocate_instance(llops) inputargs = [v_box, inputconst(lltype.Void, "c_data"), v_c_data] llops.genop('setfield', inputargs) - if v_c_data_owner is not None: - assert (v_c_data_owner.concretetype == - self.r_memoryowner.lowleveltype) - inputargs = [v_box, - inputconst(lltype.Void, "c_data_owner_keepalive"), - v_c_data_owner] - llops.genop('setfield', inputargs) + v_c_data_owner = cast_to_header(llops, v_c_data_owner) + c_name = inputconst(lltype.Void, "c_data_owner_keepalive") + llops.genop('setfield', [v_box, c_name, v_c_data_owner]) return v_box - def return_c_data(self, llops, v_c_data): + def return_c_data(self, llops, v_c_data, v_c_data_owner): """Turn a raw C pointer to the data into a memory-alias box. Used when the data is returned from an operation or C function call. Special-cased in PrimitiveRepr. """ - # XXX add v_c_data_owner - return self.allocate_instance_ref(llops, v_c_data) + return self.allocate_instance_ref(llops, v_c_data, v_c_data_owner) def copykeepalive(self, llops, v_box, v_destbox, destsuboffset=()): # copy the 'keepalive' data over, unless it's an autofree @@ -303,7 +322,7 @@ value = value.value p.c_data[0] = value - def return_value(self, llops, v_value): + def return_value(self, llops, v_value, v_content_owner=None): # like return_c_data(), but when the input is only the value # field instead of the c_data pointer r_temp = self.r_memoryowner @@ -323,9 +342,15 @@ C_ZERO = inputconst(lltype.Signed, 0) -def ll_rctypes_query(p): - S = lltype.typeOf(p).TO - return lltype.getRuntimeTypeInfo(S) +def ll_rctypes_query(rcboxheader): + return rcboxheader.rtti + +def cast_to_header(llops, v_box): + if v_box.concretetype != P_RCBOX_HEADER: + assert v_box.concretetype.TO.header == RCBOX_HEADER + v_box = llops.genop('cast_pointer', [v_box], + resulttype=P_RCBOX_HEADER) + return v_box def reccopy(source, dest): # copy recursively a structure or array onto another. Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rpointer.py Sat Sep 16 14:46:44 2006 @@ -3,6 +3,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.annotation.pairtype import pairtype from pypy.rpython.rctypes.rmodel import CTypesValueRepr, genreccopy +from pypy.rpython.rctypes.rmodel import P_RCBOX_HEADER, cast_to_header from pypy.annotation.model import SomeCTypesObject from pypy.objspace.flow.model import Constant @@ -12,7 +13,6 @@ # For recursive types, getting the r_contents is delayed until # _setup_repr(). ll_contents = lltype.Ptr(lltype.ForwardReference()) - self.keepalive_box_type = lltype.GcForwardReference() super(PointerRepr, self).__init__(rtyper, s_pointer, ll_contents) def _setup_repr(self): @@ -23,18 +23,26 @@ ownsmemory=False)) if isinstance(self.ll_type.TO, lltype.ForwardReference): self.ll_type.TO.become(self.r_contents.c_data_type) - if isinstance(self.keepalive_box_type, lltype.GcForwardReference): - self.keepalive_box_type.become( - self.r_contents.r_memoryowner.lowleveltype.TO) def get_content_keepalive_type(self): "Keepalive for the box that holds the data that 'self' points to." - return lltype.Ptr(self.keepalive_box_type) + return P_RCBOX_HEADER + + def getkeepalive(self, llops, v_box): + c_name = inputconst(lltype.Void, 'keepalive') + return llops.genop('getfield', [v_box, c_name], + resulttype=P_RCBOX_HEADER) def setkeepalive(self, llops, v_box, v_owner): - inputargs = [v_box, inputconst(lltype.Void, 'keepalive'), - v_owner] - llops.genop('setfield', inputargs) + c_name = inputconst(lltype.Void, 'keepalive') + v_owner = cast_to_header(llops, v_owner) + llops.genop('setfield', [v_box, c_name, v_owner]) + + def return_value(self, llops, v_value, v_content_owner=None): + v_box = super(PointerRepr, self).return_value(llops, v_value) + if v_content_owner is not None: + self.setkeepalive(llops, v_box, v_content_owner) + return v_box def initialize_const(self, p, ptr): if not ptr: # NULL pointer, or literal None passed as argument to @@ -58,7 +66,9 @@ v_ptr = hop.inputarg(self, 0) v_c_ptr = self.getvalue(hop.llops, v_ptr) hop.exception_cannot_occur() - return self.r_contents.allocate_instance_ref(hop.llops, v_c_ptr) + v_content_owner = self.getkeepalive(hop.llops, v_ptr) + return self.r_contents.allocate_instance_ref(hop.llops, v_c_ptr, + v_content_owner) def rtype_setattr(self, hop): s_attr = hop.args_s[1] @@ -81,7 +91,9 @@ else: v_c_ptr = hop.genop('direct_ptradd', [v_c_ptr, v_index], resulttype = r_ptr.ll_type) - return self.r_contents.return_c_data(hop.llops, v_c_ptr) + v_content_owner = self.getkeepalive(hop.llops, v_ptr) + return self.r_contents.return_c_data(hop.llops, v_c_ptr, + v_content_owner) def rtype_setitem((r_ptr, _), hop): # p[0] = x is not the same as p.contents.value = x Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py Sat Sep 16 14:46:44 2006 @@ -18,14 +18,14 @@ self.value_repr = rtyper.getprimitiverepr(ll_type) self.normalized_value_repr = rtyper.getprimitiverepr(normalized_lltype) - def return_c_data(self, llops, v_c_data): + def return_c_data(self, llops, v_c_data, v_c_data_owner): """Read out the atomic data from a raw C pointer. Used when the data is returned from an operation or C function call. """ v_value = self.getvalue_from_c_data(llops, v_c_data) return self.return_value(llops, v_value) - def return_value(self, llops, v_value): + def return_value(self, llops, v_value, v_content_owner=None): # like return_c_data(), but when the input is only the value # field instead of the c_data pointer return llops.convertvar(v_value, self.value_repr, @@ -38,7 +38,7 @@ v_primitive = hop.inputarg(self, 0) hop.exception_cannot_occur() v_c_data = self.get_c_data(hop.llops, v_primitive) - return self.return_c_data(hop.llops, v_c_data) + return self.return_c_data(hop.llops, v_c_data, None) def rtype_setattr(self, hop): s_attr = hop.args_s[1] Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Sat Sep 16 14:46:44 2006 @@ -89,6 +89,7 @@ name = s_attr.const r_field = self.r_fields[name] v_struct, v_attr = hop.inputargs(self, lltype.Void) + v_owner = self.get_c_data_owner(hop.llops, v_struct) hop.exception_cannot_occur() if isinstance(r_field, PrimitiveRepr): # primitive case (optimization; the below also works in this case) @@ -96,11 +97,11 @@ # example: s.p.contents = ... to change the pointer field 'p' # of 's'. v_value = self.get_field_value(hop.llops, v_struct, name) - return r_field.return_value(hop.llops, v_value) + return r_field.return_value(hop.llops, v_value, v_owner) else: # ByRef case v_c_data = self.get_c_data_of_field(hop.llops, v_struct, name) - return r_field.return_c_data(hop.llops, v_c_data) + return r_field.return_c_data(hop.llops, v_c_data, v_owner) def rtype_setattr(self, hop): s_attr = hop.args_s[1] Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rvoid_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rvoid_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rvoid_p.py Sat Sep 16 14:46:44 2006 @@ -43,18 +43,18 @@ return r_to.return_value(llops, v_adr) -class __extend__(pairtype(AbstractStringRepr, CVoidPRepr)): - def convert_from_to((r_from, r_to), v, llops): - # warning: no keepalives, only for short-lived conversions like - # in argument passing - # r_from could be char_repr: first convert it to string_repr - v = llops.convertvar(v, r_from, string_repr) - v_adr = llops.gendirectcall(ll_string2addr, v) - return r_to.return_value(llops, v_adr) +##class __extend__(pairtype(AbstractStringRepr, CVoidPRepr)): +## def convert_from_to((r_from, r_to), v, llops): +## # warning: no keepalives, only for short-lived conversions like +## # in argument passing +## # r_from could be char_repr: first convert it to string_repr +## v = llops.convertvar(v, r_from, string_repr) +## v_adr = llops.gendirectcall(ll_string2addr, v) +## return r_to.return_value(llops, v_adr) -def ll_string2addr(s): - if s: - ptr = lltype.direct_arrayitems(s.chars) - return llmemory.cast_ptr_to_adr(ptr) - else: - return llmemory.NULL +##def ll_string2addr(s): +## if s: +## ptr = lltype.direct_arrayitems(s.chars) +## return llmemory.cast_ptr_to_adr(ptr) +## else: +## return llmemory.NULL Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py Sat Sep 16 14:46:44 2006 @@ -98,7 +98,7 @@ ## assert strlen(ARR) == 3 # variable arguments s = chr(n) + 'bc' - assert strlen(s) == 3 + #assert strlen(s) == 3 ---- disabled assert strlen(c_char_p(s)) == 3 assert strlen((c_char * 6)('a', 'b')) == 2 # XXX Bytes are not chars in llinterp. From arigo at codespeak.net Sat Sep 16 19:08:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 19:08:56 +0200 (CEST) Subject: [pypy-svn] r32393 - pypy/branch/kill-keepalives/pypy/rpython/rctypes Message-ID: <20060916170856.A71DA1005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 19:08:54 2006 New Revision: 32393 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Log: More keepalive fine-tuning. Tests still not passing. Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py Sat Sep 16 19:08:54 2006 @@ -5,6 +5,7 @@ from pypy.annotation.pairtype import pairtype from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr from pypy.rpython.rctypes.rmodel import genreccopy_arrayitem, reccopy, C_ZERO +from pypy.rpython.rctypes.rmodel import copykeepalive from pypy.rpython.rctypes.rprimitive import PrimitiveRepr from pypy.rpython.rctypes.rpointer import PointerRepr from pypy.rpython.rctypes.aarray import VarSizedArrayType @@ -105,7 +106,9 @@ v_c_array = self.get_c_data(llops, v_array) genreccopy_arrayitem(llops, v_newvalue, v_c_array, v_index) # copy the keepalive information too - self.r_item.copykeepalive(llops, v_item, v_array, (v_index,)) + if hasattr(self.r_item.lowleveltype.TO, 'keepalive'): + copykeepalive(llops, self.r_item.lowleveltype.TO.keepalive, + v_item, (), v_array, (v_index,)) def initializeitems(self, llops, v_array, items_v): for i, v_item in enumerate(items_v): @@ -123,12 +126,16 @@ # NB. this optimization is invalid for PointerReprs! See for # example: a[0].contents = ... to change the first pointer of # an array of pointers. - v_value = r_array.get_item_value(hop.llops, v_array, v_index) - return r_array.r_item.return_value(hop.llops, v_value, v_owner) + v_c_data = r_array.get_item_value(hop.llops, v_array, v_index) else: # ByRef case v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index) - return r_array.r_item.return_c_data(hop.llops, v_c_data, v_owner) + v_item = r_array.r_item.return_c_data(hop.llops, v_c_data, v_owner) + # copy the keepalive information too + if hasattr(r_array.r_item.lowleveltype.TO, 'keepalive'): + copykeepalive(hop.llops, r_array.r_item.lowleveltype.TO.keepalive, + v_array, (v_index,), v_item, ()) + return v_item def rtype_setitem((r_array, r_int), hop): v_array, v_index, v_item = hop.inputargs(r_array, lltype.Signed, Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py Sat Sep 16 19:08:54 2006 @@ -12,8 +12,6 @@ class CCharPRepr(CTypesValueRepr): - autofree_fields = ("keepalive",) - def return_c_data(self, llops, v_c_data, v_c_data_owner): """Read out the RPython string from a raw C pointer. Used when the data is returned from an operation or C function call. Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Sat Sep 16 19:08:54 2006 @@ -9,6 +9,7 @@ RCBOX_HEADER = lltype.GcStruct('rcbox', ('rtti', lltype.Ptr(lltype.RuntimeTypeInfo))) P_RCBOX_HEADER = lltype.Ptr(RCBOX_HEADER) +lltype.attachRuntimeTypeInfo(RCBOX_HEADER) class CTypesRepr(Repr): @@ -35,8 +36,6 @@ # * 'r_memoryowner.lowleveltype' is the lowleveltype of the repr for the # same ctype but for ownsmemory=True. - autofree_fields = () - def __init__(self, rtyper, s_ctypesobject, ll_type): # s_ctypesobject: the annotation to represent # ll_type: the low-level type representing the raw @@ -56,9 +55,10 @@ fields.append(( "keepalive", content_keepalive_type )) if self.ownsmemory: - self.autofree_fields = ("c_data",) + self.__class__.autofree_fields + self.autofree_fields = ("c_data",) self.r_memoryowner = self else: + self.autofree_fields = () s_memoryowner = SomeCTypesObject(ctype, ownsmemory=True) self.r_memoryowner = rtyper.getrepr(s_memoryowner) # the box that really owns our C data - it is usually a box of @@ -104,6 +104,9 @@ lltype.attachRuntimeTypeInfo(self.lowleveltype.TO, queryptr, destrptr) + # make sure the RCBOX_HEADER itself has got a query function + lltype.attachRuntimeTypeInfo(RCBOX_HEADER, queryptr) + def get_content_keepalive_type(self): """Return the type of the extra keepalive field used for the content of this object.""" @@ -247,20 +250,6 @@ """ return self.allocate_instance_ref(llops, v_c_data, v_c_data_owner) - def copykeepalive(self, llops, v_box, v_destbox, destsuboffset=()): - # copy the 'keepalive' data over, unless it's an autofree - assert v_box.concretetype == self.lowleveltype - try: - TYPE = self.lowleveltype.TO.keepalive - except AttributeError: - pass - else: - if 'keepalive' not in self.autofree_fields: - c_keepalive = inputconst(lltype.Void, 'keepalive') - genreccopy_rel(llops, TYPE, - v_box, (c_keepalive,), - v_destbox, (c_keepalive,) + destsuboffset) - class __extend__(pairtype(CTypesRepr, CTypesRepr)): @@ -271,9 +260,10 @@ r_from.ownsmemory and not r_to.ownsmemory): v_c_data = r_from.get_c_data(llops, v) v_result = r_to.allocate_instance_ref(llops, v_c_data, v) - # copy the 'keepalive' information - c_keepalive = inputconst(lltype.Void, 'keepalive') - r_from.copykeepalive(llops, v, v_result) + # copy all the 'keepalive' information + if hasattr(r_from.lowleveltype.TO, 'keepalive'): + copykeepalive(llops, r_from.lowleveltype.TO.keepalive, + v, (), v_result, ()) return v_result else: return NotImplemented @@ -352,6 +342,14 @@ resulttype=P_RCBOX_HEADER) return v_box +def copykeepalive(llops, TYPE, v_box, srcsuboffset, + v_destbox, destsuboffset): + # copy (a part of) the 'keepalive' data over + c_keepalive = inputconst(lltype.Void, 'keepalive') + genreccopy_rel(llops, TYPE, + v_box, (c_keepalive,) + srcsuboffset, + v_destbox, (c_keepalive,) + destsuboffset) + def reccopy(source, dest): # copy recursively a structure or array onto another. T = lltype.rawTypeOf(source).TO Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Sat Sep 16 19:08:54 2006 @@ -2,6 +2,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr from pypy.rpython.rctypes.rmodel import genreccopy_structfield, reccopy +from pypy.rpython.rctypes.rmodel import copykeepalive from pypy.rpython.rctypes.rprimitive import PrimitiveRepr from pypy.annotation.model import SomeCTypesObject @@ -97,11 +98,17 @@ # example: s.p.contents = ... to change the pointer field 'p' # of 's'. v_value = self.get_field_value(hop.llops, v_struct, name) - return r_field.return_value(hop.llops, v_value, v_owner) + v_item = r_field.return_value(hop.llops, v_value, v_owner) else: # ByRef case v_c_data = self.get_c_data_of_field(hop.llops, v_struct, name) - return r_field.return_c_data(hop.llops, v_c_data, v_owner) + v_item = r_field.return_c_data(hop.llops, v_c_data, v_owner) + # copy the keepalive information too + if hasattr(r_field.lowleveltype.TO, 'keepalive'): + c_name = inputconst(lltype.Void, cmangle(name)) + copykeepalive(hop.llops, r_field.lowleveltype.TO.keepalive, + v_struct, (c_name,), v_item, ()) + return v_item def rtype_setattr(self, hop): s_attr = hop.args_s[1] @@ -118,8 +125,10 @@ v_c_struct = self.get_c_data(llops, v_struct) genreccopy_structfield(llops, v_newvalue, v_c_struct, cmangle(name)) # copy the keepalive information too - c_name = inputconst(lltype.Void, cmangle(name)) - r_field.copykeepalive(llops, v_item, v_struct, (c_name,)) + if hasattr(r_field.lowleveltype.TO, 'keepalive'): + c_name = inputconst(lltype.Void, cmangle(name)) + copykeepalive(llops, r_field.lowleveltype.TO.keepalive, + v_item, (), v_struct, (c_name,)) def cmangle(name): # obscure: names starting with '_' are not allowed in From arigo at codespeak.net Sat Sep 16 20:04:46 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Sep 2006 20:04:46 +0200 (CEST) Subject: [pypy-svn] r32394 - pypy/branch/kill-keepalives/pypy/rpython/rctypes Message-ID: <20060916180446.EB3531005A@code0.codespeak.net> Author: arigo Date: Sat Sep 16 20:04:44 2006 New Revision: 32394 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstringbuf.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Log: Wack wack wack. Puf puf. Argh. Some progress, only a few failures left when the currently-buggy malloc-removal is disabled. Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rarray.py Sat Sep 16 20:04:44 2006 @@ -127,12 +127,14 @@ # example: a[0].contents = ... to change the first pointer of # an array of pointers. v_c_data = r_array.get_item_value(hop.llops, v_array, v_index) + v_item = r_array.r_item.return_value(hop.llops, v_c_data, v_owner) else: # ByRef case v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index) - v_item = r_array.r_item.return_c_data(hop.llops, v_c_data, v_owner) + v_item = r_array.r_item.return_c_data(hop.llops, v_c_data, v_owner) # copy the keepalive information too - if hasattr(r_array.r_item.lowleveltype.TO, 'keepalive'): + if (v_item.concretetype == r_array.r_item.lowleveltype + and hasattr(r_array.r_item.lowleveltype.TO, 'keepalive')): copykeepalive(hop.llops, r_array.r_item.lowleveltype.TO.keepalive, v_array, (v_index,), v_item, ()) return v_item Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rchar_p.py Sat Sep 16 20:04:44 2006 @@ -4,8 +4,10 @@ from pypy.rpython.lltypesystem.rstr import string_repr from pypy.rpython.rctypes.rmodel import CTypesValueRepr, C_ZERO from pypy.rpython.rctypes.rarray import ArrayRepr -from pypy.rpython.rctypes.rstringbuf import StringBufRepr +from pypy.rpython.rctypes.rstringbuf import StringBufRepr, ll_stringbufnew +from pypy.rpython.rctypes.astringbuf import StringBufferType from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from ctypes import c_char, c_char_p, cast @@ -25,14 +27,19 @@ return llops.gendirectcall(ll_charp2str, v_value) def get_content_keepalive_type(self): - "An extra keepalive used for the raw copy the RPython string." - return lltype.Ptr(CHARSCOPY) # raw_malloc'ed, automatically raw_free'd + """An extra keepalive used for the box that holds the raw copy + of the RPython string.""" + s_buf = annmodel.SomeCTypesObject(StringBufferType, ownsmemory=True) + r_buf = self.rtyper.getrepr(s_buf) + return r_buf.lowleveltype def getstring(self, llops, v_box): return llops.gendirectcall(ll_getstring, v_box) def setstring(self, llops, v_box, v_str): - llops.gendirectcall(ll_setstring, v_box, v_str) + RCBOX_STRBUF = self.lowleveltype.TO.keepalive.TO + c_r_buf = inputconst(lltype.Void, RCBOX_STRBUF) + llops.gendirectcall(ll_setstring, c_r_buf, v_box, v_str) def convert_const(self, value): if value is not None and not isinstance(value, (str, c_char_p)): @@ -44,8 +51,9 @@ def initialize_const(self, p, string): if isinstance(string, c_char_p): string = string.value + RCBOX_STRBUF = self.lowleveltype.TO.keepalive.TO llstring = string_repr.convert_const(string) - ll_setstring(p, llstring) + ll_setstring(RCBOX_STRBUF, p, llstring) def rtype_getattr(self, hop): s_attr = hop.args_s[1] @@ -133,29 +141,17 @@ else: return lltype.nullptr(string_repr.lowleveltype.TO) -def ll_setstring(box, string): +def ll_setstring(RCBOX_STRBUF, box, string): if not string: new_c_data = lltype.nullptr(CCHARP.TO) - charscopy = lltype.nullptr(CHARSCOPY) + new_buf = lltype.nullptr(RCBOX_STRBUF) else: # XXX the copying of the string is often not needed, but it is # very hard to avoid in the general case of a moving GC that can # move 'string' around unpredictably. - n = len(string.chars) - buffer = llmemory.raw_malloc(NULL_HEADER + SIZEOF_CHAR * (n+1)) - charscopy = llmemory.cast_adr_to_ptr(buffer, PCHARSCOPY) - for i in range(n): - charscopy[i] = string.chars[i] - charscopy[n] = '\x00' - new_c_data = lltype.direct_arrayitems(charscopy) + new_buf = ll_stringbufnew(RCBOX_STRBUF, string) + new_c_data = lltype.direct_arrayitems(new_buf.c_data) # store a 'char *' pointer in the box.c_data box.c_data[0] = new_c_data # keep the ownership of the buffer in the box.keepalive field - prev = box.keepalive - box.keepalive = charscopy - llmemory.raw_free(llmemory.cast_ptr_to_adr(prev)) - -CHARSCOPY = lltype.Array(lltype.Char, hints={'nolength': True}) -PCHARSCOPY = lltype.Ptr(CHARSCOPY) -NULL_HEADER = llmemory.itemoffsetof(CHARSCOPY) -SIZEOF_CHAR = llmemory.sizeof(lltype.Char) + box.keepalive = new_buf Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Sat Sep 16 20:04:44 2006 @@ -174,6 +174,7 @@ return result def get_c_data(self, llops, v_box): + assert v_box.concretetype == self.lowleveltype inputargs = [v_box, inputconst(lltype.Void, "c_data")] return llops.genop('getfield', inputargs, lltype.Ptr(self.c_data_type)) @@ -248,6 +249,7 @@ Used when the data is returned from an operation or C function call. Special-cased in PrimitiveRepr. """ + assert v_c_data.concretetype.TO == self.c_data_type return self.allocate_instance_ref(llops, v_c_data, v_c_data_owner) @@ -289,6 +291,7 @@ return lltype.FixedSizeArray(ll_type, 1) def getvalue_from_c_data(self, llops, v_c_data): + assert v_c_data.concretetype.TO == self.c_data_type return llops.genop('getarrayitem', [v_c_data, C_ZERO], resulttype=self.ll_type) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rprimitive.py Sat Sep 16 20:04:44 2006 @@ -22,6 +22,7 @@ """Read out the atomic data from a raw C pointer. Used when the data is returned from an operation or C function call. """ + assert v_c_data.concretetype.TO == self.c_data_type v_value = self.getvalue_from_c_data(llops, v_c_data) return self.return_value(llops, v_value) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstringbuf.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstringbuf.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstringbuf.py Sat Sep 16 20:04:44 2006 @@ -1,4 +1,4 @@ -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.annotation.pairtype import pairtype from pypy.rpython.rmodel import IntegerRepr, inputconst from pypy.rpython.rctypes.rmodel import CTypesRefRepr @@ -128,4 +128,23 @@ newstr.chars[i] = p[i] return newstr +def ll_stringbufnew(RCBOX_STRBUF, s): + n = len(s.chars) + 1 + box = lltype.malloc(RCBOX_STRBUF) + box.header.rtti = lltype.getRuntimeTypeInfo(RCBOX_STRBUF) + box.c_data = lltype.nullptr(STRBUFTYPE) + # no flavored_malloc_varsize operation so far :-( + a = llmemory.raw_malloc(FIRST_CHAR + SIZEOF_CHAR * n) + # puf puf + (a + LENGTH_POS).signed[0] = n + p = llmemory.cast_adr_to_ptr(a, PSTRBUFTYPE) + box.c_data = p + for i in range(n): + p[i] = s.chars[i] + return box + STRBUFTYPE = lltype.Array(lltype.Char) +PSTRBUFTYPE = lltype.Ptr(STRBUFTYPE) +LENGTH_POS = llmemory.ArrayLengthOffset(STRBUFTYPE) +FIRST_CHAR = llmemory.itemoffsetof(STRBUFTYPE) +SIZEOF_CHAR = llmemory.sizeof(lltype.Char) Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rstruct.py Sat Sep 16 20:04:44 2006 @@ -104,7 +104,8 @@ v_c_data = self.get_c_data_of_field(hop.llops, v_struct, name) v_item = r_field.return_c_data(hop.llops, v_c_data, v_owner) # copy the keepalive information too - if hasattr(r_field.lowleveltype.TO, 'keepalive'): + if (v_item.concretetype == r_field.lowleveltype + and hasattr(r_field.lowleveltype.TO, 'keepalive')): c_name = inputconst(lltype.Void, cmangle(name)) copykeepalive(hop.llops, r_field.lowleveltype.TO.keepalive, v_struct, (c_name,), v_item, ()) From arigo at codespeak.net Sun Sep 17 10:32:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 10:32:51 +0200 (CEST) Subject: [pypy-svn] r32400 - pypy/dist/pypy/module/mmap/test Message-ID: <20060917083251.040A91006C@code0.codespeak.net> Author: arigo Date: Sun Sep 17 10:32:48 2006 New Revision: 32400 Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py Log: Using temporary filenames that are all one-character names, in the current directory, overwriting and deleting them all, looks quite dangerous to me! Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py ============================================================================== --- pypy/dist/pypy/module/mmap/test/test_mmap.py (original) +++ pypy/dist/pypy/module/mmap/test/test_mmap.py Sun Sep 17 10:32:48 2006 @@ -1,19 +1,12 @@ from pypy.conftest import gettestobjspace +from pypy.tool.udir import udir import os -def teardown_module(mod): - import string - for p in string.ascii_lowercase: - if os.path.exists(p): - try: - os.unlink(p) - except OSError: - print "Cannot delete '%s'" % p - class AppTestMMap: def setup_class(cls): space = gettestobjspace(usemodules=('mmap',)) cls.space = space + cls.w_tmpname = space.wrap(str(udir.join('mmap-'))) def test_page_size(self): import mmap @@ -65,7 +58,7 @@ skip("Only Unix checks file size") from mmap import mmap - f = open("a", "w+") + f = open(self.tmpname + "a", "w+") f.write("c") f.flush() @@ -74,7 +67,7 @@ def test_create(self): from mmap import mmap - f = open("b", "w+") + f = open(self.tmpname + "b", "w+") f.write("c") f.flush() @@ -85,7 +78,7 @@ def test_close(self): from mmap import mmap - f = open("c", "w+") + f = open(self.tmpname + "c", "w+") f.write("c") f.flush() @@ -95,7 +88,7 @@ def test_read_byte(self): from mmap import mmap - f = open("d", "w+") + f = open(self.tmpname + "d", "w+") f.write("c") f.flush() @@ -108,7 +101,7 @@ def test_readline(self): from mmap import mmap import os - f = open("e", "w+") + f = open(self.tmpname + "e", "w+") f.write("foo\n") f.flush() @@ -124,7 +117,7 @@ def test_read(self): from mmap import mmap - f = open("f", "w+") + f = open(self.tmpname + "f", "w+") f.write("foobar") f.flush() @@ -138,7 +131,7 @@ def test_find(self): from mmap import mmap - f = open("g", "w+") + f = open(self.tmpname + "g", "w+") f.write("foobar\0") f.flush() @@ -155,7 +148,7 @@ def test_is_modifiable(self): import mmap - f = open("h", "w+") + f = open(self.tmpname + "h", "w+") f.write("foobar") f.flush() @@ -167,7 +160,7 @@ def test_seek(self): from mmap import mmap - f = open("i", "w+") + f = open(self.tmpname + "i", "w+") f.write("foobar") f.flush() @@ -192,7 +185,7 @@ def test_write(self): import mmap - f = open("j", "w+") + f = open(self.tmpname + "j", "w+") f.write("foobar") f.flush() @@ -208,7 +201,7 @@ def test_write_byte(self): import mmap - f = open("k", "w+") + f = open(self.tmpname + "k", "w+") f.write("foobar") f.flush() @@ -224,7 +217,7 @@ def test_size(self): from mmap import mmap - f = open("l", "w+") + f = open(self.tmpname + "l", "w+") f.write("foobar") f.flush() @@ -235,7 +228,7 @@ def test_tell(self): from mmap import mmap - f = open("m", "w+") + f = open(self.tmpname + "m", "w+") f.write("c") f.flush() @@ -246,7 +239,7 @@ def test_flush(self): from mmap import mmap - f = open("n", "w+") + f = open(self.tmpname + "n", "w+") f.write("foobar") f.flush() @@ -260,7 +253,7 @@ def test_move(self): import mmap - f = open("o", "w+") + f = open(self.tmpname + "o", "w+") f.write("foobar") f.flush() @@ -287,7 +280,7 @@ import mmap import os - f = open("p", "w+") + f = open(self.tmpname + "p", "w+") f.write("foobar") f.flush() m = mmap.mmap(f.fileno(), 6, access=mmap.ACCESS_READ) @@ -306,7 +299,7 @@ def test_len(self): from mmap import mmap - f = open("q", "w+") + f = open(self.tmpname + "q", "w+") f.write("foobar") f.flush() @@ -318,7 +311,7 @@ def test_get_item(self): from mmap import mmap - f = open("r", "w+") + f = open(self.tmpname + "r", "w+") f.write("foobar") f.flush() @@ -337,7 +330,7 @@ def test_set_item(self): import mmap - f = open("s", "w+") + f = open(self.tmpname + "s", "w+") f.write("foobar") f.flush() @@ -372,7 +365,7 @@ def test_del_item(self): from mmap import mmap - f = open("t", "w+") + f = open(self.tmpname + "t", "w+") f.write("foobar") f.flush() @@ -389,7 +382,7 @@ def test_concatenation(self): from mmap import mmap - f = open("u", "w+") + f = open(self.tmpname + "u", "w+") f.write("foobar") f.flush() @@ -406,7 +399,7 @@ def test_repeatition(self): from mmap import mmap - f = open("v", "w+") + f = open(self.tmpname + "v", "w+") f.write("foobar") f.flush() @@ -432,7 +425,7 @@ import sys import os - filename = "w" + filename = self.tmpname + "w" f = open(filename, "w+") From arigo at codespeak.net Sun Sep 17 11:27:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 11:27:36 +0200 (CEST) Subject: [pypy-svn] r32401 - in pypy/dist/pypy/objspace/cpy: . test Message-ID: <20060917092736.9B7621006C@code0.codespeak.net> Author: arigo Date: Sun Sep 17 11:27:32 2006 New Revision: 32401 Modified: pypy/dist/pypy/objspace/cpy/function.py pypy/dist/pypy/objspace/cpy/test/test_function.py Log: Support for default arguments in the cpy objspace. Modified: pypy/dist/pypy/objspace/cpy/function.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/function.py (original) +++ pypy/dist/pypy/objspace/cpy/function.py Sun Sep 17 11:27:32 2006 @@ -146,6 +146,9 @@ trampoline.star_arg = tramp.star_arg trampoline.allow_someobjects = True # annotator hint trampoline._annspecialcase_ = "specialize:all_someobjects" + if func.defs_w: + trampoline.func_defaults = tuple([space.unwrap(w_x) + for w_x in func.defs_w]) w_result = W_Object(trampoline) space.wrap_cache[id(w_result)] = w_result, func, follow_annotations return w_result Modified: pypy/dist/pypy/objspace/cpy/test/test_function.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/test/test_function.py (original) +++ pypy/dist/pypy/objspace/cpy/test/test_function.py Sun Sep 17 11:27:32 2006 @@ -23,6 +23,10 @@ return space.wrap(result) entrypoint3.unwrap_spec = [ObjSpace, W_Root, 'args_w'] +def entrypoint4(space, x=21): + return space.wrap(x*2) +entrypoint4.unwrap_spec = [ObjSpace, int] + def test_builtin_function(): space = CPyObjSpace() @@ -99,3 +103,15 @@ res = fn() assert res == -400 + +def test_default_arg(): + space = CPyObjSpace() + func = interp2app(entrypoint4).__spacebind__(space) + bltin = BuiltinFunction(func) + w_entrypoint = space.wrap(bltin) + w_result = space.call_function(w_entrypoint) + result = space.int_w(w_result) + assert result == 42 + w_result = space.call_function(w_entrypoint, space.wrap(10)) + result = space.int_w(w_result) + assert result == 20 From arigo at codespeak.net Sun Sep 17 11:28:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 11:28:43 +0200 (CEST) Subject: [pypy-svn] r32402 - in pypy/dist/pypy: interpreter objspace/cpy Message-ID: <20060917092843.E6DEE1006C@code0.codespeak.net> Author: arigo Date: Sun Sep 17 11:28:41 2006 New Revision: 32402 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/cpy/objspace.py Log: A helper for mixedmodule implementors, to decode index and slice access for sequence-like objects. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sun Sep 17 11:28:41 2006 @@ -697,6 +697,32 @@ args = Arguments(self, list(posargs_w)) return self.call_args(w_func, args) + def decode_index(self, w_index_or_slice, seqlength): + """Helper for custom sequence implementations + -> (index, 0, 0) or + (start, stop, step) + """ + if self.is_true(self.isinstance(w_index_or_slice, self.w_slice)): + w_indices = self.call_method(w_index_or_slice, "indices", + self.wrap(seqlength)) + w_start, w_stop, w_step = self.unpackiterable(w_indices, 3) + start = self.int_w(w_start) + stop = self.int_w(w_stop) + step = self.int_w(w_step) + if step == 0: + raise OperationError(self.w_ValueError, + self.wrap("slice step cannot be zero")) + else: + start = self.int_w(w_index_or_slice) + if start < 0: + start += seqlength + if not (0 <= start < seqlength): + raise OperationError(self.w_IndexError, + self.wrap("index out of range")) + stop = 0 + step = 0 + return start, stop, step + class AppExecCache(SpaceCache): def build(cache, source): """ NOT_RPYTHON """ Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Sun Sep 17 11:28:41 2006 @@ -28,6 +28,7 @@ w_unicode = W_Object(unicode) w_type = W_Object(type) w_instance = W_Object(types.InstanceType) + w_slice = W_Object(slice) w_hex = W_Object(hex) # no C API function to do that :-( w_oct = W_Object(oct) From arigo at codespeak.net Sun Sep 17 12:12:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 12:12:51 +0200 (CEST) Subject: [pypy-svn] r32404 - pypy/dist/pypy/rpython/rctypes Message-ID: <20060917101251.C8F3A10071@code0.codespeak.net> Author: arigo Date: Sun Sep 17 12:12:50 2006 New Revision: 32404 Modified: pypy/dist/pypy/rpython/rctypes/apointer.py pypy/dist/pypy/rpython/rctypes/rarray.py pypy/dist/pypy/rpython/rctypes/rpointer.py Log: Arrays of length 0 are lots of fun. Modified: pypy/dist/pypy/rpython/rctypes/apointer.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/apointer.py (original) +++ pypy/dist/pypy/rpython/rctypes/apointer.py Sun Sep 17 12:12:50 2006 @@ -68,7 +68,9 @@ # POINTER(varsized_array_type): given that rctypes performs # no index checking, this pointer-to-array type is equivalent # to a pointer to an array of whatever size. - RESTYPE = POINTER(s_arg.ctype_array._type_ * 0) + # ('0' is a bad idea, though, as FixedSizeArrays of length 0 + # tend to say they have impossible items.) + RESTYPE = POINTER(s_arg.ctype_array._type_ * 1) else: # POINTER(constant_ctype) returns the constant annotation # corresponding to the POINTER(ctype). Modified: pypy/dist/pypy/rpython/rctypes/rarray.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/rarray.py (original) +++ pypy/dist/pypy/rpython/rctypes/rarray.py Sun Sep 17 12:12:50 2006 @@ -1,5 +1,6 @@ from ctypes import ARRAY, c_int -from pypy.rpython.lltypesystem.rstr import string_repr +from pypy.rpython.error import TyperError +from pypy.rpython.lltypesystem.rstr import string_repr, emptystr from pypy.rpython.rmodel import IntegerRepr, inputconst from pypy.rpython.rslice import AbstractSliceRepr from pypy.rpython.lltypesystem import lltype @@ -65,9 +66,12 @@ assert s_attr.is_constant() assert s_attr.const == 'value' assert self.r_item.ll_type == lltype.Char # .value: char arrays only - v_box = hop.inputarg(self, 0) hop.exception_cannot_occur() - return hop.gendirectcall(ll_chararrayvalue, v_box) + if self.length == 0: + return hop.inputconst(lltype.typeOf(emptystr), emptystr) + else: + v_box = hop.inputarg(self, 0) + return hop.gendirectcall(ll_chararrayvalue, v_box) def get_c_data_of_item(self, llops, v_array, v_index): v_c_array = self.get_c_data(llops, v_array) @@ -144,9 +148,12 @@ class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)): def rtype_getitem((r_array, r_slic), hop): rs = hop.rtyper.type_system.rslice + hop.exception_cannot_occur() if r_slic == rs.startstop_slice_repr: # slicing: char array only assert r_array.r_item.ll_type == lltype.Char + if r_array.length == 0: + return hop.inputconst(lltype.typeOf(emptystr), emptystr) v_array, v_slice = hop.inputargs(r_array, rs.startstop_slice_repr) return hop.gendirectcall(ll_chararrayslice, v_array, v_slice) raise TyperError('getitem does not support slices with %r' % (r_slic,)) Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/rpointer.py (original) +++ pypy/dist/pypy/rpython/rctypes/rpointer.py Sun Sep 17 12:12:50 2006 @@ -37,8 +37,8 @@ llops.genop('setfield', inputargs) def initialize_const(self, p, ptr): - if ptr is None: # passed as argument to functions expecting pointers - return + if not ptr: # NULL pointer, or literal None passed as argument to + return # functions expecting pointers llcontents = self.r_contents.convert_const(ptr.contents) p.c_data[0] = llcontents.c_data # the following line is probably pointless, as 'llcontents' will be From arigo at codespeak.net Sun Sep 17 12:17:30 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 12:17:30 +0200 (CEST) Subject: [pypy-svn] r32405 - in pypy/dist/pypy: annotation rpython/lltypesystem Message-ID: <20060917101730.E37BE10074@code0.codespeak.net> Author: arigo Date: Sun Sep 17 12:17:28 2006 New Revision: 32405 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/lltypesystem/lltype.py Log: Support for annotator-propagated length of FixedSizeArrays, and for no crashing on FixedSizeArrays of length 0. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sun Sep 17 12:17:28 2006 @@ -661,7 +661,11 @@ class __extend__(pairtype(SomePtr, SomeInteger)): def getitem((p, int1)): - v = p.ll_ptrtype._example()[0] + example = p.ll_ptrtype._example() + try: + v = example[0] + except IndexError: + return None # impossible value, e.g. FixedSizeArray(0) return ll_to_annotation(v) getitem.can_only_throw = [] @@ -784,24 +788,6 @@ pass def getitem((s_cto, s_index)): - if s_index.is_immutable_constant(): - # check that the constant index is valid, just because we - # are nice (users should really catch such errors by - # testing their programs!) - idx = s_index.const - knowntype = s_cto.knowntype - try: - length = knowntype._length_ - except AttributeError: - pass - else: - if idx < 0: - idx += length - if idx >= length: - raise IndexError( "invalid index" ) - elif idx < 0: - raise IndexError( "invalid index" ) - # Note: The following works for index either pointers and arrays, # because both have a _type_ attribute that contains the type of the # object pointed to or in the case of an array the element type. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sun Sep 17 12:17:28 2006 @@ -614,8 +614,11 @@ getattr.can_only_throw = [] def len(p): - len(p.ll_ptrtype._example()) # just doing checking - return SomeObject.len(p) + length = p.ll_ptrtype._example()._fixedlength() + if length is None: + return SomeObject.len(p) + else: + return immutablevalue(length) def setattr(p, s_attr, s_value): # just doing checking assert s_attr.is_constant(), "setattr on ptr %r with non-constant field-name" % p.ll_ptrtype Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sun Sep 17 12:17:28 2006 @@ -1051,6 +1051,13 @@ return self._obj.getlength() raise TypeError("%r instance is not an array" % (self._T,)) + def _fixedlength(self): + length = len(self) # always do this, for the checking + if isinstance(self._T, FixedSizeArray): + return length + else: + return None + def __iter__(self): # this is a work-around for the 'isrpystring' hack in __getitem__, # which otherwise causes list(p) to include the extra \x00 character. From arigo at codespeak.net Sun Sep 17 12:18:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 12:18:25 +0200 (CEST) Subject: [pypy-svn] r32406 - in pypy/dist/pypy/module/mmap: . test Message-ID: <20060917101825.B7C0210074@code0.codespeak.net> Author: arigo Date: Sun Sep 17 12:18:24 2006 New Revision: 32406 Added: pypy/dist/pypy/module/mmap/test/test_mixedmodule.py (contents, props changed) Modified: pypy/dist/pypy/module/mmap/__init__.py pypy/dist/pypy/module/mmap/interp_mmap.py pypy/dist/pypy/module/mmap/test/test_mmap.py Log: Finished the mmap review; added cpyobjspace and compilation tests. I have no clue if it works or compile on Windows. Modified: pypy/dist/pypy/module/mmap/__init__.py ============================================================================== --- pypy/dist/pypy/module/mmap/__init__.py (original) +++ pypy/dist/pypy/module/mmap/__init__.py Sun Sep 17 12:18:24 2006 @@ -2,7 +2,7 @@ class Module(MixedModule): interpleveldefs = { - 'PAGESIZE': 'interp_mmap.PAGESIZE', + 'PAGESIZE': 'space.wrap(interp_mmap.PAGESIZE)', 'mmap': 'interp_mmap.mmap' } @@ -14,19 +14,9 @@ } def buildloaders(cls): - import py # REVIEWME - py.test.skip("The mmap module is not ready: many methods do far too " - "much copying, and it uses 'pythonapi', which makes it " - "not translatable.") - from pypy.module.mmap import interp_mmap - import os - - Module.interpleveldefs["PAGESIZE"] = 'space.wrap(%r)' %\ - interp_mmap._get_page_size() - - if os.name == "posix": - for constant, value in interp_mmap.constants.iteritems(): + for constant, value in interp_mmap.constants.iteritems(): + if isinstance(value, int): Module.interpleveldefs[constant] = "space.wrap(%r)" % value super(Module, cls).buildloaders() Modified: pypy/dist/pypy/module/mmap/interp_mmap.py ============================================================================== --- pypy/dist/pypy/module/mmap/interp_mmap.py (original) +++ pypy/dist/pypy/module/mmap/interp_mmap.py Sun Sep 17 12:18:24 2006 @@ -29,11 +29,22 @@ # constants, look in sys/mman.h and platform docs for the meaning # some constants are linux only so they will be correctly exposed outside # depending on the OS - constant_names = ['MAP_SHARED', 'MAP_PRIVATE', 'MAP_ANON', 'MAP_ANONYMOUS', - 'PROT_READ', 'PROT_WRITE', 'PROT_EXEC', 'MAP_DENYWRITE', 'MAP_EXECUTABLE', + constant_names = ['MAP_SHARED', 'MAP_PRIVATE', + 'PROT_READ', 'PROT_WRITE', 'MS_SYNC'] + opt_constant_names = ['MAP_ANON', 'MAP_ANONYMOUS', + 'PROT_EXEC', + 'MAP_DENYWRITE', 'MAP_EXECUTABLE'] for name in constant_names: + setattr(CConfig, name, ctypes_platform.ConstantInteger(name)) + for name in opt_constant_names: setattr(CConfig, name, ctypes_platform.DefinedConstantInteger(name)) + + has_mremap = hasattr(libc, "mremap") + if has_mremap: + CConfig.MREMAP_MAYMOVE = ( + ctypes_platform.DefinedConstantInteger("MREMAP_MAYMOVE")) + elif _MS_WINDOWS: CConfig._includes_ += ("windows.h",) constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY', @@ -41,23 +52,16 @@ 'DUPLICATE_SAME_ACCESS'] for name in constant_names: setattr(CConfig, name, ctypes_platform.ConstantInteger(name)) - -class cConfig: - pass - -cConfig.__dict__.update(ctypes_platform.configure(CConfig)) -# needed to export the constants inside and outside. see __init__.py -for name in constant_names: - value = getattr(cConfig, name) - if value is not None: - constants[name] = value +# export the constants inside and outside. see __init__.py +constants.update(ctypes_platform.configure(CConfig)) if _POSIX: # MAP_ANONYMOUS is not always present but it's always available at CPython level - if cConfig.MAP_ANONYMOUS is None: - cConfig.MAP_ANONYMOUS = cConfig.MAP_ANON - constants["MAP_ANONYMOUS"] = cConfig.MAP_ANON + if constants["MAP_ANONYMOUS"] is None: + constants["MAP_ANONYMOUS"] = constants["MAP_ANON"] + assert constants["MAP_ANONYMOUS"] is not None + constants["MAP_ANON"] = constants["MAP_ANONYMOUS"] locals().update(constants) @@ -66,17 +70,13 @@ PTR = POINTER(c_char) # cannot use c_void_p as return value of functions :-( -size_t = cConfig.size_t -off_t = cConfig.off_t -libc.strerror.restype = c_char_p -libc.strerror.argtypes = [c_int] +memmove_ = libc.memmove +memmove_.argtypes = [PTR, PTR, size_t] if _POSIX: libc.mmap.argtypes = [PTR, size_t, c_int, c_int, c_int, off_t] libc.mmap.restype = PTR libc.mmap.includes = ("sys/mman.h",) - libc.close.argtypes = [c_int] - libc.close.restype = c_int libc.munmap.argtypes = [PTR, size_t] libc.munmap.restype = c_int libc.munmap.includes = ("sys/mman.h",) @@ -84,21 +84,17 @@ libc.msync.restype = c_int libc.msync.includes = ("sys/mman.h",) - has_mremap = False - if hasattr(libc, "mremap"): + if has_mremap: libc.mremap.argtypes = [PTR, size_t, size_t, c_ulong] libc.mremap.restype = PTR libc.mremap.includes = ("sys/mman.h",) - has_mremap = True - libc.ftruncate.argtypes = [c_int, off_t] - libc.ftruncate.restype = c_int def _get_page_size(): return libc.getpagesize() def _get_error_msg(): errno = geterrno() - return libc.strerror(errno) + return os.strerror(errno) elif _MS_WINDOWS: from ctypes import wintypes @@ -188,16 +184,19 @@ space.wrap(_get_error_msg(dwErr))) return low.value, high.value - def _get_error_msg(errno=0): - if not errno: - errno = GetLastError() - return libc.strerror(errno) + def _get_error_msg(): + errno = GetLastError() + return os.strerror(errno) PAGESIZE = _get_page_size() NULL = PTR() +EMPTY_DATA = (c_char * 0)() +NODATA = cast(pointer(EMPTY_DATA), PTR) # ____________________________________________________________ +# XXX the methods should take unsigned int arguments instead of int + class W_MMap(Wrappable): def __init__(self, space, access): self.space = space @@ -213,9 +212,6 @@ self.fd = -1 self.closed = False -## def to_str(self): -## return "".join([self.data[i] for i in range(self.size)]) - def check_valid(self): if _MS_WINDOWS: to_close = self.map_handle.value == INVALID_c_int_VALUE @@ -239,15 +235,16 @@ def setdata(self, data, size): """Set the internal data and map size from a PTR.""" + assert size >= 0 arraytype = c_char * size - self.data = cast(data, POINTER(arraytype)) + self.data = cast(data, POINTER(arraytype)).contents self.size = size def close(self): if _MS_WINDOWS: - if self.data: + if self.size > 0: self.unmapview() - self.setdata(NULL, 0) + self.setdata(NODATA, 0) if self.map_handle.value != INVALID_c_int_VALUE: CloseHandle(self.map_handle) self.map_handle.value = INVALID_c_int_VALUE @@ -257,16 +254,15 @@ elif _POSIX: self.closed = True if self.fd != -1: - libc.close(self.fd) + os.close(self.fd) self.fd = -1 - if self.data: - libc.munmap(self.data, self.size) - self.setdata(NULL, 0) + if self.size > 0: + libc.munmap(self.getptr(0), self.size) + self.setdata(NODATA, 0) close.unwrap_spec = ['self'] def unmapview(self): - data = cast(self.data, PTR) - UnmapViewOfFile(data) + UnmapViewOfFile(self.getptr(0)) def read_byte(self): self.check_valid() @@ -283,14 +279,15 @@ def readline(self): self.check_valid() + data = self.data for pos in xrange(self.pos, self.size): - if self.data[pos] == '\n': + if data[pos] == '\n': eol = pos + 1 # we're interested in the position after new line break else: # no '\n' found eol = self.size - res = self.data[self.pos:eol] + res = data[self.pos:eol] self.pos += len(res) return self.space.wrap(res) readline.unwrap_spec = ['self'] @@ -321,7 +318,7 @@ if start < 0: start = 0 data = self.data - for p in xrange(start, self.size): + for p in xrange(start, self.size - len(tofind) + 1): for q in range(len(tofind)): if data[p+q] != tofind[q]: break # position 'p' is not a match @@ -361,7 +358,7 @@ return self.space.wrap(self.pos) tell.unwrap_spec = ['self'] - def size(self): + def descr_size(self): self.check_valid() size = self.size @@ -374,8 +371,12 @@ elif _POSIX: st = os.fstat(self.fd) size = st[stat.ST_SIZE] + if size > sys.maxint: + size = sys.maxint + else: + size = int(size) return self.space.wrap(size) - size.unwrap_spec = ['self'] + descr_size.unwrap_spec = ['self'] def write(self, data): self.check_valid() @@ -396,15 +397,24 @@ def write_byte(self, byte): self.check_valid() - if len(byte) > 1: + if len(byte) != 1: raise OperationError(self.space.w_TypeError, self.space.wrap("write_byte() argument must be char")) self.check_writeable() - self.data[self.pos] = byte + self.data[self.pos] = byte[0] self.pos += 1 write_byte.unwrap_spec = ['self', str] - + + def getptr(self, offset): + if offset > 0: + # XXX 64-bit support for pointer arithmetic! + dataptr = cast(pointer(self.data), c_void_p) + dataptr = c_void_p(dataptr.value + offset) + return cast(dataptr, PTR) + else: + return cast(pointer(self.data), PTR) + def flush(self, offset=0, size=0): self.check_valid() @@ -414,11 +424,7 @@ raise OperationError(self.space.w_ValueError, self.space.wrap("flush values out of range")) else: - # XXX 64-bit support for pointer arithmetic! - start = cast(self.data, c_void_p) - if offset > 0: - start = c_void_p(start.value + offset) - start = cast(start, PTR) + start = self.getptr(offset) if _MS_WINDOWS: res = FlushViewOfFile(start, size) return self.space.wrap(res) @@ -445,22 +451,14 @@ self.check_writeable() # check boundings - assert src >= 0; assert dest >= 0; assert count >= 0; assert self.size >= 0 - if (src + count > self.size) or (dest + count > self.size): + if (src < 0 or dest < 0 or count < 0 or + src + count > self.size or dest + count > self.size): raise OperationError(self.space.w_ValueError, self.space.wrap("source or destination out of range")) - XXXXXXX - data_dest = c_char_p("".join([self.data[i] for i in range(dest, self.size)])) - data_src = c_char_p("".join([self.data[i] for i in range(src, src+count)])) - libc.memmove XXX (data_dest, data_src, size_t(count)) - - assert dest >= 0 - str_left = self.space.str_w(self.to_str())[0:dest] - final_str = "%s%s" % (str_left, data_dest.value) - - p = c_char_p(final_str) - libc.memcpy(self.data, p, len(final_str)) + datasrc = self.getptr(src) + datadest = self.getptr(dest) + memmove_(datadest, datasrc, count) move.unwrap_spec = ['self', int, int, int] def resize(self, newsize): @@ -475,15 +473,16 @@ self.space.wrap(msg)) # resize the underlying file first - res = libc.ftruncate(self.fd, newsize) - if res == -1: + try: + os.ftruncate(self.fd, newsize) + except OSError, e: raise OperationError(self.space.w_EnvironmentError, - self.space.wrap(_get_error_msg())) + self.space.wrap(os.strerror(e.errno))) # now resize the mmap - MREMAP_MAYMOVE = 1 - libc.mremap(self.data, self.size, newsize, MREMAP_MAYMOVE) - self.size = newsize + newdata = libc.mremap(self.getptr(0), self.size, newsize, + MREMAP_MAYMOVE or 0) + self.setdata(newdata, newsize) elif _MS_WINDOWS: # disconnect the mapping self.unmapview() @@ -520,7 +519,7 @@ dwErrCode = GetLastError() raise OperationError(self.space.w_EnvironmentError, - self.space.wrap(_get_error_msg(dwErrCode))) + self.space.wrap(os.strerror(dwErrCode))) resize.unwrap_spec = ['self', int] def __len__(self): @@ -529,65 +528,50 @@ return self.space.wrap(self.size) __len__.unwrap_spec = ['self'] - def __getitem__(self, index): + def descr_getitem(self, w_index): self.check_valid() - # XXX this does not support slice() instances + space = self.space + start, stop, step = space.decode_index(w_index, self.size) + if step == 0: # index only + return space.wrap(self.data[start]) + elif step == 1: + if 0 <= start <= stop: + res = self.data[start:stop] + else: + res = '' + return space.wrap(res) + else: + raise OperationError(space.w_ValueError, + space.wrap("mmap object does not support slicing with a step")) + descr_getitem.unwrap_spec = ['self', W_Root] - try: - return self.space.wrap(self.space.str_w(self.to_str())[index]) - except IndexError: - raise OperationError(self.space.w_IndexError, - self.space.wrap("mmap index out of range")) - __getitem__.unwrap_spec = ['self', int] - - def __setitem__(self, index, value): + def descr_setitem(self, w_index, value): self.check_valid() - self.check_writeable() - - # XXX this does not support slice() instances - - if len(value) != 1: - raise OperationError(self.space.w_IndexError, - self.space.wrap("mmap assignment must be single-character string")) - str_data = "" - try: - str_data = self.space.str_w(self.to_str()) - str_data_lst = [i for i in str_data] - str_data_lst[index] = value - str_data = "".join(str_data_lst) - except IndexError: - raise OperationError(self.space.w_IndexError, - self.space.wrap("mmap index out of range")) + self.check_writeable() - XXXXXXXXXX - p = c_char_p(str_data) - libc.memcpy(self.data, p, len(str_data)) - __setitem__.unwrap_spec = ['self', int, str] - - def __delitem__(self, index): - self.check_valid() - - # XXX this does not support slice() instances (does it matter?) - - raise OperationError(self.space.w_TypeError, - self.space.wrap("mmap object doesn't support item deletion")) - __delitem__.unwrap_spec = ['self', int] - - def __add__(self, w_other): - self.check_valid() - - raise OperationError(self.space.w_SystemError, - self.space.wrap("mmaps don't support concatenation")) - __add__.unwrap_spec = ['self', W_Root] - - def __mul__(self, w_other): - self.check_valid() - - raise OperationError(self.space.w_SystemError, - self.space.wrap("mmaps don't support repeat operation")) - __mul__.unwrap_spec = ['self', W_Root] + space = self.space + start, stop, step = space.decode_index(w_index, self.size) + if step == 0: # index only + if len(value) != 1: + raise OperationError(space.w_ValueError, + space.wrap("mmap assignment must be " + "single-character string")) + self.data[start] = value[0] + elif step == 1: + length = stop - start + if start < 0 or length < 0: + length = 0 + if len(value) != length: + raise OperationError(space.w_ValueError, + space.wrap("mmap slice assignment is wrong size")) + for i in range(length): + self.data[start + i] = value[i] + else: + raise OperationError(space.w_ValueError, + space.wrap("mmap object does not support slicing with a step")) + descr_setitem.unwrap_spec = ['self', W_Root, str] W_MMap.typedef = TypeDef("mmap", @@ -598,7 +582,7 @@ find = interp2app(W_MMap.find), seek = interp2app(W_MMap.seek), tell = interp2app(W_MMap.tell), - size = interp2app(W_MMap.size), + size = interp2app(W_MMap.descr_size), write = interp2app(W_MMap.write), write_byte = interp2app(W_MMap.write_byte), flush = interp2app(W_MMap.flush), @@ -606,11 +590,8 @@ resize = interp2app(W_MMap.resize), __len__ = interp2app(W_MMap.__len__), - __getitem__ = interp2app(W_MMap.__getitem__), - __setitem__ = interp2app(W_MMap.__setitem__), - __delitem__ = interp2app(W_MMap.__delitem__), - __add__ = interp2app(W_MMap.__add__), - __mul__ = interp2app(W_MMap.__mul__), + __getitem__ = interp2app(W_MMap.descr_getitem), + __setitem__ = interp2app(W_MMap.descr_setitem), ) def _check_map_size(space, size): @@ -660,6 +641,10 @@ else: mode = st[stat.ST_MODE] size = st[stat.ST_SIZE] + if size > sys.maxint: + size = sys.maxint + else: + size = int(size) if stat.S_ISREG(mode): if map_size == 0: map_size = size @@ -677,7 +662,11 @@ flags |= MAP_ANONYMOUS else: - m.fd = os.dup(fd) + try: + m.fd = os.dup(fd) + except OSError, e: + raise OperationError(space.w_EnvironmentError, + space.wrap(os.strerror(e.errno))) res = libc.mmap(NULL, map_size, prot, flags, fd, 0) if cast(res, c_void_p).value == -1: @@ -778,5 +767,5 @@ dwErr = GetLastError() raise OperationError(space.w_EnvironmentError, - space.wrap(_get_error_msg(dwErr))) + space.wrap(os.strerror(dwErr))) mmap.unwrap_spec = [ObjSpace, int, int, str, int] Added: pypy/dist/pypy/module/mmap/test/test_mixedmodule.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/mmap/test/test_mixedmodule.py Sun Sep 17 12:18:24 2006 @@ -0,0 +1,194 @@ +""" +Test the compilation of the mmap mixedmodule to a CPython extension +module. +""" + +from pypy.interpreter.mixedmodule import testmodule, compilemodule +from pypy.tool.udir import udir +import sys +import os + + +def test_cpy(): + run_tests(testmodule("mmap")) + +def test_compiled(): + run_tests(compilemodule("mmap")) + + +def run_tests(mmap): + # this is a global test, ported from test_mmap.py + PAGESIZE = mmap.PAGESIZE + + filename = str(udir.join('mmap-mixedmodule')) + + f = open(filename, "w+") + + # write 2 pages worth of data to the file + f.write('\0' * PAGESIZE) + f.write('foo') + f.write('\0' * (PAGESIZE - 3)) + f.flush() + m = mmap.mmap(f.fileno(), 2 * PAGESIZE) + f.close() + + # sanity checks + assert m.find("foo") == PAGESIZE + assert len(m) == 2 * PAGESIZE + assert m[0] == '\0' + # assert m[0:3] == '\0\0\0' + + # modify the file's content + m[0] = '3' + # m[PAGESIZE+3:PAGESIZE+3+3] = 'bar' + + # check that the modification worked + assert m[0] == '3' + # assert m[0:3] == '3\0\0' + # assert m[PAGESIZE-1:PAGESIZE+7] == '\0foobar\0' + + m.flush() + + # test seeking around + m.seek(0,0) + assert m.tell() == 0 + m.seek(42, 1) + assert m.tell() == 42 + m.seek(0, 2) + assert m.tell() == len(m) + + raises(ValueError, m.seek, -1) + raises(ValueError, m.seek, 1, 2) + raises(ValueError, m.seek, -len(m) - 1, 2) + + # try resizing map + if not (("darwin" in sys.platform) or ("freebsd" in sys.platform)): + m.resize(512) + + assert len(m) == 512 + raises(ValueError, m.seek, 513, 0) + + # check that the underlying file is truncated too + f = open(filename) + f.seek(0, 2) + assert f.tell() == 512 + f.close() + assert m.size() == 512 + + m.close() + f.close() + + # test access=ACCESS_READ + mapsize = 10 + open(filename, "wb").write("a" * mapsize) + f = open(filename, "rb") + m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ) + # assert m[:] == 'a' * mapsize + # def f(m): m[:] = 'b' * mapsize + # py.test.raises(TypeError, f, m) + def fn(): m[0] = 'b' + raises(TypeError, fn) + def fn(m): m.seek(0, 0); m.write("abc") + raises(TypeError, fn, m) + def fn(m): m.seek(0, 0); m.write_byte("d") + raises(TypeError, fn, m) + if not (("darwin" in sys.platform) or ("freebsd" in sys.platform)): + raises(TypeError, m.resize, 2 * mapsize) + assert open(filename, "rb").read() == 'a' * mapsize + + # opening with size too big + f = open(filename, "r+b") + if not os.name == "nt": + # this should work under windows + raises(ValueError, mmap.mmap, f.fileno(), mapsize + 1) + f.close() + + # if _MS_WINDOWS: + # # repair damage from the resizing test. + # f = open(filename, 'r+b') + # f.truncate(mapsize) + # f.close() + m.close() + + # test access=ACCESS_WRITE" + f = open(filename, "r+b") + m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE) + m.write('c' * mapsize) + m.seek(0) + data = m.read(mapsize) + assert data == 'c' * mapsize + m.flush() + m.close() + f.close() + f = open(filename, 'rb') + stuff = f.read() + f.close() + assert stuff == 'c' * mapsize + + # test access=ACCESS_COPY + f = open(filename, "r+b") + m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY) + m.write('d' * mapsize) + m.seek(0) + data = m.read(mapsize) + assert data == 'd' * mapsize + m.flush() + assert open(filename, "rb").read() == 'c' * mapsize + if not (("darwin" in sys.platform) or ("freebsd" in sys.platform)): + raises(TypeError, m.resize, 2 * mapsize) + m.close() + f.close() + + # test invalid access + f = open(filename, "r+b") + raises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4) + f.close() + + # test incompatible parameters + if os.name == "posix": + f = open(filename, "r+b") + raises(ValueError, mmap.mmap, f.fileno(), mapsize, flags=mmap.MAP_PRIVATE, + prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE) + f.close() + + + # bad file descriptor + raises(EnvironmentError, mmap.mmap, -2, 4096) + + # do a tougher .find() test. SF bug 515943 pointed out that, in 2.2, + # searching for data with embedded \0 bytes didn't work. + f = open(filename, 'w+') + data = 'aabaac\x00deef\x00\x00aa\x00' + n = len(data) + f.write(data) + f.flush() + m = mmap.mmap(f.fileno(), n) + f.close() + + for start in range(n + 1): + for finish in range(start, n + 1): + sl = data[start:finish] + assert m.find(sl) == data.find(sl) + assert m.find(sl + 'x') == -1 + m.close() + + # test mapping of entire file by passing 0 for map length + f = open(filename, "w+") + f.write(2**16 * 'm') + f.close() + f = open(filename, "rb+") + m = mmap.mmap(f.fileno(), 0) + assert len(m) == 2**16 + assert m.read(2**16) == 2**16 * "m" + m.close() + f.close() + + # make move works everywhere (64-bit format problem earlier) + f = open(filename, 'w+') + f.write("ABCDEabcde") + f.flush() + m = mmap.mmap(f.fileno(), 10) + m.move(5, 0, 5) + assert m.read(10) == "ABCDEABCDE" + m.close() + f.close() Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py ============================================================================== --- pypy/dist/pypy/module/mmap/test/test_mmap.py (original) +++ pypy/dist/pypy/module/mmap/test/test_mmap.py Sun Sep 17 12:18:24 2006 @@ -43,7 +43,7 @@ raises(TypeError, mmap, 0, 1, 2, 3, "foo", 5) raises(TypeError, mmap, 0, 1, foo="foo") raises(TypeError, mmap, 0, -1) - raises(OverflowError, mmap, 0, sys.maxint) + raises(OverflowError, mmap, 0, sys.maxint ** 3) raises(ValueError, mmap, 0, 1, flags=2, access=3) raises(ValueError, mmap, 0, 1, access=123) elif os.name == "nt": @@ -72,7 +72,7 @@ f.write("c") f.flush() m = mmap(f.fileno(), 1) - assert m._to_str() == "c" + assert m.read(99) == "c" f.close() @@ -84,7 +84,7 @@ f.flush() m = mmap(f.fileno(), 1) m.close() - raises(ValueError, m._check_valid) + raises(ValueError, m.read, 1) def test_read_byte(self): from mmap import mmap @@ -153,8 +153,8 @@ f.write("foobar") f.flush() m = mmap.mmap(f.fileno(), 6, access=mmap.ACCESS_READ) - raises(TypeError, m._check_writeable) - raises(TypeError, m._check_resizeable) + raises(TypeError, m.write, 'x') + raises(TypeError, m.resize, 7) m.close() f.close() @@ -343,7 +343,8 @@ def fn(): m[-7] = 'a' raises(IndexError, fn) def fn(): m[0] = 'ab' - raises(IndexError, fn) + raises((IndexError, ValueError), fn) # IndexError is in CPython, + # but doesn't make much sense # def f(m): m[1:3] = u'xx' # py.test.raises(IndexError, f, m) # def f(m): m[1:4] = "zz" @@ -388,9 +389,9 @@ m = mmap(f.fileno(), 6) def fn(): m + 1 - raises(SystemError, fn) - def fn(m): m += 1 - raises(SystemError, fn, m) + raises((SystemError, TypeError), fn) # SystemError is in CPython, + def fn(m): m += 1 # but it doesn't make much + raises((SystemError, TypeError), fn, m) # sense def fn(): 1 + m raises(TypeError, fn) m.close() @@ -405,10 +406,10 @@ m = mmap(f.fileno(), 6) def fn(): m * 1 - raises(SystemError, fn) - def fn(m): m *= 1 - raises(SystemError, fn, m) - def fn(): 1 * m + raises((SystemError, TypeError), fn) # SystemError is in CPython, + def fn(m): m *= 1 # but it + raises((SystemError, TypeError), fn, m) # doesn't + def fn(): 1 * m # make much sense raises(TypeError, fn) m.close() f.close() From arigo at codespeak.net Sun Sep 17 13:30:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 13:30:13 +0200 (CEST) Subject: [pypy-svn] r32408 - in pypy/dist/pypy/module/rctime: . test Message-ID: <20060917113013.E35A21006C@code0.codespeak.net> Author: arigo Date: Sun Sep 17 13:30:12 2006 New Revision: 32408 Modified: pypy/dist/pypy/module/rctime/__init__.py pypy/dist/pypy/module/rctime/app_time.py pypy/dist/pypy/module/rctime/interp_time.py pypy/dist/pypy/module/rctime/test/test_rctime.py Log: Streamlining of the rctime module. Export it under the app-level name 'time', too. Modified: pypy/dist/pypy/module/rctime/__init__.py ============================================================================== --- pypy/dist/pypy/module/rctime/__init__.py (original) +++ pypy/dist/pypy/module/rctime/__init__.py Sun Sep 17 13:30:12 2006 @@ -2,6 +2,8 @@ from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): + applevel_name = 'time' + interpleveldefs = { 'accept2dyear': 'interp_time.accept2dyear', 'timezone': 'interp_time.timezone', @@ -19,12 +21,6 @@ } def buildloaders(cls): - import py # REVIEWME - py.test.skip("The rctime module is not ready: the checks on the input " - "arguments are incomplete; strftime() can eat all your " - "memory in error conditions; the use of math.fmod() " - "should be removed.") - from pypy.module.rctime import interp_time import os @@ -50,7 +46,6 @@ buildloaders = classmethod(buildloaders) appleveldefs = { - '_check_float': 'app_time._check_float', 'struct_time': 'app_time.struct_time', '__doc__': 'app_time.__doc__', 'strptime': 'app_time.strptime', Modified: pypy/dist/pypy/module/rctime/app_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/app_time.py (original) +++ pypy/dist/pypy/module/rctime/app_time.py Sun Sep 17 13:30:12 2006 @@ -4,10 +4,8 @@ class struct_time(object): def __init__(self, tup): - if tup and len(tup) < 9: + if len(tup) != 9: raise TypeError, "time.struct_time() takes a 9-sequence" - if not tup: - raise TypeError, "time.struct_time() takes at least 1 argument (0 given)" self._tup = tup self.tm_year = self._tup[0] @@ -40,26 +38,17 @@ return cmp(self._tup, other) -def _check_float(arg): - try: - float(arg) - except ValueError: - raise TypeError, "a float is required" - if _POSIX: - def _float_sleep(secs): - import select - select.select([], [], [], secs) - + from select import select + def sleep(secs): """sleep(seconds) Delay execution for a given number of seconds. The argument may be a floating point number for subsecond precision.""" - _check_float(secs) - _float_sleep(secs) + select([], [], [], secs) + - def strptime(string, format="%a %b %d %H:%M:%S %Y"): """strptime(string, format) -> struct_time @@ -67,7 +56,7 @@ See the library reference manual for formatting codes (same as strftime()).""" - import _strptime + import _strptime # from the CPython standard library return _strptime.strptime(string, format) __doc__ = """This module provides various functions to manipulate time values. Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Sun Sep 17 13:30:12 2006 @@ -63,7 +63,6 @@ libc.gettimeofday.argtypes = [c_void_p, c_void_p] libc.gettimeofday.restype = c_int has_gettimeofday = True -libc.strerror.restype = c_char_p libc.clock.restype = clock_t libc.time.argtypes = [POINTER(time_t)] libc.time.restype = time_t @@ -81,7 +80,7 @@ libc.tzset.restype = None # tzset() returns void elif _WIN: QueryPerformanceCounter = windll.kernel32.QueryPerformanceCounter - QueryPerformanceCounter.argtypes = [POINTER(c_int)] + QueryPerformanceCounter.argtypes = [POINTER(LARGE_INTEGER)] QueryPerformanceCounter.restype = BOOL Sleep = windll.kernel32.Sleep Sleep.argtypes = [DWORD] @@ -140,7 +139,7 @@ def _get_error_msg(): errno = geterrno() - return libc.strerror(errno) + return os.strerror(errno) def _floattime(): """ _floattime() -> computes time since the Epoch for various platforms. @@ -153,13 +152,12 @@ time() has a resolution in seconds """ - if _WIN: - return float(libc.time(None)) if has_gettimeofday: t = timeval() if libc.gettimeofday(byref(t), c_void_p(None)) == 0: return float(t.tv_sec) + t.tv_usec * 0.000001 - return 0.0 + + return float(libc.time(None)) # elif hasattr(_libc, "ftime"): # t = _timeb() @@ -173,14 +171,6 @@ # return t.value if _WIN: - def _float_sleep(space, secs): - msecs = secs * 1000.0 - if msecs > float(sys.maxint * 2 - 1): # ULONG_MAX - raise OperationError(space.w_OverflowError, - space.wrap("sleep length is too large")) - ul_millis = c_ulong(int(msecs)) - Sleep(ul_millis) - def sleep(space, w_secs): """sleep(seconds) @@ -188,36 +178,33 @@ a floating point number for subsecond precision.""" secs = space.float_w(w_secs) - _check_float(space, secs) - _float_sleep(space, secs) + if secs < 0.0: + secs = 0.0 + msecs = secs * 1000.0 + try: + msecs = int(msecs) + except OverflowError: + raise OperationError(space.w_OverflowError, + space.wrap("sleep length is too large")) + ul_millis = c_ulong(msecs) + Sleep(ul_millis) -def _check_float(space, seconds): - # this call the app level _check_float to check the type of - # the given seconds - w_check_float = _get_module_object(space, "_check_float") - space.call_function(w_check_float, space.wrap(seconds)) - def _get_module_object(space, obj_name): - w_module = space.getbuiltinmodule('rctime') + w_module = space.getbuiltinmodule('time') w_obj = space.getattr(w_module, space.wrap(obj_name)) return w_obj -def _set_module_object(space, obj_name, obj_value): - w_module = space.getbuiltinmodule('rctime') - space.setattr(w_module, space.wrap(obj_name), space.wrap(obj_value)) - -# duplicated function to make the annotator work correctly -def _set_module_list_object(space, list_name, list_value): - w_module = space.getbuiltinmodule('rctime') - space.setattr(w_module, space.wrap(list_name), space.newlist(list_value)) +def _set_module_object(space, obj_name, w_obj_value): + w_module = space.getbuiltinmodule('time') + space.setattr(w_module, space.wrap(obj_name), w_obj_value) def _get_floattime(space, w_seconds): - # this check is done because None will be automatically wrapped + # w_seconds can be a wrapped None (it will be automatically wrapped + # in the callers, so we never get a real None here). if space.is_w(w_seconds, space.w_None): seconds = _floattime() else: seconds = space.float_w(w_seconds) - _check_float(space, seconds) return seconds def _tm_to_tuple(space, t): @@ -237,16 +224,32 @@ w_time_tuple = space.newtuple(time_tuple) return space.call_function(w_struct_time, w_time_tuple) -def _gettmarg(space, w_tup, buf): - y = space.int_w(w_tup[0]) - buf.tm_mon = space.int_w(w_tup[1]) - buf.tm_mday = space.int_w(w_tup[2]) - buf.tm_hour = space.int_w(w_tup[3]) - buf.tm_min = space.int_w(w_tup[4]) - buf.tm_sec = space.int_w(w_tup[5]) - buf.tm_wday = space.int_w(w_tup[6]) - buf.tm_yday = space.int_w(w_tup[7]) - buf.tm_isdst = space.int_w(w_tup[8]) +def _gettmarg(space, w_tup, allowNone=True): + if allowNone and space.is_w(w_tup, space.w_None): + # default to the current local time + tt = time_t(int(_floattime())) + pbuf = libc.localtime(byref(tt)) + if not pbuf: + raise OperationError(space.w_ValueError, + space.wrap(_get_error_msg())) + return pbuf.contents + + tup_w = space.unpackiterable(w_tup) + if len(tup_w) != 9: + raise OperationError(space.w_TypeError, + space.wrap("argument must be sequence of " + "length 9, not %d" % len(tup_w))) + + buf = tm() + y = space.int_w(tup_w[0]) + buf.tm_mon = space.int_w(tup_w[1]) + buf.tm_mday = space.int_w(tup_w[2]) + buf.tm_hour = space.int_w(tup_w[3]) + buf.tm_min = space.int_w(tup_w[4]) + buf.tm_sec = space.int_w(tup_w[5]) + buf.tm_wday = space.int_w(tup_w[6]) + buf.tm_yday = space.int_w(tup_w[7]) + buf.tm_isdst = space.int_w(tup_w[8]) w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) @@ -264,9 +267,13 @@ raise OperationError(space.w_ValueError, space.wrap("year out of range")) + if buf.tm_wday < 0: + raise OperationError(space.w_ValueError, + space.wrap("day of week out of range")) + buf.tm_year = y - 1900 buf.tm_mon = buf.tm_mon - 1 - buf.tm_wday = int(math.fmod((buf.tm_wday + 1), 7)) + buf.tm_wday = (buf.tm_wday + 1) % 7 buf.tm_yday = buf.tm_yday - 1 return buf @@ -280,6 +287,13 @@ secs = _floattime() return space.wrap(secs) +if _WIN: + class PCCache: + pass + pccache = PCCache() + pccache.divisor = 0.0 + pccache.ctrStart = LARGE_INTEGER() + def clock(space): """clock() -> floating point number @@ -288,24 +302,21 @@ records.""" if _POSIX: - res = float(float(libc.clock()) / CLOCKS_PER_SEC) + res = float(libc.clock()) / CLOCKS_PER_SEC return space.wrap(res) elif _WIN: - divisor = 0.0 - ctrStart = c_int() - now = c_int() - - if divisor == 0.0: - freq = c_int() - QueryPerformanceCounter(byref(ctrStart)) + if pccache.divisor == 0.0: + freq = LARGE_INTEGER() res = QueryPerformanceCounter(byref(freq)) if not res or not freq: return space.wrap(float(libc.clock())) - divisor = float(freq.value) - + pccache.divisor = float(freq.value) + QueryPerformanceCounter(byref(pccache.ctrStart)) + + now = LARGE_INTEGER() QueryPerformanceCounter(byref(now)) - diff = float(now.value - ctrStart.value) - return space.wrap(float(diff / divisor)) + diff = float(now.value - pccache.ctrStart.value) + return space.wrap(diff / pccache.divisor) def ctime(space, w_seconds=None): """ctime([seconds]) -> string @@ -333,37 +344,7 @@ Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'. When the time tuple is not present, current time as returned by localtime() is used.""" - tup = None - tuple_len = 0 - buf_value = tm() - - # if len(tup_w): - # w_tup = tup_w[0] - if not space.is_w(w_tup, space.w_None): - tuple_len = space.int_w(space.len(w_tup)) - - if tuple_len < 9: - raise OperationError(space.w_TypeError, - space.wrap("argument must be 9-item sequence")) - - # check if every passed object is a int - tup = space.unpackiterable(w_tup) - for t in tup: - space.int_w(t) - # map(space.int_w, tup) # XXX: can't use it - - buf_value = _gettmarg(space, tup, buf_value) - else: - # empty list - buf = None - - tt = time_t(int(_floattime())) - buf = libc.localtime(byref(tt)) - if not buf: - raise OperationError(space.w_ValueError, - space.wrap(_get_error_msg())) - buf_value = buf.contents - + buf_value = _gettmarg(space, w_tup) p = libc.asctime(byref(buf_value)) if not p: raise OperationError(space.w_ValueError, @@ -411,26 +392,8 @@ """mktime(tuple) -> floating point number Convert a time tuple in local time to seconds since the Epoch.""" - - if space.is_w(w_tup, space.w_None): - raise OperationError(space.w_TypeError, - space.wrap("argument must be 9-item sequence not None")) - else: - tup_w = space.unpackiterable(w_tup) - - if 1 < len(tup_w) < 9: - raise OperationError(space.w_TypeError, - space.wrap("argument must be a sequence of length 9, not %d"\ - % len(tup_w))) - - tt = time_t(int(_floattime())) - - buf = libc.localtime(byref(tt)) - if not buf: - raise OperationError(space.w_ValueError, space.wrap(_get_error_msg())) - - buf = _gettmarg(space, tup_w, buf.contents) + buf = _gettmarg(space, w_tup, allowNone=False) tt = libc.mktime(byref(buf)) if tt == -1: raise OperationError(space.w_OverflowError, @@ -457,52 +420,21 @@ # reset timezone, altzone, daylight and tzname timezone, daylight, tzname, altzone = _init_timezone() - _set_module_object(space, "timezone", timezone) - _set_module_object(space, 'daylight', daylight) + _set_module_object(space, "timezone", space.wrap(timezone)) + _set_module_object(space, 'daylight', space.wrap(daylight)) tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])] - _set_module_list_object(space, 'tzname', tzname_w) - _set_module_object(space, 'altzone', altzone) + _set_module_object(space, 'tzname', space.newlist(tzname_w)) + _set_module_object(space, 'altzone', space.wrap(altzone)) tzset.unwrap_spec = [ObjSpace] -def strftime(space, w_format, w_tup=None): +def strftime(space, format, w_tup=None): """strftime(format[, tuple]) -> string Convert a time tuple to a string according to a format specification. See the library reference manual for formatting codes. When the time tuple is not present, current time as returned by localtime() is used.""" - - tup = None - tuple_len = 0 - buf_value = tm() - - format = space.str_w(w_format) - - # if len(tup_w): - # w_tup = tup_w[0] - if not space.is_w(w_tup, space.w_None): - tuple_len = space.int_w(space.len(w_tup)) - - if tuple_len < 9: - raise OperationError(space.w_TypeError, - space.wrap("argument must be 9-item sequence")) - - # check if every passed object is a int - tup = space.unpackiterable(w_tup) - for t in tup: - space.int_w(t) - # map(space.int_w, tup) # XXX: can't use it - - buf_value = _gettmarg(space, tup, buf_value) - else: - # empty list - buf = None - - tt = time_t(int(_floattime())) - buf = libc.localtime(byref(tt)) - if not buf: - raise OperationError(space.w_ValueError, - space.wrap(_get_error_msg())) - buf_value = buf.contents + + buf_value = _gettmarg(space, w_tup) # Checks added to make sure strftime() does not crash Python by # indexing blindly into some array for a textual representation @@ -523,11 +455,6 @@ if buf_value.tm_sec < 0 or buf_value.tm_sec > 61: raise OperationError(space.w_ValueError, space.wrap("seconds out of range")) - # tm_wday does not need checking of its upper-bound since taking - # "% 7" in gettmarg() automatically restricts the range. - if buf_value.tm_wday < 0: - raise OperationError(space.w_ValueError, - space.wrap("day of week out of range")) if buf_value.tm_yday < 0 or buf_value.tm_yday > 365: raise OperationError(space.w_ValueError, space.wrap("day of year out of range")) @@ -546,8 +473,8 @@ # More likely, the format yields an empty result, # e.g. an empty format, or %Z when the timezone # is unknown. - if buflen > 0: - return space.wrap(outbuf.value[:buflen]) + if buflen < 0: buflen = 0 # should not occur + return space.wrap(outbuf.value[:buflen]) i += i -strftime.unwrap_spec = [ObjSpace, W_Root, W_Root] +strftime.unwrap_spec = [ObjSpace, str, W_Root] Modified: pypy/dist/pypy/module/rctime/test/test_rctime.py ============================================================================== --- pypy/dist/pypy/module/rctime/test/test_rctime.py (original) +++ pypy/dist/pypy/module/rctime/test/test_rctime.py Sun Sep 17 13:30:12 2006 @@ -7,7 +7,7 @@ cls.space = space def test_attributes(self): - import rctime + import time as rctime assert isinstance(rctime.accept2dyear, int) assert isinstance(rctime.altzone, int) assert isinstance(rctime.daylight, int) @@ -16,7 +16,7 @@ assert isinstance(rctime.__doc__, str) def test_sleep(self): - import rctime + import time as rctime import sys import os raises(TypeError, rctime.sleep, "foo") @@ -25,18 +25,18 @@ raises(OverflowError, rctime.sleep, sys.maxint) def test_clock(self): - import rctime + import time as rctime rctime.clock() assert isinstance(rctime.clock(), float) def test_time(self): - import rctime + import time as rctime rctime.time() assert isinstance(rctime.time(), float) assert rctime.time() != 0.0 # 0.0 means failure def test_ctime(self): - import rctime + import time as rctime raises(TypeError, rctime.ctime, "foo") rctime.ctime(None) rctime.ctime() @@ -45,7 +45,7 @@ rctime.ctime(rctime.time()) def test_gmtime(self): - import rctime + import time as rctime raises(TypeError, rctime.gmtime, "foo") rctime.gmtime() rctime.gmtime(None) @@ -60,7 +60,7 @@ assert rctime.gmtime(t) == rctime.gmtime(t) def test_localtime(self): - import rctime + import time as rctime raises(TypeError, rctime.localtime, "foo") rctime.localtime() rctime.localtime(None) @@ -74,7 +74,7 @@ assert rctime.localtime(t) == rctime.localtime(t) def test_mktime(self): - import rctime + import time as rctime raises(TypeError, rctime.mktime, "foo") raises(TypeError, rctime.mktime, None) raises(TypeError, rctime.mktime, (1, 2)) @@ -105,7 +105,7 @@ assert rctime.mktime(tuple(ltime)) == rctime.mktime(ltime) def test_asctime(self): - import rctime + import time as rctime rctime.asctime() # raises(TypeError, rctime.asctime, None) raises(TypeError, rctime.asctime, ()) @@ -124,7 +124,7 @@ assert rctime.asctime(tuple(ltime)) == rctime.asctime(ltime) def test_struct_time(self): - import rctime + import time as rctime raises(TypeError, rctime.struct_time) raises(TypeError, rctime.struct_time, "foo") raises(TypeError, rctime.struct_time, (1, 2, 3)) @@ -134,7 +134,7 @@ assert len(st_time) == len(tup) def test_tzset(self): - import rctime + import time as rctime import os if not os.name == "posix": @@ -199,7 +199,7 @@ rctime.tzset() def test_strftime(self): - import rctime + import time as rctime t = rctime.time() tt = rctime.gmtime(t) @@ -214,7 +214,7 @@ raises(TypeError, rctime.strftime, range(8)) def test_strftime_bounds_checking(self): - import rctime + import time as rctime # make sure that strftime() checks the bounds of the various parts # of the time tuple. @@ -254,7 +254,7 @@ raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 1, 2)) def test_strptime(self): - import rctime + import time as rctime t = rctime.time() tt = rctime.gmtime(t) From arigo at codespeak.net Sun Sep 17 13:35:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 13:35:39 +0200 (CEST) Subject: [pypy-svn] r32409 - pypy/dist/lib-python/modified-2.4.1/test Message-ID: <20060917113539.CB9A510071@code0.codespeak.net> Author: arigo Date: Sun Sep 17 13:35:39 2006 New Revision: 32409 Added: pypy/dist/lib-python/modified-2.4.1/test/test_mmap.py - copied, changed from r32406, pypy/dist/lib-python/2.4.1/test/test_mmap.py Log: "pypy-c --usemodules=mmap" passes the stdlib mmap test after this fix. From arigo at codespeak.net Sun Sep 17 13:36:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 13:36:28 +0200 (CEST) Subject: [pypy-svn] r32410 - pypy/dist/pypy/module/mmap/test Message-ID: <20060917113628.6865910071@code0.codespeak.net> Author: arigo Date: Sun Sep 17 13:36:25 2006 New Revision: 32410 Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py Log: Bad style copied from the CPython stdlib. Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py ============================================================================== --- pypy/dist/pypy/module/mmap/test/test_mmap.py (original) +++ pypy/dist/pypy/module/mmap/test/test_mmap.py Sun Sep 17 13:36:25 2006 @@ -486,7 +486,9 @@ # test access=ACCESS_READ mapsize = 10 - open(filename, "wb").write("a" * mapsize) + f = open(filename, "wb") + f.write("a" * mapsize) + f.close() f = open(filename, "rb") m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ) # assert m[:] == 'a' * mapsize From arigo at codespeak.net Sun Sep 17 15:53:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 15:53:13 +0200 (CEST) Subject: [pypy-svn] r32413 - pypy/dist/pypy/interpreter Message-ID: <20060917135313.D9F0310053@code0.codespeak.net> Author: arigo Date: Sun Sep 17 15:53:09 2006 New Revision: 32413 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: A probably naive and misguided attempt at making the module-selection logic of objspaces less strange. Trying now to get a pypy-c with rctime... Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sun Sep 17 15:53:09 2006 @@ -185,7 +185,7 @@ except AttributeError: return self.__class__.__name__ - def setbuiltinmodule(self, importname, installed_builtin_modules=[]): + def setbuiltinmodule(self, importname): """NOT_RPYTHON. load a lazy pypy/module and put it into sys.modules""" import sys @@ -198,10 +198,6 @@ else: name = importname - if name in installed_builtin_modules: - del sys.modules[fullname] - return None - w_name = self.wrap(name) w_mod = self.wrap(Module(self, w_name)) w_modules = self.sys.get('modules') @@ -226,14 +222,15 @@ '_codecs', 'gc', '_weakref', 'array', 'marshal', 'errno', 'math', '_sre', '_pickle_support'] - # there also are the '_sre' and 'marshal' modules - # but those currently cause translation problems. You can - # enable them when running PyPy on top of CPython - # by e.g. specifying --usemodules=_sre,marshal + # You can enable more modules by specifying --usemodules=xxx,yyy for name, value in self.config.objspace.usemodules: if value and name not in modules: modules.append(name) + # a bit of custom logic: time2 or rctime take precedence over time + if ('time2' in modules or 'rctime' in modules) and 'time' in modules: + modules.remove('time') + import pypy if not self.config.objspace.nofaking: for modname in self.ALL_BUILTIN_MODULES: @@ -269,7 +266,8 @@ self.setitem(w_modules, w_name, w_builtin) self.setitem(self.builtin.w_dict, self.wrap('__builtins__'), w_builtin) - installed_builtin_modules = ['sys', '__builtin__', 'exceptions'] # bootstrap ones + bootstrap_modules = ['sys', '__builtin__', 'exceptions'] + installed_builtin_modules = bootstrap_modules[:] # initialize with "bootstrap types" from objspace (e.g. w_None) for name, value in self.__dict__.items(): @@ -280,9 +278,11 @@ # install midex and faked modules and set builtin_module_names on sys for mixedname in self.get_builtinmodule_to_install(): - if not mixedname.startswith('faked+'): - self.install_mixemodule(mixedname, installed_builtin_modules) - else: + if (mixedname not in bootstrap_modules + and not mixedname.startswith('faked+')): + self.install_mixedmodule(mixedname, installed_builtin_modules) + for mixedname in self.get_builtinmodule_to_install(): + if mixedname.startswith('faked+'): modname = mixedname[6:] self.install_faked_module(modname, installed_builtin_modules) @@ -294,12 +294,14 @@ self.setitem(self.sys.w_dict, self.wrap('builtin_module_names'), w_builtin_module_names) - def install_mixemodule(self, mixedname, installed_builtin_modules): + def install_mixedmodule(self, mixedname, installed_builtin_modules): """NOT_RPYTHON""" - if mixedname not in installed_builtin_modules: - modname = self.setbuiltinmodule(mixedname, installed_builtin_modules) - if modname: - installed_builtin_modules.append(modname) + modname = self.setbuiltinmodule(mixedname) + if modname: + assert modname not in installed_builtin_modules, ( + "duplicate interp-level module enabled for the " + "app-level module %r" % (modname,)) + installed_builtin_modules.append(modname) def load_cpython_module(self, modname): "NOT_RPYTHON. Steal a module from CPython." From cfbolz at codespeak.net Sun Sep 17 16:00:31 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 16:00:31 +0200 (CEST) Subject: [pypy-svn] r32414 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060917140031.7D15A10071@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 16:00:29 2006 New Revision: 32414 Added: pypy/dist/pypy/module/_random/rpy_random.py pypy/dist/pypy/module/_random/test/test_mersenne.py Log: first steps in rewriting the mersenne twister algorithm in RPython. Basic generation works, some helpers missing. Added: pypy/dist/pypy/module/_random/rpy_random.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_random/rpy_random.py Sun Sep 17 16:00:29 2006 @@ -0,0 +1,111 @@ +# this code is a version of the mersenne twister random number generator which +# is supposed to be used from RPython without the Python interpreter wrapping +# machinery etc. + +# this is stolen from CPython's _randommodule.c + +from pypy.rpython.rarithmetic import r_uint + +N = 624 +M = 397 +MATRIX_A = r_uint(0x9908b0df) # constant vector a +UPPER_MASK = r_uint(0x80000000) # most significant w-r bits +LOWER_MASK = r_uint(0x7fffffff) # least significant r bits + +class Random(object): + def __init__(self, seed=r_uint(0)): + self.state = [r_uint(0)] * N + self.index = 0 + if seed: + self.init_genrand(seed) + + def init_genrand(self, s): + mt = self.state + mt[0]= s & r_uint(0xffffffff) + for mti in range(1, N): + mt[mti] = (r_uint(1812433253) * + (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti) + # See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. + # In the previous versions, MSBs of the seed affect + # only MSBs of the array mt[]. + # for >32 bit machines + mt[mti] &= r_uint(0xffffffff); + self.index = mti + 1 + + def init_by_array(self, init_key): + key_length = len(init_key) + mt = self.state + self.init_genrand(r_uint(19650218)) + i = 1 + j = 0 + if N > key_length: + max_k = N + else: + max_k = key_length + for k in range(max_k, 0, -1): + mt[i] = ((mt[i] ^ + ((mt[i - 1] ^ (mt[i - 1] >> 30)) * r_uint(1664525))) + + init_key[j] + j) # non linear + mt[i] &= r_uint(0xffffffff) # for WORDSIZE > 32 machines + i += 1 + j += 1 + if i >= N: + mt[0] = mt[N - 1] + i = 1 + if j >= key_length: + j = 0 + for k in range(N - 1, 0, -1): + mt[i] = ((mt[i] ^ + ((mt[i - 1] ^ (mt[i - 1] >> 30)) * r_uint(1566083941))) + - i) # non linear + mt[i] &= r_uint(0xffffffff) # for WORDSIZE > 32 machines + i += 1 + if (i>=N): + mt[0] = mt[N - 1] + i = 1 + mt[0] = r_uint(0x80000000) + + def genrand32(self): + mag01 = [0, MATRIX_A] + mt = self.state + if self.index >= N: + for kk in range(N - M): + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK) + mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & r_uint(1)] + for kk in range(N - M, N - 1): + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK) + mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & r_uint(1)] + y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK) + mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & r_uint(1)] + self.index = 0 + y = mt[self.index] + self.index += 1 + y ^= y >> 11 + y ^= (y << 7) & r_uint(0x9d2c5680) + y ^= (y << 15) & r_uint(0xefc60000) + y ^= (y >> 18) + return y + + def random(self): + a = self.genrand32() >> 5 + b = self.genrand32() >> 6 + return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0) + +def main(): + import sys + rnd = Random() + rnd.init_genrand(1000) + print rnd.index + +# for j in range(100): +# print rnd.state[j], +# if j % 7 == 6: +# print +# print "\n" + for j in range(5): + print rnd.genrand32(), + if j % 7 == 6: + print + print + +main() Added: pypy/dist/pypy/module/_random/test/test_mersenne.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_random/test/test_mersenne.py Sun Sep 17 16:00:29 2006 @@ -0,0 +1,17 @@ +from pypy.module._random.rpy_random import Random + +# the numbers were created by using CPython's _randommodule.c + +def test_init_from_seed(): + rnd = Random(1000) + assert rnd.state[:14] == [1000, 4252021385, 1724402292, 571538732, + 73690720, 4283493349, 2222270404, 2464917285, 427676011, + 1101193792, 2887716015, 3670250828, 1664757559, 1538426459] + +def test_numbers(): + rnd = Random(1000) + nums = [rnd.genrand32() for i in range(14)] + assert nums == [2807145907, 882709079, 493951047, 2621574848, 4081433851, + 44058974, 2070996316, 1549632257, 3747249597, 3650674304, + 911961945, 58396205, 174846504, 1478498153] + From cfbolz at codespeak.net Sun Sep 17 16:09:00 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 16:09:00 +0200 (CEST) Subject: [pypy-svn] r32415 - pypy/dist/pypy/module/_random/test Message-ID: <20060917140900.8929510072@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 16:08:59 2006 New Revision: 32415 Modified: pypy/dist/pypy/module/_random/test/test_mersenne.py Log: add test for init_by_array Modified: pypy/dist/pypy/module/_random/test/test_mersenne.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_mersenne.py (original) +++ pypy/dist/pypy/module/_random/test/test_mersenne.py Sun Sep 17 16:08:59 2006 @@ -15,3 +15,9 @@ 44058974, 2070996316, 1549632257, 3747249597, 3650674304, 911961945, 58396205, 174846504, 1478498153] +def test_init_by_array(): + rnd = Random() + rnd.init_by_array([1, 2, 3, 4]) + assert rnd.state[:14] == [2147483648, 1269538435, 699006892, 381364451, + 172015551, 3237099449, 3609464087, 2187366456, 654585064, + 2665903765, 3735624613, 1241943673, 2038528247, 3774211972] From cfbolz at codespeak.net Sun Sep 17 16:15:07 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 16:15:07 +0200 (CEST) Subject: [pypy-svn] r32416 - pypy/dist/pypy/module/_random Message-ID: <20060917141507.1651B10072@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 16:15:05 2006 New Revision: 32416 Modified: pypy/dist/pypy/module/_random/rpy_random.py Log: forgot a ";", thanks armin Modified: pypy/dist/pypy/module/_random/rpy_random.py ============================================================================== --- pypy/dist/pypy/module/_random/rpy_random.py (original) +++ pypy/dist/pypy/module/_random/rpy_random.py Sun Sep 17 16:15:05 2006 @@ -29,7 +29,7 @@ # In the previous versions, MSBs of the seed affect # only MSBs of the array mt[]. # for >32 bit machines - mt[mti] &= r_uint(0xffffffff); + mt[mti] &= r_uint(0xffffffff) self.index = mti + 1 def init_by_array(self, init_key): @@ -95,13 +95,14 @@ import sys rnd = Random() rnd.init_genrand(1000) + rnd.init_by_array([1, 2, 3, 4]) print rnd.index -# for j in range(100): -# print rnd.state[j], -# if j % 7 == 6: -# print -# print "\n" + for j in range(100): + print rnd.state[j], + if j % 7 == 6: + print + print "\n" for j in range(5): print rnd.genrand32(), if j % 7 == 6: From cfbolz at codespeak.net Sun Sep 17 16:16:13 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 16:16:13 +0200 (CEST) Subject: [pypy-svn] r32417 - pypy/dist/pypy/module/_random Message-ID: <20060917141613.933C310076@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 16:16:12 2006 New Revision: 32417 Modified: pypy/dist/pypy/module/_random/rpy_random.py Log: remove testing main method Modified: pypy/dist/pypy/module/_random/rpy_random.py ============================================================================== --- pypy/dist/pypy/module/_random/rpy_random.py (original) +++ pypy/dist/pypy/module/_random/rpy_random.py Sun Sep 17 16:16:12 2006 @@ -91,22 +91,3 @@ b = self.genrand32() >> 6 return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0) -def main(): - import sys - rnd = Random() - rnd.init_genrand(1000) - rnd.init_by_array([1, 2, 3, 4]) - print rnd.index - - for j in range(100): - print rnd.state[j], - if j % 7 == 6: - print - print "\n" - for j in range(5): - print rnd.genrand32(), - if j % 7 == 6: - print - print - -main() From cfbolz at codespeak.net Sun Sep 17 18:56:17 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 18:56:17 +0200 (CEST) Subject: [pypy-svn] r32418 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060917165617.7FF2D1006C@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 18:56:15 2006 New Revision: 32418 Modified: pypy/dist/pypy/module/_random/rpy_random.py pypy/dist/pypy/module/_random/test/test_mersenne.py Log: implement jumpahead Modified: pypy/dist/pypy/module/_random/rpy_random.py ============================================================================== --- pypy/dist/pypy/module/_random/rpy_random.py (original) +++ pypy/dist/pypy/module/_random/rpy_random.py Sun Sep 17 18:56:15 2006 @@ -91,3 +91,11 @@ b = self.genrand32() >> 6 return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0) + def jumpahead(self, n): + mt = self.state + for i in range(N - 1, 0, -1): + j = n % i + mt[i], mt[j] = mt[j], mt[i] + for i in range(N): + mt[i] += i + 1 + self.index = N Modified: pypy/dist/pypy/module/_random/test/test_mersenne.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_mersenne.py (original) +++ pypy/dist/pypy/module/_random/test/test_mersenne.py Sun Sep 17 18:56:15 2006 @@ -1,4 +1,5 @@ -from pypy.module._random.rpy_random import Random +from pypy.module._random.rpy_random import Random, N, r_uint +import _random # the numbers were created by using CPython's _randommodule.c @@ -21,3 +22,13 @@ assert rnd.state[:14] == [2147483648, 1269538435, 699006892, 381364451, 172015551, 3237099449, 3609464087, 2187366456, 654585064, 2665903765, 3735624613, 1241943673, 2038528247, 3774211972] + +def test_jumpahead(): + rnd = Random() + rnd.state = [r_uint(0)] * N + rnd.state[0] = r_uint(1) + cpyrandom = _random.Random() + cpyrandom.setstate(tuple([int(s) for s in rnd.state] + [rnd.index])) + rnd.jumpahead(100) + cpyrandom.jumpahead(100) + assert tuple(rnd.state) + (rnd.index, ) == cpyrandom.getstate() From arigo at codespeak.net Sun Sep 17 19:00:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 19:00:33 +0200 (CEST) Subject: [pypy-svn] r32419 - in pypy/branch/kill-keepalives/pypy/rpython/rctypes: . test Message-ID: <20060917170033.6234C1006E@code0.codespeak.net> Author: arigo Date: Sun Sep 17 19:00:31 2006 New Revision: 32419 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rfunc.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rstringbuf.py pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py Log: A fix, a smaller test for it, and a skip. Now rctypes tests mostly pass again. Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/rmodel.py Sun Sep 17 19:00:31 2006 @@ -222,6 +222,16 @@ v_rawaddr = llops.genop("raw_malloc", [v_size], resulttype=llmemory.Address) llops.genop("raw_memclear", [v_rawaddr, v_size]) + assert isinstance(TYPE, lltype.Array) # XXX for now + if not TYPE._hints.get('nolength', False): + # initialize the length field, if any + c_lengthofs = inputconst(lltype.Signed, + llmemory.ArrayLengthOffset(TYPE)) + v_p = llops.genop("adr_add", [v_rawaddr, c_lengthofs], + resulttype=llmemory.Address) + c_Signed = inputconst(lltype.Void, lltype.Signed) + c_zero = inputconst(lltype.Signed, 0) + llops.genop("raw_store", [v_p, c_Signed, c_zero, v_length]) v_rawdata = llops.genop("cast_adr_to_ptr", [v_rawaddr], resulttype=lltype.Ptr(TYPE)) c_datafieldname = inputconst(lltype.Void, "c_data") Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rfunc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rfunc.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rfunc.py Sun Sep 17 19:00:31 2006 @@ -107,9 +107,12 @@ def test_ll_atoi(): keepalive = [] def str2subarray(string): - llstring = string_repr.convert_const(string) - keepalive.append(llstring) - return lltype.direct_arrayitems(llstring.chars) + p = lltype.malloc(lltype.Array(lltype.Char), len(string)+1, + immortal=True) + for i in range(len(string)): + p[i] = string[i] + p[len(string)] = '\x00' + return p assert ll_atoi(str2subarray("")) == 0 assert ll_atoi(str2subarray("42z7")) == 42 assert ll_atoi(str2subarray("blah")) == 0 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rstringbuf.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rstringbuf.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rstringbuf.py Sun Sep 17 19:00:31 2006 @@ -209,3 +209,11 @@ fn = compile(func, [int]) res = fn(0x12345678) assert res == 0x12345678 + + def test_compile_len(self): + def func(n): + buf = create_string_buffer(n) + return len(buf) + fn = compile(func, [int]) + res = fn(321) + assert res == 321 Modified: pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rctypes/test/test_rvoid_p.py Sun Sep 17 19:00:31 2006 @@ -119,6 +119,8 @@ class Test_compilation: def test_compile_c_char_p(self): + py.test.skip("the c_void_p() doesn't keep the c_int(12) alive") + # XXX ...that's probably a bug def func(): x = c_int(12) p1 = cast(pointer(x), c_void_p) From cfbolz at codespeak.net Sun Sep 17 19:53:30 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 19:53:30 +0200 (CEST) Subject: [pypy-svn] r32421 - pypy/extradoc/sprintinfo/ddorf2006b Message-ID: <20060917175330.27A851006C@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 19:53:27 2006 New Revision: 32421 Added: pypy/extradoc/sprintinfo/ddorf2006b/ pypy/extradoc/sprintinfo/ddorf2006b/announce.txt pypy/extradoc/sprintinfo/ddorf2006b/people.txt Log: (arigo, cfbolz): ddorf sprint announcement Added: pypy/extradoc/sprintinfo/ddorf2006b/announce.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/ddorf2006b/announce.txt Sun Sep 17 19:53:27 2006 @@ -0,0 +1,59 @@ +Duesseldorf PyPy sprint October 30 - November 5 2006 +===================================================== + +The next PyPy sprint will be held in the Computer Science department of +Heinrich-Heine Universitaet Duesseldorf from the 30th of October to the 5th of +November 2006. + +Topics and goals +---------------- + +The topics of the sprints are not fixed yet. We will progress on the subjects +that we are currently working on, while giving a special priority to any topic +that "non-core" people find interesting. There are many topics that could fit +both category :-) Here are some examples: + +* Just-In-Time work. Two sub-topics: + + - write and/or optimize a machine-code backend (we have 386 only so far) + - work on turning simple interpreters into JIT compilers (we cannot do + this for the whole of the PyPy interpreter yet, we're getting there + small step by small step). + +* Optimization of core Python data types, making full + use of PyPy's flexible architecture and python-implemented + (and then translated) type system. (We have already various dict and + str implementations.) + +* "Next-step stuff" that will requires some thinking and design: + + - distribution (where a single program runs on multiple machines) + - persistence (save an "image" of a running program, or a part of it) + - security (in many possible senses of the word) + +* and as always, there is the topic of implementing or completing core + extension modules (e.g. socket...). This is hacking with a mix of + ctypes and RPython. + + +Location +-------- + +The sprint will (probably) take place in a seminar room of +the geography department (which is getting assimilated by the cs +department and is below it). It is in the building 25.12 of the +university campus. For travel instructions see + + http://stups.cs.uni-duesseldorf.de/anreise/esbahn.php + +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 send to that list. We'll keep +a list of `people`_ which we'll update (which you can do so yourself +if you have codespeak commit rights). + +.. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint +.. _`people`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006b/people.html Added: pypy/extradoc/sprintinfo/ddorf2006b/people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/ddorf2006b/people.txt Sun Sep 17 19:53:27 2006 @@ -0,0 +1,44 @@ +People coming to the Duesseldorf sprint October 2006 +==================================================== + +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 +==================== ============== ===================== +Carl Friedrich Bolz always there private +==================== ============== ===================== + +People on the following list were present at previous sprints: + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +Jacob Hallen ? ? +Aurelien Campeas ? ? +Alexandre Fayolle ? ? +Lene Wagner ? ? +Amaury Forgeot d'Arc ? ? +Valentino Volonghi ? ? +Boris Feigin ? ? +Andrew Thompson ? ? +Bert Freudenberg ? ? +Laura Creighton ? ? +Beatrice Duering ? ? +Richard Emslie ? ? +Johan Hahn ? ? +Michael Hudson ? ? +Armin Rigo ? ? +Holger Krekel ? ? +Eric van Riet Paap ? ? +Maciej Fijalkowski ? ? +Anders Chrigstroem ? ? +Samuele Pedroni ? ? +Christian Tismer ? ? +Antonio Cuni ? ? +Anders Lehmann ? ? +Niklaus Haldimann ? ? +Christian Tismer ? ? +==================== ============== ===================== From arigo at codespeak.net Sun Sep 17 19:56:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 17 Sep 2006 19:56:03 +0200 (CEST) Subject: [pypy-svn] r32422 - pypy/extradoc/sprintinfo/ddorf2006b Message-ID: <20060917175603.D7BDC1006C@code0.codespeak.net> Author: arigo Date: Sun Sep 17 19:56:01 2006 New Revision: 32422 Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt Log: Added myself to the DDrof people list. Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006b/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006b/people.txt Sun Sep 17 19:56:01 2006 @@ -9,6 +9,7 @@ Name Arrive/Depart Accomodation ==================== ============== ===================== Carl Friedrich Bolz always there private +Armin Rigo 27th / - private ==================== ============== ===================== People on the following list were present at previous sprints: @@ -30,7 +31,6 @@ Richard Emslie ? ? Johan Hahn ? ? Michael Hudson ? ? -Armin Rigo ? ? Holger Krekel ? ? Eric van Riet Paap ? ? Maciej Fijalkowski ? ? From cfbolz at codespeak.net Sun Sep 17 20:33:06 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 20:33:06 +0200 (CEST) Subject: [pypy-svn] r32423 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060917183306.0E4FF10053@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 20:33:04 2006 New Revision: 32423 Modified: pypy/dist/pypy/module/_random/__init__.py pypy/dist/pypy/module/_random/interp_random.py pypy/dist/pypy/module/_random/test/test_random.py Log: Implementation of _random using the rpy_random mersenne twister implementation. Needs more tests and is currently disabled, but in theory it is superior than the current applevel implementation Modified: pypy/dist/pypy/module/_random/__init__.py ============================================================================== --- pypy/dist/pypy/module/_random/__init__.py (original) +++ pypy/dist/pypy/module/_random/__init__.py Sun Sep 17 20:33:04 2006 @@ -1,6 +1,4 @@ -import py # FINISHME -py.test.skip("The _random module is not ready: it misses the post-2.2 parts of " - "the interface and it needs to use new Mersenne Twister algorithm.") +import py from pypy.interpreter.mixedmodule import MixedModule @@ -8,29 +6,6 @@ appleveldefs = {} interpleveldefs = { - 'Random' : 'interp_random.W_Random', - 'seed' : 'interp_random.get_random_method(space, "seed")', - 'getstate' : 'interp_random.get_random_method(space, "getstate")', - 'setstate' : 'interp_random.get_random_method(space, "setstate")', - 'jumpahead' : 'interp_random.get_random_method(space, "jumpahead")', - 'randrange' : 'interp_random.get_random_method(space, "randrange")', - 'randint' : 'interp_random.get_random_method(space, "randint")', - 'choice' : 'interp_random.get_random_method(space, "choice")', - 'shuffle' : 'interp_random.get_random_method(space, "shuffle")', - 'sample' : 'interp_random.get_random_method(space, "sample")', - 'random' : 'interp_random.get_random_method(space, "random")', - 'uniform' : 'interp_random.get_random_method(space, "uniform")', - 'betavariate' : 'interp_random.get_random_method(space, "betavariate")', - 'expovariate' : 'interp_random.get_random_method(space, "expovariate")', - 'gammavariate' : 'interp_random.get_random_method(space, "gammavariate")', - 'jumpahead' : 'interp_random.get_random_method(space, "jumpahead")', - 'gauss' : 'interp_random.get_random_method(space, "gauss")', - 'lognormvariate' : 'interp_random.get_random_method(space, "lognormvariate")', - 'normalvariate' : 'interp_random.get_random_method(space, "normalvariate")', - 'vonmisesvariate' : 'interp_random.get_random_method(space, "vonmisesvariate")', - 'paretovariate' : 'interp_random.get_random_method(space, "paretovariate")', - 'cunifvariate' : 'interp_random.get_random_method(space, "cunifvariate")', - 'weibullvariate' : 'interp_random.get_random_method(space, "weibullvariate")', - 'whseed' : 'interp_random.get_random_method(space, "whseed")', # officially obsolete + 'Random' : 'interp_random.W_Random', } Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Sun Sep 17 20:33:04 2006 @@ -3,33 +3,13 @@ from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app from pypy.interpreter.baseobjspace import Wrappable from pypy.rpython.rarithmetic import r_uint +from pypy.module._random import rpy_random from math import log as _log, exp as _exp, pi as _pi, e as _e from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin from math import floor as _floor -def _verify(w_name, w_computed, w_expected): - if abs(w_computed - w_expected) > 1e-7: - raise OperationError( - space.w_ValueError, - space.wrap( - "computed value for %s deviates too much " - "(computed %g, expected %g)" % (w_name, w_computed, w_expected))) - - -NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) -_verify('NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141) - -TWOPI = 2.0*_pi -_verify('TWOPI', TWOPI, 6.28318530718) - -LOG4 = _log(4.0) -_verify('LOG4', LOG4, 1.38629436111989) - -SG_MAGICCONST = 1.0 + _log(4.5) -_verify('SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627) - -#del _verify +import time def descr_new__(space, w_subtype, w_anything=NoneNotWrapped): x = space.allocate_instance(W_Random, w_subtype) @@ -37,593 +17,98 @@ return space.wrap(x) class W_Random(Wrappable): - """A wrappable box around an interp level md5 object.""" - VERSION = 1 # used by getstate/setstate - - def __init__(self, space, anything=NoneNotWrapped): - """Initialize an instance. - - Optional argument x controls seeding, as for Random.seed(). - """ - self.seed(space, anything) - - - def seed(self, space, w_a=NoneNotWrapped): - """Initialize internal state from hashable object. - - None or no argument seeds from current time. - - If a is not None or an int or long, hash(a) is used instead. - - If a is an int or long, a is used directly. Distinct values between - 0 and 27814431486575L inclusive are guaranteed to yield distinct - internal states (this guarantee is specific to the default - Wichmann-Hill generator). - """ - if w_a is None: - # Initialize from current time - import time - a = int(time.time() * 256) - else: - a = space.int_w(space.hash(w_a)) - - a, x = divmod(a, 30268) - a, y = divmod(a, 30306) - a, z = divmod(a, 30322) - self._seed = int(x)+1, int(y)+1, int(z)+1 - - self.gauss_next = None - seed.unwrap_spec = ['self', ObjSpace, W_Root] - + def __init__(self, space, w_anything): + self._rnd = rpy_random.Random() + self.seed(space, w_anything) + __init__.unwrap_spec = ['self', ObjSpace, W_Root] def random(self, space): - """Get the next random number in the range [0.0, 1.0).""" - - # Wichman-Hill random number generator. - # - # Wichmann, B. A. & Hill, I. D. (1982) - # Algorithm AS 183: - # An efficient and portable pseudo-random number generator - # Applied Statistics 31 (1982) 188-190 - # - # see also: - # Correction to Algorithm AS 183 - # Applied Statistics 33 (1984) 123 - # - # McLeod, A. I. (1985) - # A remark on Algorithm AS 183 - # Applied Statistics 34 (1985),198-200 - - # This part is thread-unsafe: - # BEGIN CRITICAL SECTION - x, y, z = self._seed - x = (171 * x) % 30269 - y = (172 * y) % 30307 - z = (170 * z) % 30323 - self._seed = x, y, z - # END CRITICAL SECTION - - # Note: on a platform using IEEE-754 double arithmetic, this can - # never return 0.0 (asserted by Tim; proof too long for a comment). - randf = (x/30269.0 + y/30307.0 + z/30323.0) % 1.0 - return space.wrap(randf) + return space.newfloat(self._rnd.random()) random.unwrap_spec = ['self', ObjSpace] + def seed(self, space, w_n=NoneNotWrapped): + if w_n is None: + w_n = space.newint(int(time.time())) + else: + if space.is_true(space.isinstance(w_n, space.w_int)): + w_n = space.abs(w_n) + elif space.is_true(space.isinstance(w_n, space.w_long)): + w_n = space.abs(w_n) + else: + # XXX not perfectly like CPython + w_n = space.abs(space.hash(w_n)) + key = [] + w_one = space.newlong(1) + w_thirtytwo = space.newlong(32) + # 0xffffffff + w_masklower = space.sub(space.pow(w_one, w_thirtytwo, space.w_None), + w_one) + while space.is_true(w_n): + w_chunk = space.and_(w_n, w_masklower) + chunk = r_uint(space.int_w(w_chunk)) + key.append(chunk) + w_n = space.rshift(w_n, w_thirtytwo) + self._rnd.init_by_array(key) + seed.unwrap_spec = ['self', ObjSpace, W_Root] + def getstate(self, space): - """Return internal state; can be passed to setstate() later.""" - st = (self.VERSION, self._seed, self.gauss_next) - return space.wrap(st) + state = [None] * (rpy_random.N + 1) + for i in range(rpy_random.N): + state[i] = space.newint(int(self._rnd.state[i])) + state[rpy_random.N] = space.newint(self._rnd.index) + return space.newtuple(state) getstate.unwrap_spec = ['self', ObjSpace] def setstate(self, space, w_state): - """Restore internal state from object returned by getstate().""" - u_state = space.unwrap(w_state) - print u_state - version = u_state[0] - if version == 1: - self._seed = u_state[1] - self.gauss_next = u_state[2] - else: - raise OperationError(space.w_ValueError, - space.wrap("state with version %s passed to " - "Random.setstate() of version %s" % - (version, self.VERSION))) + if not space.is_true(space.isinstance(w_state, space.w_tuple)): + errstring = space.wrap("state vector must be tuple") + raise OperationError(space.w_TypeError, errstring) + if space.int_w(space.len(w_state)) != rpy_random.N + 1: + errstring = space.wrap("state vector is the wrong size") + raise OperationError(space.w_TypeError, errstring) + for i in range(rpy_random.N): + w_item = space.getitem(w_state, space.newint(i)) + self._rnd.state[i] = r_uint(space.int_w(w_item)) + w_item = space.getitem(w_state, space.newint(i)) + self._rnd.index = r_uint(space.int_w(w_item)) setstate.unwrap_spec = ['self', ObjSpace, W_Root] - - def jumpahead(self, space, w_n): - """Act as if n calls to random() were made, but quickly. - - n is an int, greater than or equal to 0. - - Example use: If you have 2 threads and know that each will - consume no more than a million random numbers, create two Random - objects r1 and r2, then do - r2.setstate(r1.getstate()) - r2.jumpahead(1000000) - Then r1 and r2 will use guaranteed-disjoint segments of the full - period. - """ - - if not space.is_true(space.ge(w_n, space.wrap(0))): - raise OperationError(space.w_ValueError, - space.wrap("n must be >= 0")) - x, y, z = self._seed - x = (x * space.int_w(space.pow(space.wrap(171), w_n, space.wrap(30269)))) % 30269 - y = (y * space.int_w(space.pow(space.wrap(172), w_n, space.wrap(30307)))) % 30307 - z = (z * space.int_w(space.pow(space.wrap(170), w_n, space.wrap(30323)))) % 30323 - self._seed = x, y, z - jumpahead.unwrap_spec = ['self', ObjSpace, W_Root] - - - def _whseed(self, space, x=0, y=0, z=0): - """Set the Wichmann-Hill seed from (x, y, z). - - These must be integers in the range [0, 256). - """ - if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256): - raise OperationError(space.w_ValueError, - space.wrap('seeds must be in range(0, 256)')) - if 0 == x == y == z: - # Initialize from current time - import time - t = (int(time.time()) &0x7fffff) * 256 - t = (t&0xffffff) ^ (t>>24) - t, x = divmod(t, 256) - t, y = divmod(t, 256) - t, z = divmod(t, 256) - # Zero is a poor seed, so substitute 1 - self._seed = (x or 1, y or 1, z or 1) - - self.gauss_next = None - _whseed.unwrap_spec = ['self', ObjSpace, int, int, int] - - def whseed(self, space, w_a=NoneNotWrapped): - """Seed from hashable object's hash code. - - None or no argument seeds from current time. It is not guaranteed - that objects with distinct hash codes lead to distinct internal - states. - - This is obsolete, provided for compatibility with the seed routine - used prior to Python 2.1. Use the .seed() method instead. - """ - - if w_a is None: - self._whseed(ObjSpace) - return - else: - a = space.int_w(space.hash(w_a)) - a, x = divmod(a, 256) - a, y = divmod(a, 256) - a, z = divmod(a, 256) - x = (x + a) % 256 or 1 - y = (y + a) % 256 or 1 - z = (z + a) % 256 or 1 - self._whseed(ObjSpace, x, y, z) - whseed.unwrap_spec = ['self', ObjSpace, W_Root] - -## -------------------- pickle support ------------------- - - def __getstate__(self, space): # for pickle - return self.getstate() - - def __setstate__(self, space, state): # for pickle - self.setstate(state) - - def randrange(self, space, start, w_stop=NoneNotWrapped, step=1): - """Choose a random item from range(start, stop[, step]). - - This fixes the problem with randint() which includes the - endpoint; in Python this is usually not what you want. - Do not supply the 'int' and 'default' arguments. - """ - # This code is a bit messy to make it fast for the - # common case while still doing adequate error checking. - if w_stop is None: - if start > 0: - return space.wrap(int(self.random() * start)) - raise OperationError(space.w_ValueError, - space.wrap("empty range for randrange()")) - - # stop argument supplied. - istop = space.int_w(w_stop) - if step == 1 and start < istop: - fl = _floor(space.unwrap(self.random(space))*(istop - start)) - return space.wrap(int(start + fl)) - - if step == 1: - raise OperationError(space.w_ValueError, - space.wrap("empty range for randrange()")) - - # Non-unit step argument supplied. - if step > 0: - n = ((istop - start) + step - 1) / step - elif step < 0: - n = ((istop - start) + step + 1) / step - else: - raise OperationError(space.w_ValueError, - space.wrap("zero step for randrange()")) - - if n <= 0: - raise OperationError(space.w_ValueError, - space.wrap("empty range for randrange()")) - - res = start + step*int(space.unwrap(self.random(space)) * n) - return space.wrap(int(res)) - randrange.unwrap_spec = ['self', ObjSpace, int, W_Root, int] - - def randint(self, space, a, b): - """Return random integer in range [a, b], including both end points. - """ - return self.randrange(space, a, space.wrap(b+1)) - randint.unwrap_spec = ['self', ObjSpace, int, int] - - def choice(self, space, w_seq): - """Choose a random element from a non-empty sequence.""" - length = space.int_w(space.len(w_seq)) - ind = int(space.unwrap(self.random(space)) * length) - return space.getitem(w_seq, space.wrap(ind)) - choice.unwrap_spec = ['self', ObjSpace, W_Root] - - def shuffle(self, space, w_x, w_random=NoneNotWrapped): - """x, random=random.random -> shuffle list x in place; return None. - - Optional arg random is a 0-argument function returning a random - float in [0.0, 1.0); by default, the standard random.random. - - Note that for even rather small len(x), the total number of - permutations of x is larger than the period of most random number - generators; this implies that "most" permutations of a long - sequence can never be generated. - """ - - if w_random is None: - w_random = space.getattr(space.wrap(self), space.wrap('random')) - length = space.unwrap(space.len(w_x)) - - for i in xrange(length-1, 0, -1): - # pick an element in x[:i+1] with which to exchange x[i] - j = int(space.float_w(space.call_function(w_random)) * (i+1)) - w_i = space.wrap(i) - w_j = space.wrap(j) - w_xi = space.getitem(w_x, w_i) - w_xj = space.getitem(w_x, w_j) - space.setitem(w_x, w_i, w_xj) - space.setitem(w_x, w_j, w_xi) - shuffle.unwrap_spec = ['self', ObjSpace, W_Root, W_Root] - - def uniform(self, space, a, b): - """Get a random number in the range [a, b).""" - return space.wrap(a + (b-a) * space.unwrap(self.random(space))) - uniform.unwrap_spec = ['self', ObjSpace, int, int] - - def normalvariate(self, space, mu, sigma): - """Normal distribution. - - mu is the mean, and sigma is the standard deviation. - - """ - # mu = mean, sigma = standard deviation - - # Uses Kinderman and Monahan method. Reference: Kinderman, - # A.J. and Monahan, J.F., "Computer generation of random - # variables using the ratio of uniform deviates", ACM Trans - # Math Software, 3, (1977), pp257-260. - while 1: - u1 = space.unwrap(self.random(space)) - u2 = 1.0 - space.unwrap(self.random(space)) - z = NV_MAGICCONST*(u1-0.5)/u2 - zz = z*z/4.0 - if zz <= -_log(u2): - break - return space.wrap(mu + z*sigma) - normalvariate.unwrap_spec = ['self', ObjSpace, float, float] - - - def lognormvariate(self, space, mu, sigma): - """Log normal distribution. - - If you take the natural logarithm of this distribution, you'll get a - normal distribution with mean mu and standard deviation sigma. - mu can have any value, and sigma must be greater than zero. - - """ - return space.wrap(_exp(space.unwrap(self.normalvariate(space, mu, sigma)))) - lognormvariate.unwrap_spec = ['self', ObjSpace, float, float] - - def cunifvariate(self, space, mean, arc): - """Circular uniform distribution. - - mean is the mean angle, and arc is the range of the distribution, - centered around the mean angle. Both values must be expressed in - radians. Returned values range between mean - arc/2 and - mean + arc/2 and are normalized to between 0 and pi. - - Deprecated in version 2.3. Use: - (mean + arc * (Random.random() - 0.5)) % Math.pi - - """ - # mean: mean angle (in radians between 0 and pi) - # arc: range of distribution (in radians between 0 and pi) - - return space.wrap((mean + arc * (space.unwrap(self.random(space)) - 0.5)) % _pi) - cunifvariate.unwrap_spec = ['self', ObjSpace, float, float] - - def expovariate(self, space, lambd): - """Exponential distribution. - - lambd is 1.0 divided by the desired mean. (The parameter would be - called "lambda", but that is a reserved word in Python.) Returned - values range from 0 to positive infinity. - - """ - # lambd: rate lambd = 1/mean - # ('lambda' is a Python reserved word) - - random = self.random - u = space.unwrap(random(space)) - while u <= 1e-7: - u = space.unwrap(random(space)) - return space.wrap(-_log(u)/lambd) - expovariate.unwrap_spec = ['self', ObjSpace, float] - - def vonmisesvariate(self, space, mu, kappa): - """Circular data distribution. - - mu is the mean angle, expressed in radians between 0 and 2*pi, and - kappa is the concentration parameter, which must be greater than or - equal to zero. If kappa is equal to zero, this distribution reduces - to a uniform random angle over the range 0 to 2*pi. - - """ - # mu: mean angle (in radians between 0 and 2*pi) - # kappa: concentration parameter kappa (>= 0) - # if kappa = 0 generate uniform random angle - - # Based upon an algorithm published in: Fisher, N.I., - # "Statistical Analysis of Circular Data", Cambridge - # University Press, 1993. - - # Thanks to Magnus Kessler for a correction to the - # implementation of step 4. - - random = self.random - if kappa <= 1e-6: - return TWOPI * space.unwrap(random(space)) - - a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa) - b = (a - _sqrt(2.0 * a))/(2.0 * kappa) - r = (1.0 + b * b)/(2.0 * b) - - while 1: - u1 = space.unwrap(random(space)) - - z = _cos(_pi * u1) - f = (1.0 + r * z)/(r + z) - c = kappa * (r - f) - - u2 = space.unwrap(random(space)) - - if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)): - break - - u3 = space.unwrap(random(space)) - if u3 > 0.5: - theta = (mu % TWOPI) + _acos(f) - else: - theta = (mu % TWOPI) - _acos(f) - return space.wrap(theta) - vonmisesvariate.unwrap_spec = ['self', ObjSpace, float, float] + def jumpahead(self, n): + self._rnd.jumpahead(n) + jumpahead.unwrap_spec = ['self', int] + + def getrandbits(self, space, k): + if k <= 0: + strerror = space.wrap("number of bits must be greater than zero") + raise OperationError(space.w_ValueError, strerror) + bytes = ((k - 1) // 32 + 1) * 4 + bytesarray = [0] * bytes + for i in range(0, bytes, 4): + k -= 32 + r = self._rnd.genrand32() + if k < 0: + r >>= (32 - k) + bytesarray[i + 0] = r & r_uint(0xff) + bytesarray[i + 1] = (r >> 8) & r_uint(0xff) + bytesarray[i + 2] = (r >> 16) & r_uint(0xff) + bytesarray[i + 3] = (r >> 24) & r_uint(0xff) + + # XXX so far this is quadratic + w_result = space.newlong(0) + w_eight = space.newlong(8) + for byte in bytesarray: + w_result = space.lshift( + space.and_(w_result, space.newlong(int(byte))), w_eight) + return w_result + getrandbits.unwrap_spec = ['self', ObjSpace, int] - def gammavariate(self, space, alpha, beta): - """Gamma distribution. Not the gamma function! - - Conditions on the parameters are alpha > 0 and beta > 0. - - """ - - # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 - - # Warning: a few older sources define the gamma distribution in terms - # of alpha > -1.0 - if alpha <= 0.0 or beta <= 0.0: - raise OperationError(space.w_ValueError, - space.wrap('gammavariate: alpha and beta must be > 0.0')) - - random = self.random - if alpha > 1.0: - - # Uses R.C.H. Cheng, "The generation of Gamma - # variables with non-integral shape parameters", - # Applied Statistics, (1977), 26, No. 1, p71-74 - - ainv = _sqrt(2.0 * alpha - 1.0) - bbb = alpha - LOG4 - ccc = alpha + ainv - - while 1: - u1 = space.unwrap(random(space)) - if not 1e-7 < u1 < .9999999: - continue - u2 = 1.0 - space.unwrap(random(space)) - v = _log(u1/(1.0-u1))/ainv - x = alpha*_exp(v) - z = u1*u1*u2 - r = bbb+ccc*v-x - if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): - return space.wrap(x * beta) - - elif alpha == 1.0: - # expovariate(1) - u = space.unwrap(random(space)) - while u <= 1e-7: - u = space.unwrap(random(space)) - return space.wrap(-_log(u) * beta) - - else: # alpha is between 0 and 1 (exclusive) - - # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle - - while 1: - u = space.unwrap(random(space)) - b = (_e + alpha)/_e - p = b*u - if p <= 1.0: - x = pow(p, 1.0/alpha) - else: - # p > 1 - x = -_log((b-p)/alpha) - u1 = space.unwrap(random(space)) - if not (((p <= 1.0) and (u1 > _exp(-x))) or - ((p > 1) and (u1 > pow(x, alpha - 1.0)))): - break - return space.wrap(x * beta) - gammavariate.unwrap_spec = ['self', ObjSpace, float, float] - - def stdgamma(self, space, alpha, ainv, bbb, ccc): - # This method was (and shall remain) undocumented. - # This method is deprecated - # for the following reasons: - # 1. Returns same as .gammavariate(alpha, 1.0) - # 2. Requires caller to provide 3 extra arguments - # that are functions of alpha anyway - # 3. Can't be used for alpha < 0.5 - - # ainv = sqrt(2 * alpha - 1) - # bbb = alpha - log(4) - # ccc = alpha + ainv - - # XXX there is no warning support in pypy ! - print "The stdgamma function is deprecated; use gammavariate() instead" - - return self.gammavariate(space, alpha, 1.0) - stdgamma.unwrap_spec = ['self', ObjSpace, float, float, float, float] - - def gauss(self, space, mu, sigma): - """Gaussian distribution. - - mu is the mean, and sigma is the standard deviation. This is - slightly faster than the normalvariate() function. - - Not thread-safe without a lock around calls. - - """ - - # When x and y are two variables from [0, 1), uniformly - # distributed, then - # - # cos(2*pi*x)*sqrt(-2*log(1-y)) - # sin(2*pi*x)*sqrt(-2*log(1-y)) - # - # are two *independent* variables with normal distribution - # (mu = 0, sigma = 1). - # (Lambert Meertens) - # (corrected version; bug discovered by Mike Miller, fixed by LM) - - # Multithreading note: When two threads call this function - # simultaneously, it is possible that they will receive the - # same return value. The window is very small though. To - # avoid this, you have to use a lock around all calls. (I - # didn't want to slow this down in the serial case by using a - # lock here.) - - random = self.random - z = self.gauss_next - self.gauss_next = None - if z is None: - x2pi = space.unwrap(random(space)) * TWOPI - g2rad = _sqrt(-2.0 * _log(1.0 - space.unwrap(random(space)))) - z = _cos(x2pi) * g2rad - self.gauss_next = _sin(x2pi) * g2rad - - return space.wrap(mu + z*sigma) - gauss.unwrap_spec = ['self', ObjSpace, float, float] - -## -------------------- beta -------------------- -## See -## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470 -## for Ivan Frohne's insightful analysis of why the original implementation: -## -## def betavariate(self, alpha, beta): -## # Discrete Event Simulation in C, pp 87-88. -## -## y = self.expovariate(alpha) -## z = self.expovariate(1.0/beta) -## return z/(y+z) -## -## was dead wrong, and how it probably got that way. - - def betavariate(self, space, alpha, beta): - """Beta distribution. - - Conditions on the parameters are alpha > -1 and beta} > -1. - Returned values range between 0 and 1. - - """ - - # This version due to Janne Sinkkonen, and matches all the std - # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). - y = space.unwrap(self.gammavariate(space, alpha, 1.)) - if y == 0: - return space.wrap(0.0) - else: - return space.wrap(y / (y + space.unwrap(self.gammavariate(space, beta, 1.)))) - betavariate.unwrap_spec = ['self', ObjSpace, float, float] - - def paretovariate(self, space, alpha): - """Pareto distribution. alpha is the shape parameter.""" - # Jain, pg. 495 - - u = 1.0 - space.unwrap(self.random(space)) - return space.wrap(1.0 / pow(u, 1.0/alpha)) - paretovariate.unwrap_spec = ['self', ObjSpace, float] - - def weibullvariate(self, space, alpha, beta): - """Weibull distribution. - - alpha is the scale parameter and beta is the shape parameter. - - """ - # Jain, pg. 499; bug fix courtesy Bill Arms - - u = 1.0 - space.unwrap(self.random(space)) - return space.wrap(alpha * pow(-_log(u), 1.0/beta)) - weibullvariate.unwrap_spec = ['self', ObjSpace, float, float] - W_Random.typedef = TypeDef("W_Random", __new__ = interp2app(descr_new__), - seed = interp2app(W_Random.seed), random = interp2app(W_Random.random), + seed = interp2app(W_Random.seed), getstate = interp2app(W_Random.getstate), setstate = interp2app(W_Random.setstate), jumpahead = interp2app(W_Random.jumpahead), - _whseed = interp2app(W_Random._whseed), - whseed = interp2app(W_Random.whseed), - randrange = interp2app(W_Random.randrange), - randint = interp2app(W_Random.randint), - choice = interp2app(W_Random.choice), - shuffle = interp2app(W_Random.shuffle), - uniform = interp2app(W_Random.uniform), - normalvariate = interp2app(W_Random.normalvariate), - lognormvariate = interp2app(W_Random.lognormvariate), - cunifvariate = interp2app(W_Random.cunifvariate), - expovariate = interp2app(W_Random.expovariate), - vonmisesvariate = interp2app(W_Random.vonmisesvariate), - gammavariate = interp2app(W_Random.gammavariate), - gauss = interp2app(W_Random.gauss), - betavariate = interp2app(W_Random.betavariate), - paretovariate = interp2app(W_Random.paretovariate), - weibullvariate = interp2app(W_Random.weibullvariate), - stdgamma = interp2app(W_Random.stdgamma), - ) -_inst_map = {} - -def get_random_method(space, attrname): - try: - w_self = _inst_map[space] - except KeyError: - _inst_map[space] = w_self = W_Random(space, None) - w_method = space.getattr(w_self,space.wrap(attrname)) - return w_method + getrandbits = interp2app(W_Random.getrandbits), +) Modified: pypy/dist/pypy/module/_random/test/test_random.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_random.py (original) +++ pypy/dist/pypy/module/_random/test/test_random.py Sun Sep 17 20:33:04 2006 @@ -1,8 +1,6 @@ import py from pypy.conftest import gettestobjspace -py.test.skip("XXX missing _random.sample()") - class AppTestRandom: def setup_class(cls): cls.space = gettestobjspace(usemodules=['_random']) @@ -11,6 +9,41 @@ import _random _random.__dict__ # crashes if entries in __init__.py can't be resolved - # XXX MISSING TESTS XXX - # XXX MISSING TESTs XXX - # XXX MISSING TESTS XXX + def test_random(self): + import _random + # XXX quite a bad test + rnd = _random.Random(1) + lst1 = [rnd.random() for i in range(100)] + rnd.seed(1) + lst2 = [rnd.random() for i in range(100)] + assert lst1 == lst2 + smaller = 0 + for elt in lst1: + assert 0 <= elt <= 1 + if elt < 0.5: + smaller += 1 + # quite unlikely to fail, but well + assert smaller > 10 + + def test_getstate_setstate(self): + import _random + rnd1 = _random.Random() + rnd1.random() + rnd2 = _random.Random() + assert rnd1.getstate() != rnd2.getstate() + rnd1.setstate(rnd2.getstate()) + assert [rnd1.random() for i in range(100)] == [ + rnd2.random() for i in range(100)] + + def test_seed(self): + import _random + rnd = _random.Random() + rnd.seed() + obj = "spam and eggs" + nums = [] + for o in [obj, hash(obj), -hash(obj)]: + rnd.seed(o) + nums.append([rnd.random() for i in range(100)]) + n1 = nums[0] + for n2 in nums[1:]: + assert n1 == n2 From cfbolz at codespeak.net Sun Sep 17 20:48:50 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 20:48:50 +0200 (CEST) Subject: [pypy-svn] r32426 - pypy/dist/pypy/module/_random Message-ID: <20060917184850.E95CF10071@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 20:48:49 2006 New Revision: 32426 Modified: pypy/dist/pypy/module/_random/interp_random.py Log: typo Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Sun Sep 17 20:48:49 2006 @@ -69,7 +69,7 @@ for i in range(rpy_random.N): w_item = space.getitem(w_state, space.newint(i)) self._rnd.state[i] = r_uint(space.int_w(w_item)) - w_item = space.getitem(w_state, space.newint(i)) + w_item = space.getitem(w_state, space.newint(rpy_random.N)) self._rnd.index = r_uint(space.int_w(w_item)) setstate.unwrap_spec = ['self', ObjSpace, W_Root] From cfbolz at codespeak.net Sun Sep 17 21:13:47 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Sep 2006 21:13:47 +0200 (CEST) Subject: [pypy-svn] r32427 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060917191347.DC6F91006C@code0.codespeak.net> Author: cfbolz Date: Sun Sep 17 21:13:45 2006 New Revision: 32427 Modified: pypy/dist/pypy/module/_random/interp_random.py pypy/dist/pypy/module/_random/test/test_random.py Log: everything not tested is broken. So was the getrandbits method. Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Sun Sep 17 21:13:45 2006 @@ -87,7 +87,7 @@ k -= 32 r = self._rnd.genrand32() if k < 0: - r >>= (32 - k) + k >>= (32 - k) bytesarray[i + 0] = r & r_uint(0xff) bytesarray[i + 1] = (r >> 8) & r_uint(0xff) bytesarray[i + 2] = (r >> 16) & r_uint(0xff) @@ -98,7 +98,7 @@ w_eight = space.newlong(8) for byte in bytesarray: w_result = space.lshift( - space.and_(w_result, space.newlong(int(byte))), w_eight) + space.or_(w_result, space.newlong(int(byte))), w_eight) return w_result getrandbits.unwrap_spec = ['self', ObjSpace, int] Modified: pypy/dist/pypy/module/_random/test/test_random.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_random.py (original) +++ pypy/dist/pypy/module/_random/test/test_random.py Sun Sep 17 21:13:45 2006 @@ -39,11 +39,19 @@ import _random rnd = _random.Random() rnd.seed() - obj = "spam and eggs" - nums = [] - for o in [obj, hash(obj), -hash(obj)]: - rnd.seed(o) - nums.append([rnd.random() for i in range(100)]) - n1 = nums[0] - for n2 in nums[1:]: - assert n1 == n2 + for obj in ["spam and eggs", 3.14, 1+2j, 'a', tuple('abc')]: + nums = [] + for o in [obj, hash(obj), -hash(obj)]: + rnd.seed(o) + nums.append([rnd.random() for i in range(100)]) + n1 = nums[0] + for n2 in nums[1:]: + assert n1 == n2 + + def test_randbits(self): + import math + import _random + rnd = _random.Random() + for n in range(10, 200, 10): + n = rnd.getrandbits(n) + assert int(math.log(n) / math.log(2)) <= n From arigo at codespeak.net Mon Sep 18 10:22:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Sep 2006 10:22:42 +0200 (CEST) Subject: [pypy-svn] r32431 - pypy/dist/pypy/module/_random Message-ID: <20060918082242.B57841007A@code0.codespeak.net> Author: arigo Date: Mon Sep 18 10:22:39 2006 New Revision: 32431 Modified: pypy/dist/pypy/module/_random/interp_random.py Log: Kill unused imports. Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Mon Sep 18 10:22:39 2006 @@ -5,10 +5,6 @@ from pypy.rpython.rarithmetic import r_uint from pypy.module._random import rpy_random -from math import log as _log, exp as _exp, pi as _pi, e as _e -from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin -from math import floor as _floor - import time def descr_new__(space, w_subtype, w_anything=NoneNotWrapped): From mwh at codespeak.net Mon Sep 18 10:40:04 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 18 Sep 2006 10:40:04 +0200 (CEST) Subject: [pypy-svn] r32432 - in pypy/branch/kill-keepalives/pypy/rpython: . test Message-ID: <20060918084004.E3F6710075@code0.codespeak.net> Author: mwh Date: Mon Sep 18 10:40:03 2006 New Revision: 32432 Modified: pypy/branch/kill-keepalives/pypy/rpython/rptr.py pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py Log: rtype the access of an embedded gcstruct that is the first element of a gcstruct as a cast_pointer. Modified: pypy/branch/kill-keepalives/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/rptr.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/rptr.py Mon Sep 18 10:40:03 2006 @@ -36,7 +36,10 @@ return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): - if isinstance(hop.r_result, InteriorPtrRepr): + if (attr, FIELD_TYPE) == self.lowleveltype.TO._first_struct(): + return hop.genop('cast_pointer', [hop.inputarg(self, 0)], + resulttype=hop.r_result.lowleveltype) + elif isinstance(hop.r_result, InteriorPtrRepr): return hop.genop('same_as', [hop.inputarg(self, 0)], resulttype=self.lowleveltype) else: Modified: pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/test/test_rptr.py Mon Sep 18 10:40:03 2006 @@ -205,6 +205,23 @@ py.test.raises(TypeError, "interpret(wrong, [1, 2])") +def test_first_subfield_access_is_cast_pointer(): + B = GcStruct("B", ('x', Signed)) + C = GcStruct("C", ('super', B), ('y', Signed)) + def f(): + c = malloc(C) + c.super.x = 1 + c.y = 2 + return c.super.x + c.y + s, t = ll_rtype(f, []) + from pypy.translator.translator import graphof + from pypy.objspace.flow.model import summary + graph = graphof(t, f) + graphsum = summary(graph) + assert 'getsubstruct' not in graphsum + assert 'cast_pointer' in graphsum + + def test_interior_ptr(): S = Struct("S", ('x', Signed)) From cfbolz at codespeak.net Mon Sep 18 10:48:10 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 18 Sep 2006 10:48:10 +0200 (CEST) Subject: [pypy-svn] r32433 - pypy/extradoc/sprintinfo/ddorf2006b Message-ID: <20060918084810.8EF2210080@code0.codespeak.net> Author: cfbolz Date: Mon Sep 18 10:48:09 2006 New Revision: 32433 Modified: pypy/extradoc/sprintinfo/ddorf2006b/announce.txt Log: tried to add things about py.test and wp13. Modified: pypy/extradoc/sprintinfo/ddorf2006b/announce.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006b/announce.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006b/announce.txt Mon Sep 18 10:48:09 2006 @@ -31,6 +31,18 @@ - persistence (save an "image" of a running program, or a part of it) - security (in many possible senses of the word) +* Working on py.test testing tool: + + - py.test recently grew some distribution features which are still rough + around the edges and could use improvement + + - there are some more ideas for features of py.test around, like adding + profiling capabilities (and more) + +* Work on the PyPy build tool: There are some plans to provide a tool that + allows one to flexibly configure PyPy and to also request builds from a set + of build servers. If there is interest there could be work in this area. + * and as always, there is the topic of implementing or completing core extension modules (e.g. socket...). This is hacking with a mix of ctypes and RPython. From arigo at codespeak.net Mon Sep 18 11:28:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Sep 2006 11:28:23 +0200 (CEST) Subject: [pypy-svn] r32437 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20060918092823.02F6810076@code0.codespeak.net> Author: arigo Date: Mon Sep 18 11:28:22 2006 New Revision: 32437 Modified: pypy/dist/pypy/interpreter/astcompiler/symbols.py Log: Look away Modified: pypy/dist/pypy/interpreter/astcompiler/symbols.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/symbols.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/symbols.py Mon Sep 18 11:28:22 2006 @@ -501,7 +501,12 @@ if scope.firstReturnWithArgument is None: scope.firstReturnWithArgument = node node.value.accept(self) - + + def visitCondExpr(self, node): + issue_warning(self.space, "conditional expression", + node.filename, node.lineno) + ast.ASTVisitor.visitCondExpr(self, node) + def sort(l): l = l[:] l.sort() From ericvrp at codespeak.net Mon Sep 18 13:37:28 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 18 Sep 2006 13:37:28 +0200 (CEST) Subject: [pypy-svn] r32440 - pypy/dist/pypy/translator/llvm Message-ID: <20060918113728.59E561007B@code0.codespeak.net> Author: ericvrp Date: Mon Sep 18 13:37:26 2006 New Revision: 32440 Modified: pypy/dist/pypy/translator/llvm/opwriter.py Log: Add missing llong_neg operation to genllvm to fix translation. Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Mon Sep 18 13:37:26 2006 @@ -197,6 +197,8 @@ # XXX rxe: Surely that cant be right? uint_neg = int_neg + llong_neg = int_neg + def float_neg(self, opr): self._generic_neg(opr, "0.0") From arigo at codespeak.net Mon Sep 18 15:08:31 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Sep 2006 15:08:31 +0200 (CEST) Subject: [pypy-svn] r32441 - pypy/dist/pypy/module/rctime Message-ID: <20060918130831.8BC1610076@code0.codespeak.net> Author: arigo Date: Mon Sep 18 15:08:29 2006 New Revision: 32441 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: (arre, arigo) Use the proper overflow-detecting variant of int(). Thanks Ben Young. Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Sep 18 15:08:29 2006 @@ -4,6 +4,7 @@ from pypy.rpython.rctypes.aerrno import geterrno from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace +from pypy.rpython.rarithmetic import ovfcheck_float_to_int from ctypes import * import math import os @@ -182,7 +183,7 @@ secs = 0.0 msecs = secs * 1000.0 try: - msecs = int(msecs) + msecs = ovfcheck_float_to_int(msecs) except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("sleep length is too large")) From arigo at codespeak.net Mon Sep 18 15:31:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Sep 2006 15:31:25 +0200 (CEST) Subject: [pypy-svn] r32442 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060918133125.9914910076@code0.codespeak.net> Author: arigo Date: Mon Sep 18 15:31:23 2006 New Revision: 32442 Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (arre, arigo) (Skipped) test for 'yellow calls'. Typo. Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Mon Sep 18 15:31:23 2006 @@ -426,7 +426,7 @@ myframe = jitstate.frame if myframe.local_boxes: # else it's a green Void return jitstate.returnbox = myframe.local_boxes[0] - # ^^^ fetched by an 'fetch_return' operation + # ^^^ fetched by a 'fetch_return' operation jitstate.frame = myframe.backframe jitstate.exitindex = -1 return jitstate Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Mon Sep 18 15:31:23 2006 @@ -355,6 +355,11 @@ return 'oopspec' elif (originalconcretetype(s_result) is not lltype.Void and isinstance(r_result, GreenRepr)): + for v in spaceop.args: + s_arg = self.annotator.binding(v) + r_arg = self.getrepr(s_arg) + if not isinstance(r_arg, GreenRepr): + return 'yellow' return 'green' else: return 'red' Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Mon Sep 18 15:31:23 2006 @@ -885,3 +885,17 @@ res = self.timeshift(ll_function, [3], [], policy=P_NOVIRTUAL) assert res == 3 + + def test_split_on_green_return(self): + py.test.skip("in-progress") + def ll_two(x): + if x > 0: + return 17 + else: + return 22 + def ll_function(x): + n = ll_two(x) + return n+1 + res = self.timeshift(ll_function, [-70], []) + assert res == 23 + self.check_insns({'int_gt': 1}) From arigo at codespeak.net Mon Sep 18 17:07:01 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Sep 2006 17:07:01 +0200 (CEST) Subject: [pypy-svn] r32449 - pypy/dist/pypy/jit/timeshifter Message-ID: <20060918150701.1CA4910078@code0.codespeak.net> Author: arigo Date: Mon Sep 18 17:07:00 2006 New Revision: 32449 Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py Log: (arre, arigo) Typo. Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Mon Sep 18 17:07:00 2006 @@ -215,7 +215,7 @@ # Then we make a new block based on this new state. replace_memo = rvalue.copy_memo() for box in outgoingvarboxes: - box = box.forcevar(jitstate.curbuilder, replace_memo) + box.forcevar(jitstate.curbuilder, replace_memo) if replace_memo.boxes: jitstate.replace(replace_memo) start_new_block(states_dic, jitstate, key) From jum at codespeak.net Mon Sep 18 22:50:06 2006 From: jum at codespeak.net (jum at codespeak.net) Date: Mon, 18 Sep 2006 22:50:06 +0200 (CEST) Subject: [pypy-svn] r32468 - pypy/dist/pypy/doc Message-ID: <20060918205006.4A13910077@code0.codespeak.net> Author: jum Date: Mon Sep 18 22:50:05 2006 New Revision: 32468 Modified: pypy/dist/pypy/doc/svn-help.txt Log: Updated ppc binary to latest version. Modified: pypy/dist/pypy/doc/svn-help.txt ============================================================================== --- pypy/dist/pypy/doc/svn-help.txt (original) +++ pypy/dist/pypy/doc/svn-help.txt Mon Sep 18 22:50:05 2006 @@ -146,7 +146,7 @@ .. _website: http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B259403 .. _GUI: http://tortoisesvn.tigris.org/servlets/ProjectDocumentList?folderID=616 -.. _MacOS: http://codespeak.net/~jum/svn-1.3.1-darwin-ppc.tar.gz +.. _MacOS: http://codespeak.net/~jum/svn-1.4.0-darwin-ppc.tar.gz .. _versions: http://subversion.tigris.org/project_packages.html .. _Win: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4B6140F9-2D36-4977-8FA1-6F8A0F5DCA8F .. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1 From cfbolz at codespeak.net Tue Sep 19 00:16:07 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Sep 2006 00:16:07 +0200 (CEST) Subject: [pypy-svn] r32469 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060918221607.27FD310078@code0.codespeak.net> Author: cfbolz Date: Tue Sep 19 00:16:04 2006 New Revision: 32469 Modified: pypy/dist/pypy/module/_random/interp_random.py pypy/dist/pypy/module/_random/test/test_mersenne.py pypy/dist/pypy/module/_random/test/test_random.py Log: oops, all seeds were effectively the same :-( Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Tue Sep 19 00:16:04 2006 @@ -35,15 +35,18 @@ w_n = space.abs(space.hash(w_n)) key = [] w_one = space.newlong(1) + w_two = space.newlong(2) w_thirtytwo = space.newlong(32) # 0xffffffff - w_masklower = space.sub(space.pow(w_one, w_thirtytwo, space.w_None), + w_masklower = space.sub(space.pow(w_two, w_thirtytwo, space.w_None), w_one) while space.is_true(w_n): w_chunk = space.and_(w_n, w_masklower) chunk = r_uint(space.int_w(w_chunk)) key.append(chunk) w_n = space.rshift(w_n, w_thirtytwo) + if not key: + key = [r_uint(0)] self._rnd.init_by_array(key) seed.unwrap_spec = ['self', ObjSpace, W_Root] Modified: pypy/dist/pypy/module/_random/test/test_mersenne.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_mersenne.py (original) +++ pypy/dist/pypy/module/_random/test/test_mersenne.py Tue Sep 19 00:16:04 2006 @@ -22,6 +22,9 @@ assert rnd.state[:14] == [2147483648, 1269538435, 699006892, 381364451, 172015551, 3237099449, 3609464087, 2187366456, 654585064, 2665903765, 3735624613, 1241943673, 2038528247, 3774211972] + # try arrays of various sizes to test for corner cases + for size in [N, N - 1, N + 1, N // 2, 2 * N]: + rnd.init_by_array(range(N)) def test_jumpahead(): rnd = Random() Modified: pypy/dist/pypy/module/_random/test/test_random.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_random.py (original) +++ pypy/dist/pypy/module/_random/test/test_random.py Tue Sep 19 00:16:04 2006 @@ -39,14 +39,30 @@ import _random rnd = _random.Random() rnd.seed() + different_nums = [] for obj in ["spam and eggs", 3.14, 1+2j, 'a', tuple('abc')]: nums = [] for o in [obj, hash(obj), -hash(obj)]: rnd.seed(o) nums.append([rnd.random() for i in range(100)]) n1 = nums[0] + different_nums.append(n1) for n2 in nums[1:]: assert n1 == n2 + n1 = different_nums[0] + for n2 in different_nums[1:]: + assert n1 != n2 + + def test_seedargs(self): + import _random + rnd = _random.Random() + for arg in [None, 0, 0L, 1, 1L, -1, -1L, 10**20, -(10**20), + 3.14, 1+2j, 'a', tuple('abc')]: + rnd.seed(arg) + for arg in [range(3), dict(one=1)]: + raises(TypeError, rnd.seed, arg) + raises(TypeError, rnd.seed, 1, 2) + raises(TypeError, type(rnd), []) def test_randbits(self): import math From cfbolz at codespeak.net Tue Sep 19 00:32:59 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Sep 2006 00:32:59 +0200 (CEST) Subject: [pypy-svn] r32470 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060918223259.E462510078@code0.codespeak.net> Author: cfbolz Date: Tue Sep 19 00:32:57 2006 New Revision: 32470 Modified: pypy/dist/pypy/module/_random/interp_random.py pypy/dist/pypy/module/_random/test/test_random.py Log: very ugly way to get an unsigned int out of a long :-( Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Tue Sep 19 00:32:57 2006 @@ -42,7 +42,14 @@ w_one) while space.is_true(w_n): w_chunk = space.and_(w_n, w_masklower) - chunk = r_uint(space.int_w(w_chunk)) + try: + chunk = r_uint(space.int_w(w_chunk)) + except OperationError, e: + # XXX just assuming that it is an OverflowError + # should only happen on 32 bit machines, so the following is + # correct + w_neg = space.sub(space.sub(w_chunk, w_masklower), w_one) + chunk = r_uint(space.int_w(w_neg)) key.append(chunk) w_n = space.rshift(w_n, w_thirtytwo) if not key: Modified: pypy/dist/pypy/module/_random/test/test_random.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_random.py (original) +++ pypy/dist/pypy/module/_random/test/test_random.py Tue Sep 19 00:32:57 2006 @@ -57,7 +57,7 @@ import _random rnd = _random.Random() for arg in [None, 0, 0L, 1, 1L, -1, -1L, 10**20, -(10**20), - 3.14, 1+2j, 'a', tuple('abc')]: + 3.14, 1+2j, 'a', tuple('abc'), 0xffffffffffL]: rnd.seed(arg) for arg in [range(3), dict(one=1)]: raises(TypeError, rnd.seed, arg) From cfbolz at codespeak.net Tue Sep 19 00:37:09 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Sep 2006 00:37:09 +0200 (CEST) Subject: [pypy-svn] r32471 - pypy/dist/pypy/module/_random Message-ID: <20060918223709.E2F9010078@code0.codespeak.net> Author: cfbolz Date: Tue Sep 19 00:37:07 2006 New Revision: 32471 Modified: pypy/dist/pypy/module/_random/interp_random.py Log: it seems we have space.uint_w too. thanks samuele Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Tue Sep 19 00:37:07 2006 @@ -42,14 +42,7 @@ w_one) while space.is_true(w_n): w_chunk = space.and_(w_n, w_masklower) - try: - chunk = r_uint(space.int_w(w_chunk)) - except OperationError, e: - # XXX just assuming that it is an OverflowError - # should only happen on 32 bit machines, so the following is - # correct - w_neg = space.sub(space.sub(w_chunk, w_masklower), w_one) - chunk = r_uint(space.int_w(w_neg)) + chunk = space.uint_w(w_chunk) key.append(chunk) w_n = space.rshift(w_n, w_thirtytwo) if not key: @@ -74,9 +67,9 @@ raise OperationError(space.w_TypeError, errstring) for i in range(rpy_random.N): w_item = space.getitem(w_state, space.newint(i)) - self._rnd.state[i] = r_uint(space.int_w(w_item)) + self._rnd.state[i] = space.uint_w(w_item) w_item = space.getitem(w_state, space.newint(rpy_random.N)) - self._rnd.index = r_uint(space.int_w(w_item)) + self._rnd.index = space.uint_w(w_item) setstate.unwrap_spec = ['self', ObjSpace, W_Root] def jumpahead(self, n): From arigo at codespeak.net Tue Sep 19 12:48:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 12:48:23 +0200 (CEST) Subject: [pypy-svn] r32480 - pypy/branch/timeshift-refactoring Message-ID: <20060919104823.960FA10078@code0.codespeak.net> Author: arigo Date: Tue Sep 19 12:48:22 2006 New Revision: 32480 Added: pypy/branch/timeshift-refactoring/ - copied from r32479, pypy/dist/ Log: (arre, arigo) A branch in which to refactor the timeshifter. From arigo at codespeak.net Tue Sep 19 12:50:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 12:50:50 +0200 (CEST) Subject: [pypy-svn] r32481 - pypy/branch/timeshift-refactoring/pypy/jit/timeshifter Message-ID: <20060919105050.C843110078@code0.codespeak.net> Author: arigo Date: Tue Sep 19 12:50:49 2006 New Revision: 32481 Added: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/bak-timeshift.py - copied unchanged from r32480, pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/timeshift.py Removed: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/timeshift.py Log: (arre, arigo) Move this file out of the way. From mwh at codespeak.net Tue Sep 19 13:22:39 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Sep 2006 13:22:39 +0200 (CEST) Subject: [pypy-svn] r32486 - in pypy/branch/kill-keepalives/pypy: rpython/lltypesystem rpython/memory translator/backendopt Message-ID: <20060919112239.5FEED10078@code0.codespeak.net> Author: mwh Date: Tue Sep 19 13:22:38 2006 New Revision: 32486 Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Log: attempt number #12214321 at climbing out of the rctypes hole. this one adds a local_raw_malloc operation and a step in the gctransformer to get rid of them again. doesn't work, checking in to get onto a local machine and use --view. Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py Tue Sep 19 13:22:38 2006 @@ -329,6 +329,7 @@ # __________ address operations __________ 'raw_malloc': LLOp(canraise=(MemoryError,)), + 'local_raw_malloc': LLOp(canraise=(MemoryError,)), 'raw_malloc_usage': LLOp(sideeffects=False), 'raw_free': LLOp(), 'raw_memclear': LLOp(), Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Tue Sep 19 13:22:38 2006 @@ -3,7 +3,7 @@ from pypy.rpython.lltypesystem.lloperation import llop, LL_OPERATIONS from pypy.objspace.flow.model import SpaceOperation, Variable, Constant, \ c_last_exception, FunctionGraph, Block, Link, checkgraph -from pypy.translator.unsimplify import varoftype +from pypy.translator.unsimplify import varoftype, copyvar from pypy.translator.unsimplify import insert_empty_block from pypy.translator.unsimplify import insert_empty_startblock from pypy.translator.unsimplify import starts_with_empty_block @@ -81,6 +81,7 @@ return self.seen_graphs[graph] = True self.links_to_split = {} # link -> vars to pop_alive across the link + self.seen_local_raw_malloc = False # for sanity, we need an empty block at the start of the graph if not starts_with_empty_block(graph): @@ -107,12 +108,66 @@ if starts_with_empty_block(graph): remove_empty_startblock(graph) + if self.seen_local_raw_malloc: + self.remove_local_mallocs(graph) + self.links_to_split = None v = Variable('vanishing_exc_value') v.concretetype = self.get_lltype_of_exception_value() graph.exc_cleanup = (v, self.pop_alive(v)) return is_borrowed # xxx for tests only + def remove_local_mallocs(self, graph): + from pypy.translator.backendopt.malloc import compute_lifetimes + lifetimes = compute_lifetimes(graph) + for info in lifetimes: + cand = True + # XXX do checking + for cp in info.creationpoints: + if cp[0] != "op": + cand = False + break + op = cp[2] + if op.opname != 'local_raw_malloc': + cand = False + break + op.opname = 'raw_malloc' + if cand: + for cp in info.creationpoints: + cp[2].opname = 'raw_malloc' + + variables_by_block = {} + for block, var in info.variables: + vars = variables_by_block.setdefault(block, {}) + vars[var] = True + for block, vars in variables_by_block.iteritems(): + links_with_a_var = [] + links_without_a_var = [] + for link in block.exits: + if set(vars) ^ set(link.args): + links_with_a_var.append(link) + else: + links_without_a_var.append(link) + #if not links_without_a_var: + # continue + for link in links_without_a_var: + for v in vars: + if v.concretetype == llmemory.Address: + break + newblock = insert_empty_block(None, link) + link.args.append(v) + newblock.inputargs.append(copyvar(None, v)) + if v.concretetype != llmemory.Address: + newv = varoftype(llmemory.Address) + newblock.operations.append(SpaceOperation( + "cast_ptr_to_adr", [newblock.inputargs[-1]], newv)) + v = newv + else: + v = newblock.inputargs[-1] + newblock.operations.append(SpaceOperation( + "raw_free", [v], varoftype(lltype.Void))) + checkgraph(graph) + def compute_borrowed_vars(self, graph): # the input args are borrowed, and stay borrowed for as long as they # are not merged with other values. @@ -271,6 +326,10 @@ replace_setinteriorfield = replace_setfield replace_setarrayitem = replace_setfield + def replace_local_raw_malloc(self, op, livevars, block): + self.seen_local_raw_malloc = True + return [op] + def replace_safe_call(self, op, livevars, block): return [SpaceOperation("direct_call", op.args, op.result)] Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Tue Sep 19 13:22:38 2006 @@ -341,6 +341,15 @@ S = op.args[0].concretetype.TO fldnames = [a.value for a in op.args[1:-1]] key = key_for_field_access(S, *fldnames) + if len(fldnames) == 1 and fldnames[0] in fields_to_raw_free and not isinstance(op.args[2], Constant): + # find the raw malloc and replace it with a local_raw_malloc + # XXX delicate in the extreme! + i = -1 + while newops[i].opname != 'raw_malloc': + i -= 1 + newops[i] = SpaceOperation("local_raw_malloc", + newops[i].args, + newops[i].result) assert key in newvarsmap if key in accessed_substructs: c_name = Constant('data', lltype.Void) @@ -429,12 +438,12 @@ newargs.append(arg) link.args[:] = newargs - if not var_exits: - for field in fields_to_raw_free: - newops.append(SpaceOperation("flavored_free", - [Constant("raw", lltype.Void), - newvarsmap[key_for_field_access(STRUCT, field)]], - varoftype(lltype.Void))) +## if not var_exits: +## for field in fields_to_raw_free: +## newops.append(SpaceOperation("flavored_free", +## [Constant("raw", lltype.Void), +## newvarsmap[key_for_field_access(STRUCT, field)]], +## varoftype(lltype.Void))) if insert_keepalive and last_removed_access is not None: keepalives = [] From arigo at codespeak.net Tue Sep 19 13:23:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 13:23:17 +0200 (CEST) Subject: [pypy-svn] r32487 - in pypy/branch/timeshift-refactoring/pypy/jit: hintannotator timeshifter timeshifter/test Message-ID: <20060919112317.49AAC10078@code0.codespeak.net> Author: arigo Date: Tue Sep 19 13:23:14 2006 New Revision: 32487 Added: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py (contents, props changed) Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/annotator.py pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py Log: (arre, arigo) First test passes again in the refactored world. (Intermediate check-in...) Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/annotator.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/annotator.py Tue Sep 19 13:23:14 2006 @@ -20,9 +20,6 @@ flowgraph = desc.specialize(input_args_hs) return self.build_graph_types(flowgraph, input_args_hs) - def simplify(self): - pass - def consider_op_malloc(self, hs_TYPE): TYPE = hs_TYPE.const if getattr(self.policy, 'novirtualcontainer', False): Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py Tue Sep 19 13:23:14 2006 @@ -65,6 +65,7 @@ self.descs = {} self.tsgraph_maximal_call_families = UnionFind(TsGraphCallFamily) self.annotator = hannotator + self.tsgraphsigs = {} # circular imports hack global hintmodel from pypy.jit.hintannotator import model as hintmodel @@ -109,7 +110,13 @@ return origin def compute_at_fixpoint(self): - pass + # compute and cache the signature of the graphs before they are + # modified by further code + ha = self.annotator + for tsgraph in ha.translator.graphs: + sig_hs = ([ha.binding(v) for v in tsgraph.getargs()], + ha.binding(tsgraph.getreturnvar())) + self.tsgraphsigs[tsgraph] = sig_hs def immutableconstant(self, const): res = hintmodel.SomeLLAbstractConstant(const.concretetype, {}) Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py Tue Sep 19 13:23:14 2006 @@ -42,10 +42,11 @@ _opdesc_cache = {} def make_opdesc(hop): + from pypy.jit.timeshifter.rtyper import originalconcretetype hrtyper = hop.rtyper op_key = (hrtyper.RGenOp, hop.spaceop.opname, - tuple([hrtyper.originalconcretetype(s_arg) for s_arg in hop.args_s]), - hrtyper.originalconcretetype(hop.s_result)) + tuple([originalconcretetype(s_arg) for s_arg in hop.args_s]), + originalconcretetype(hop.s_result)) try: return _opdesc_cache[op_key] except KeyError: @@ -253,7 +254,8 @@ def getexitindex(jitstate): return jitstate.exitindex -def save_locals(jitstate, redboxes): +def save_locals(jitstate, *redboxes): + redboxes = list(redboxes) assert None not in redboxes jitstate.frame.local_boxes = redboxes @@ -415,18 +417,17 @@ def enter_graph(jitstate): jitstate.frame = VirtualFrame(jitstate.frame, [], []) -def leave_graph(return_queue, return_cache): - for jitstate in return_queue[:-1]: - res = retrieve_jitstate_for_merge(return_cache, jitstate, (), - # XXX strange next argument - jitstate.frame.local_boxes) - assert res is True # finished - frozen, block = return_cache[()] - jitstate = return_queue[-1] +def leave_graph(jitstate): +## for jitstate in return_queue[:-1]: +## res = retrieve_jitstate_for_merge(return_cache, jitstate, (), +## # XXX strange next argument +## jitstate.frame.local_boxes) +## assert res is True # finished +## frozen, block = return_cache[()] +## jitstate = return_queue[-1] myframe = jitstate.frame if myframe.local_boxes: # else it's a green Void return jitstate.returnbox = myframe.local_boxes[0] # ^^^ fetched by a 'fetch_return' operation jitstate.frame = myframe.backframe - jitstate.exitindex = -1 - return jitstate +## jitstate.exitindex = -1 Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Tue Sep 19 13:23:14 2006 @@ -10,7 +10,9 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.hintannotator import model as hintmodel from pypy.jit.hintannotator import container as hintcontainer -from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer +from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, oop +from pypy.jit.timeshifter.transform import HintGraphTransformer +from pypy.jit.codegen import model as cgmodel class HintTypeSystem(LowLevelTypeSystem): name = "hinttypesystem" @@ -44,19 +46,153 @@ class HintRTyper(RPythonTyper): - def __init__(self, hannotator, timeshifter): + def __init__(self, hannotator, rtyper, RGenOp): RPythonTyper.__init__(self, hannotator, type_system=HintTypeSystem.instance) + self.rtyper = rtyper + self.RGenOp = RGenOp self.green_reprs = PRECOMPUTED_GREEN_REPRS.copy() self.red_reprs = {} self.color_cache = {} - self.timeshifter = timeshifter - self.RGenOp = timeshifter.RGenOp - originalconcretetype = staticmethod(originalconcretetype) + self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper) + self.timeshift_mapping = {} + self.sigs = {} + + (self.s_CodeGenerator, + self.r_CodeGenerator) = self.s_r_instanceof(cgmodel.CodeGenerator) + (self.s_JITState, + self.r_JITState) = self.s_r_instanceof(rtimeshift.JITState) + (self.s_RedBox, + self.r_RedBox) = self.s_r_instanceof(rvalue.RedBox) + (self.s_OopSpecDesc, + self.r_OopSpecDesc) = self.s_r_instanceof(oop.OopSpecDesc) + (self.s_ConstOrVar, + self.r_ConstOrVar) = self.s_r_instanceof(cgmodel.GenVarOrConst) + (self.s_Block, + self.r_Block) = self.s_r_instanceof(cgmodel.CodeGenBlock) + + self.etrafo = hannotator.exceptiontransformer + self.cexcdata = self.etrafo.cexcdata + self.exc_data_ptr = self.cexcdata.value + gv_excdata = RGenOp.constPrebuiltGlobal(self.exc_data_ptr) + LL_EXC_TYPE = rtyper.exceptiondata.lltype_of_exception_type + LL_EXC_VALUE = rtyper.exceptiondata.lltype_of_exception_value + null_exc_type_box = rvalue.redbox_from_prebuilt_value(RGenOp, + lltype.nullptr(LL_EXC_TYPE.TO)) + null_exc_value_box = rvalue.redbox_from_prebuilt_value(RGenOp, + lltype.nullptr(LL_EXC_VALUE.TO)) + + p = self.etrafo.rpyexc_fetch_type_ptr.value + gv_rpyexc_fetch_type = RGenOp.constPrebuiltGlobal(p) + tok_fetch_type = RGenOp.sigToken(lltype.typeOf(p).TO) + kind_etype = RGenOp.kindToken(LL_EXC_TYPE) + + p = self.etrafo.rpyexc_fetch_value_ptr.value + gv_rpyexc_fetch_value = RGenOp.constPrebuiltGlobal(p) + tok_fetch_value = RGenOp.sigToken(lltype.typeOf(p).TO) + kind_evalue = RGenOp.kindToken(LL_EXC_VALUE) + + p = self.etrafo.rpyexc_clear_ptr.value + gv_rpyexc_clear = RGenOp.constPrebuiltGlobal(p) + tok_clear = RGenOp.sigToken(lltype.typeOf(p).TO) + + p = self.etrafo.rpyexc_raise_ptr.value + gv_rpyexc_raise = RGenOp.constPrebuiltGlobal(p) + tok_raise = RGenOp.sigToken(lltype.typeOf(p).TO) + + def fetch_global_excdata(jitstate): + builder = jitstate.curbuilder + gv_etype = builder.genop_call(tok_fetch_type, + gv_rpyexc_fetch_type, []) + gv_evalue = builder.genop_call(tok_fetch_value, + gv_rpyexc_fetch_value, []) + builder.genop_call(tok_clear, gv_rpyexc_clear, []) + etypebox = rvalue.PtrRedBox(kind_etype, gv_etype) + evaluebox = rvalue.PtrRedBox(kind_evalue, gv_evalue) + rtimeshift.setexctypebox (jitstate, etypebox) + rtimeshift.setexcvaluebox(jitstate, evaluebox) + self.fetch_global_excdata = fetch_global_excdata + + def store_global_excdata(jitstate): + builder = jitstate.curbuilder + etypebox = jitstate.exc_type_box + if etypebox.is_constant(): + ll_etype = rvalue.ll_getvalue(etypebox, llmemory.Address) + if not ll_etype: + return # we known there is no exception set + evaluebox = jitstate.exc_value_box + gv_etype = etypebox .getgenvar(builder) + gv_evalue = evaluebox.getgenvar(builder) + builder.genop_call(tok_raise, + gv_rpyexc_raise, [gv_etype, gv_evalue]) + self.store_global_excdata = store_global_excdata + + def ll_fresh_jitstate(builder): + return rtimeshift.JITState(builder, None, + null_exc_type_box, + null_exc_value_box) + self.ll_fresh_jitstate = ll_fresh_jitstate + + def ll_finish_jitstate(jitstate, graphsigtoken): + returnbox = rtimeshift.getreturnbox(jitstate) + gv_ret = returnbox.getgenvar(jitstate.curbuilder) + store_global_excdata(jitstate) + jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret) + self.ll_finish_jitstate = ll_finish_jitstate + + def specialize(self, view=False): + """ + Driver for running the timeshifter. + """ + graphs = self.annotator.translator.graphs + if view: + for graph in graphs: + self.transform_graph(graph) + self.annotator.translator.view() # in the middle + for graph in graphs: + self.timeshift_graph(graph) + + else: + # do the whole transformation graph-by-graph if there is no + # need to view the intermediate result + for graph in graphs: + self.transform_graph(graph) + self.timeshift_graph(graph) + + def transform_graph(self, graph): + # prepare the graphs by inserting all bookkeeping/dispatching logic + # as special operations + assert graph.startblock in self.annotator.annotated + transformer = HintGraphTransformer(self.annotator, graph) + transformer.transform() + flowmodel.checkgraph(graph) # for now + + def timeshift_graph(self, graph): + # specialize all blocks of this graph + for block in graph.iterblocks(): + self.annotator.annotated[block] = graph + self.specialize_block(block) + # "normalize" the graphs by putting an explicit v_jitstate variable + # everywhere + self.insert_v_jitstate_everywhere(graph) + # the graph is now timeshifted, so it is *itself* no longer + # exception-transformed... + del graph.exceptiontransformed + + # ____________________________________________________________ + + def s_r_instanceof(self, cls, can_be_None=True): + # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. + return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) + + def get_sig_hs(self, tsgraph): + # the signature annotations are cached on the HintBookkeeper because + # the graph is transformed already + return self.annotator.bookkeeper.tsgraphsigs[tsgraph] def make_new_lloplist(self, block): - return HintLowLevelOpList(self.timeshifter) + return HintLowLevelOpList(self) def getgreenrepr(self, lowleveltype): try: @@ -75,7 +211,7 @@ if isinstance(lowleveltype, lltype.Ptr): if isinstance(lowleveltype.TO, lltype.Struct): redreprcls = RedStructRepr - r = redreprcls(lowleveltype, self.timeshifter) + r = redreprcls(lowleveltype, self) self.red_reprs[lowleveltype] = r return r @@ -90,6 +226,28 @@ self.color_cache[id(hs)] = color return color + def insert_v_jitstate_everywhere(self, graph): + from pypy.translator.unsimplify import varoftype + for block in graph.iterblocks(): + v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') + if block is graph.returnblock: + assert block.inputargs[0].concretetype is lltype.Void + del block.inputargs[0] + block.inputargs = [v_jitstate] + block.inputargs + for op in block.operations: + if op.opname == 'getjitstate': + op.opname = 'same_as' + op.args = [v_jitstate] + elif op.opname == 'setjitstate': + [v_jitstate] = op.args + for i in range(len(block.operations)-1, -1, -1): + if block.operations[i].opname == 'setjitstate': + del block.operations[i] + for link in block.exits: + if link.target is graph.returnblock: + del link.args[0] # Void + link.args = [v_jitstate] + link.args + def generic_translate_operation(self, hop, force=False): # detect constant-foldable all-green operations if not force and hop.spaceop.opname not in rtimeshift.FOLDABLE_OPS: @@ -114,7 +272,7 @@ ll_generate = rtimeshift.ll_gen1 elif opdesc.nb_args == 2: ll_generate = rtimeshift.ll_gen2 - ts = self.timeshifter + ts = self c_opdesc = inputconst(lltype.Void, opdesc) s_opdesc = ts.rtyper.annotator.bookkeeper.immutablevalue(opdesc) v_jitstate = hop.llops.getjitstate() @@ -133,7 +291,7 @@ T = originalconcretetype(hop.args_s[0]) v_redbox = hop.inputarg(self.getredrepr(T), arg=0) assert isinstance(hop.r_result, GreenRepr) - ts = self.timeshifter + ts = self c_T = hop.inputconst(lltype.Void, T) s_T = ts.rtyper.annotator.bookkeeper.immutablevalue(T) s_res = annmodel.lltype_to_annotation(T) @@ -157,7 +315,7 @@ def translate_op_getfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_getfield(hop) - ts = self.timeshifter + ts = self if hop.args_v[0] == ts.cexcdata: # reading one of the exception boxes (exc_type or exc_value) fieldname = hop.args_v[1].value @@ -198,7 +356,7 @@ if res is not None: return res - ts = self.timeshifter + ts = self v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed)) fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) @@ -217,7 +375,7 @@ return res PTRTYPE = originalconcretetype(hop.args_s[0]) - ts = self.timeshifter + ts = self [v_argbox] = hop.inputargs(self.getredrepr(PTRTYPE)) fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) @@ -234,7 +392,7 @@ def translate_op_setfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_setfield(hop) - ts = self.timeshifter + ts = self PTRTYPE = originalconcretetype(hop.args_s[0]) VALUETYPE = originalconcretetype(hop.args_s[2]) if hop.args_v[0] == ts.cexcdata: @@ -271,7 +429,7 @@ def translate_op_setarrayitem(self, hop): PTRTYPE = originalconcretetype(hop.args_s[0]) VALUETYPE = PTRTYPE.TO.OF - ts = self.timeshifter + ts = self v_argbox, v_index, v_valuebox= hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed), self.getredrepr(VALUETYPE)) @@ -287,7 +445,7 @@ def translate_op_getsubstruct(self, hop): ##if isinstance(hop.args_r[0], BlueRepr): ## return hop.args_r[0].timeshift_getsubstruct(hop) - ts = self.timeshifter + ts = self PTRTYPE = originalconcretetype(hop.args_s[0]) v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE), green_void_repr) @@ -311,7 +469,7 @@ return r_result.create(hop) def translate_op_malloc_varsize(self, hop): - ts = self.timeshifter + ts = self assert isinstance(hop.r_result, RedRepr) PTRTYPE = originalconcretetype(hop.s_result) TYPE = PTRTYPE.TO @@ -329,7 +487,7 @@ def translate_op_ptr_nonzero(self, hop, reverse=False): - ts = self.timeshifter + ts = self PTRTYPE = originalconcretetype(hop.args_s[0]) v_argbox, = hop.inputargs(self.getredrepr(PTRTYPE)) v_jitstate = hop.llops.getjitstate() @@ -371,7 +529,7 @@ def translate_op_indirect_call(self, hop): bk = self.annotator.bookkeeper - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() v_funcbox = hop.args_v[0] graph_list = hop.args_v[-1].value @@ -396,25 +554,41 @@ v_newjitstate = hop.genop('indirect_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) + # special operations inserted by the HintGraphTransformer + + def translate_op_enter_graph(self, hop): + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(rtimeshift.enter_graph, + [self.s_JITState], + [v_jitstate ], + annmodel.s_None) + + def translate_op_leave_graph(self, hop): + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph, + [self.s_JITState], + [v_jitstate ], + annmodel.s_None) def translate_op_save_locals(self, hop): - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() - v_boxes = ts.build_box_list(hop.llops, hop.args_v) + boxes_s = [ts.s_RedBox] * len(hop.args_v) + boxes_v = hop.args_v hop.llops.genmixlevelhelpercall(rtimeshift.save_locals, - [ts.s_JITState, ts.s_box_list], - [v_jitstate, v_boxes], + [ts.s_JITState] + boxes_s, + [v_jitstate ] + boxes_v, annmodel.s_None) def translate_op_restore_local(self, hop): - ts = self.timeshifter + ts = self assert isinstance(hop.args_v[0], flowmodel.Constant) index = hop.args_v[0].value v_jitstate = hop.llops.getjitstate() return ts.read_out_box(hop.llops, v_jitstate, index) def translate_op_fetch_return(self, hop): - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.getreturnbox, [ts.s_JITState], @@ -442,7 +616,7 @@ # if the ll_handler() takes more arguments, it must be 'None' defaults. # Pass them as constant Nones. - ts = self.timeshifter + ts = self ll_handler = oopspecdesc.ll_handler missing_args = ((ll_handler.func_code.co_argcount - 2) - len(oopspecdesc.argtuple)) @@ -480,7 +654,7 @@ def handle_red_call(self, hop): bk = self.annotator.bookkeeper - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() c_func = hop.args_v[0] fnobj = c_func.value._obj @@ -501,9 +675,9 @@ """Warning: the HintLowLevelOpList's rtyper is the *original* rtyper, while the HighLevelOp's rtyper is actually our HintRTyper... """ - def __init__(self, timeshifter): - LowLevelOpList.__init__(self, timeshifter.rtyper) - self.timeshifter = timeshifter + def __init__(self, hrtyper): + LowLevelOpList.__init__(self, hrtyper.rtyper) + self.hrtyper = hrtyper def hasparentgraph(self): return False # for now @@ -524,23 +698,22 @@ args_v = [v_self] + args_v function = function.im_func - graph = self.timeshifter.annhelper.getgraph(function, args_s, s_result) + graph = self.hrtyper.annhelper.getgraph(function, args_s, s_result) self.record_extra_call(graph) # xxx - c = self.timeshifter.annhelper.graph2const(graph) + c = self.hrtyper.annhelper.graph2const(graph) # build the 'direct_call' operation - rtyper = self.timeshifter.rtyper try: RESULT = annmodel.annotation_to_lltype(s_result) except ValueError: - RESULT = rtyper.getrepr(s_result).lowleveltype + RESULT = self.rtyper.getrepr(s_result).lowleveltype return self.genop('direct_call', [c]+args_v, resulttype = RESULT) def getjitstate(self): return self.genop('getjitstate', [], - resulttype = self.timeshifter.r_JITState) + resulttype = self.hrtyper.r_JITState) def setjitstate(self, v_newjitstate): self.genop('setjitstate', [v_newjitstate]) @@ -568,7 +741,7 @@ # fall back to a red repr return hrtyper.getredrepr(hs_container.concretetype) return BlueStructRepr(hs_container.concretetype, vstructdef, - hrtyper.timeshifter) + hrtyper) def rtyper_makekey((ts, hs_container), hrtyper): vstructdef = hs_container.contentdef @@ -597,26 +770,26 @@ return hs_c.__class__, class RedRepr(Repr): - def __init__(self, original_concretetype, timeshifter): + def __init__(self, original_concretetype, hrtyper): assert original_concretetype is not lltype.Void, ( "cannot make red boxes for the lltype Void") self.original_concretetype = original_concretetype - self.lowleveltype = timeshifter.r_RedBox.lowleveltype - self.timeshifter = timeshifter + self.lowleveltype = hrtyper.r_RedBox.lowleveltype + self.hrtyper = hrtyper def get_genop_var(self, v, llops): - ts = self.timeshifter + ts = self.hrtyper v_jitstate = hop.llops.getjitstate() return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox, - [ts.s_JITState, llops.timeshifter.s_RedBox], + [ts.s_JITState, llops.hrtyper.s_RedBox], [v_jitstate, v], ts.s_ConstOrVar) def convert_const(self, ll_value): - RGenOp = self.timeshifter.RGenOp + RGenOp = self.hrtyper.RGenOp redbox = rvalue.redbox_from_prebuilt_value(RGenOp, ll_value) - timeshifter = self.timeshifter - return timeshifter.annhelper.delayedconst(timeshifter.r_RedBox, redbox) + hrtyper = self.hrtyper + return hrtyper.annhelper.delayedconst(hrtyper.r_RedBox, redbox) def residual_values(self, ll_value): return [ll_value] @@ -626,7 +799,7 @@ typedesc = None def create(self, hop): - ts = self.timeshifter + ts = self.hrtyper if self.typedesc is None: T = self.original_concretetype.TO self.typedesc = rcontainer.StructTypeDesc(ts.RGenOp, T) @@ -659,7 +832,7 @@ return annmodel.SomeInteger() def get_genop_var(self, v, llops): - ts = self.timeshifter + ts = self.hrtyper v_jitstate = hop.llops.getjitstate() return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant, [ts.s_JITState, self.annotation()], @@ -689,12 +862,12 @@ def convert_from_to((r_from, r_to), v, llops): assert r_from.lowleveltype == r_to.original_concretetype - ts = llops.timeshifter + ts = llops.hrtyper v_jitstate = llops.getjitstate() return llops.genmixlevelhelpercall(rvalue.ll_fromvalue, [ts.s_JITState, r_from.annotation()], [v_jitstate, v], - llops.timeshifter.s_RedBox) + ts.s_RedBox) # ____________________________________________________________ Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py Tue Sep 19 13:23:14 2006 @@ -3,7 +3,7 @@ from pypy.jit.hintannotator.annotator import HintAnnotator from pypy.jit.hintannotator.bookkeeper import HintBookkeeper from pypy.jit.hintannotator.model import * -from pypy.jit.timeshifter.timeshift import HintTimeshift +from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype from pypy.jit.timeshifter import rtimeshift, rvalue, rtyper as hintrtyper from pypy.objspace.flow.model import summary from pypy.rpython.lltypesystem import lltype, llmemory, rstr @@ -94,12 +94,13 @@ backendoptimize=backendoptimize) # make the timeshifted graphs - htshift = HintTimeshift(ha, rtyper, self.RGenOp) - fresh_jitstate = htshift.ll_fresh_jitstate - finish_jitstate = htshift.ll_finish_jitstate - RESTYPE = htshift.originalconcretetype( - ha.translator.graphs[0].getreturnvar()) - htshift.timeshift() + hrtyper = HintRTyper(ha, rtyper, self.RGenOp) + hrtyper.specialize(view = conftest.option.view) + + fresh_jitstate = hrtyper.ll_fresh_jitstate + finish_jitstate = hrtyper.ll_finish_jitstate + args_hs, hs_res = hrtyper.get_sig_hs(ha.translator.graphs[0]) + RESTYPE = originalconcretetype(hs_res) t = rtyper.annotator.translator for graph in ha.translator.graphs: checkgraph(graph) @@ -122,9 +123,9 @@ argcolors = [] generate_code_args_s = [] - for v, llvalue in zip(graph1varargs, values): + for v, hs_arg, llvalue in zip(graph1varargs, args_hs, values): s_var = annmodel.ll_to_annotation(llvalue) - r = htshift.hrtyper.bindingrepr(v) + r = hrtyper.bindingrepr(v) residual_v = r.residual_values(llvalue) if len(residual_v) == 0: color = "green" @@ -132,9 +133,9 @@ else: color = "red" assert residual_v == [llvalue], "XXX for now" - ARGTYPE = htshift.originalconcretetype(v) + ARGTYPE = originalconcretetype(hs_arg) residual_argtypes.append(ARGTYPE) - timeshifted_entrypoint_args_s.append(htshift.s_RedBox) + timeshifted_entrypoint_args_s.append(hrtyper.s_RedBox) generate_code_args_s.append(annmodel.SomeBool()) argcolors.append(color) generate_code_args_s.append(s_var) @@ -143,9 +144,9 @@ graph1) timeshifted_entrypoint = PseudoHighLevelCallable( timeshifted_entrypoint_fnptr, - [htshift.s_JITState] + [hrtyper.s_JITState] + timeshifted_entrypoint_args_s, - htshift.s_JITState) + hrtyper.s_JITState) FUNC = lltype.FuncType(residual_argtypes, RESTYPE) argcolors = unrolling_iterable(argcolors) self.argcolors = argcolors @@ -216,7 +217,7 @@ self.ml_generate_code = ml_generate_code ## self.ml_call_residual_graph = ml_call_residual_graph self.rtyper = rtyper - self.htshift = htshift + self.hrtyper = hrtyper self.annotate_interface_functions() if conftest.option.view: from pypy.translator.tool.graphpage import FlowGraphPage @@ -228,7 +229,7 @@ return values def annotate_interface_functions(self): - annhelper = self.htshift.annhelper + annhelper = self.hrtyper.annhelper RGenOp = self.RGenOp ml_generate_code = self.ml_generate_code ## ml_call_residual_graph = self.ml_call_residual_graph @@ -270,7 +271,7 @@ # now try to run the residual graph generated by the builder residual_graph = ll_generated._obj.graph - residual_graph.exceptiontransformed = self.htshift.exc_data_ptr + residual_graph.exceptiontransformed = self.hrtyper.exc_data_ptr if conftest.option.view: residual_graph.show() self.insns = summary(residual_graph) Added: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py ============================================================================== --- (empty file) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Tue Sep 19 13:23:14 2006 @@ -0,0 +1,79 @@ +from pypy.objspace.flow import model as flowmodel +from pypy.annotation import model as annmodel +from pypy.jit.hintannotator import model as hintmodel +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.rmodel import inputconst +from pypy.translator.unsimplify import varoftype, copyvar +from pypy.translator.unsimplify import split_block, split_block_at_start + + +class HintGraphTransformer(object): + + def __init__(self, hannotator, graph): + self.hannotator = hannotator + self.graph = graph + self.dispatch_to = [] + self.latestexitindex = -1 + + def transform(self): + self.insert_enter_graph() + self.insert_leave_graph() + + # __________ helpers __________ + + def genop(self, llops, opname, args, result_type=None): + # 'result_type' can be a LowLevelType (for green returns) + # or a template variable whose hintannotation is copied + if result_type is None: + v_res = self.new_void_var() + elif isinstance(result_type, lltype.LowLevelType): + v_res = varoftype(result_type) + hs = hintmodel.SomeLLAbstractConstant(result_type, {}) + self.hannotator.setbinding(v_res, hs) + elif isinstance(result_type, flowmodel.Variable): + var = result_type + v_res = copyvar(self.hannotator, var) + else: + raise TypeError("result_type=%r" % (result_type,)) + + spaceop = flowmodel.SpaceOperation(opname, args, v_res) + llops.append(spaceop) + return v_res + + def new_void_var(self, name=None): + v_res = varoftype(lltype.Void, name) + self.hannotator.setbinding(v_res, annmodel.s_ImpossibleValue) + return v_res + + def new_block_before(self, block): + newinputargs = [copyvar(self.hannotator, var) + for var in block.inputargs] + newblock = flowmodel.Block(newinputargs) + bridge = flowmodel.Link(newinputargs, block) + newblock.closeblock(bridge) + return newblock + + # __________ transformation steps __________ + + def insert_enter_graph(self): + entryblock = self.new_block_before(self.graph.startblock) + entryblock.isstartblock = True + self.graph.startblock.isstartblock = False + self.graph.startblock = entryblock + + self.genop(entryblock.operations, 'enter_graph', []) + + def insert_leave_graph(self): + block = self.graph.returnblock + [v_retbox] = block.inputargs + block.operations = [] + split_block(self.hannotator, block, 0) + [link] = block.exits + assert len(link.args) == 0 + link.args = [inputconst(lltype.Void, None)] + link.target.inputargs = [self.new_void_var('dummy')] + self.graph.returnblock = link.target + self.graph.returnblock.operations = () + + self.genop(block.operations, 'save_locals', [v_retbox]) + self.genop(block.operations, 'leave_graph', []) From mwh at codespeak.net Tue Sep 19 13:41:23 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Sep 2006 13:41:23 +0200 (CEST) Subject: [pypy-svn] r32488 - pypy/branch/kill-keepalives/pypy/rpython Message-ID: <20060919114123.6800D1007B@code0.codespeak.net> Author: mwh Date: Tue Sep 19 13:41:22 2006 New Revision: 32488 Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Log: llinterp support for these strange local mallocs Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/llinterp.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Tue Sep 19 13:41:22 2006 @@ -171,6 +171,7 @@ self.curr_block = None self.curr_operation_index = 0 self.alloca_objects = [] + self.local_mallocs = [] # _______________________________________________________ # variable setters/getters helpers @@ -244,6 +245,8 @@ for obj in self.alloca_objects: #XXX slighly unclean obj._setobj(None) + for adr in self.local_mallocs: + self.heap.raw_free(adr) return args finally: if tracer: From mwh at codespeak.net Tue Sep 19 13:51:05 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Sep 2006 13:51:05 +0200 (CEST) Subject: [pypy-svn] r32489 - pypy/branch/kill-keepalives/pypy/rpython/memory Message-ID: <20060919115105.0C8231007B@code0.codespeak.net> Author: mwh Date: Tue Sep 19 13:51:03 2006 New Revision: 32489 Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Log: add an assert. the tests pass now -- confused, maybe i wasn't running the right code before? Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Tue Sep 19 13:51:03 2006 @@ -152,6 +152,7 @@ # continue for link in links_without_a_var: for v in vars: + assert v not in link.args if v.concretetype == llmemory.Address: break newblock = insert_empty_block(None, link) From mwh at codespeak.net Tue Sep 19 14:01:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Sep 2006 14:01:47 +0200 (CEST) Subject: [pypy-svn] r32490 - pypy/branch/kill-keepalives/pypy/rpython/memory Message-ID: <20060919120147.5AEA31007A@code0.codespeak.net> Author: mwh Date: Tue Sep 19 14:01:45 2006 New Revision: 32490 Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Log: i hate operator overloading (^ is obviously "lattice-meet", not "symmetric difference") Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Tue Sep 19 14:01:45 2006 @@ -144,7 +144,7 @@ links_with_a_var = [] links_without_a_var = [] for link in block.exits: - if set(vars) ^ set(link.args): + if set(vars) & set(link.args): links_with_a_var.append(link) else: links_without_a_var.append(link) From mwh at codespeak.net Tue Sep 19 15:05:48 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Sep 2006 15:05:48 +0200 (CEST) Subject: [pypy-svn] r32491 - in pypy/branch/kill-keepalives/pypy: rpython/memory translator/backendopt Message-ID: <20060919130548.0457F10082@code0.codespeak.net> Author: mwh Date: Tue Sep 19 15:05:46 2006 New Revision: 32491 Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Log: tweaks, and an important fix to malloc.py Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Tue Sep 19 15:05:46 2006 @@ -138,35 +138,36 @@ variables_by_block = {} for block, var in info.variables: - vars = variables_by_block.setdefault(block, {}) - vars[var] = True + vars = variables_by_block.setdefault(block, set()) + vars.add(var) for block, vars in variables_by_block.iteritems(): links_with_a_var = [] links_without_a_var = [] for link in block.exits: - if set(vars) & set(link.args): + if vars & set(link.args): links_with_a_var.append(link) else: links_without_a_var.append(link) #if not links_without_a_var: # continue for link in links_without_a_var: + vv = iter(vars).next() for v in vars: assert v not in link.args if v.concretetype == llmemory.Address: - break + vv = v newblock = insert_empty_block(None, link) - link.args.append(v) - newblock.inputargs.append(copyvar(None, v)) - if v.concretetype != llmemory.Address: + link.args.append(vv) + newblock.inputargs.append(copyvar(None, vv)) + if vv.concretetype != llmemory.Address: newv = varoftype(llmemory.Address) newblock.operations.append(SpaceOperation( "cast_ptr_to_adr", [newblock.inputargs[-1]], newv)) - v = newv + vv = newv else: - v = newblock.inputargs[-1] + vv = newblock.inputargs[-1] newblock.operations.append(SpaceOperation( - "raw_free", [v], varoftype(lltype.Void))) + "raw_free", [vv], varoftype(lltype.Void))) checkgraph(graph) def compute_borrowed_vars(self, graph): Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Tue Sep 19 15:05:46 2006 @@ -87,7 +87,7 @@ def visit(node): if isinstance(node, Block): for op in node.operations: - if op.opname in ("same_as", "cast_pointer"): + if op.opname in ("same_as", "cast_pointer", "cast_adr_to_ptr"): # special-case these operations to identify their input # and output variables union(node, op.args[0], node, op.result) From mwh at codespeak.net Tue Sep 19 15:06:38 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Sep 2006 15:06:38 +0200 (CEST) Subject: [pypy-svn] r32492 - pypy/branch/kill-keepalives/pypy/rpython Message-ID: <20060919130638.7CEF810082@code0.codespeak.net> Author: mwh Date: Tue Sep 19 15:06:37 2006 New Revision: 32492 Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Log: i'm sure i'd checked this in already Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/llinterp.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Tue Sep 19 15:06:37 2006 @@ -751,6 +751,11 @@ assert lltype.typeOf(value) == typ getattr(addr, str(typ).lower())[offset] = value + def op_local_raw_malloc(self, size): + r = self.heap.raw_malloc(size) + self.local_mallocs.append(r) + return r + # ____________________________________________________________ # Overflow-detecting variants From arigo at codespeak.net Tue Sep 19 16:57:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 16:57:43 +0200 (CEST) Subject: [pypy-svn] r32501 - in pypy/branch/timeshift-refactoring/pypy/translator/backendopt: . test Message-ID: <20060919145743.969221007C@code0.codespeak.net> Author: arigo Date: Tue Sep 19 16:57:37 2006 New Revision: 32501 Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py Log: (arre, arigo) A possibly useful tool for graph construction and transformation. It allows us to build a few blocks without worrying about passing variables along links and renaming them *at all*, and then goes along and fixes the blocks. More precisely, it's an SSA to SSI transformation. Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py (original) +++ pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py Tue Sep 19 16:57:37 2006 @@ -16,9 +16,7 @@ # [Block, blockvar, linkvar, linkvar, linkvar...] opportunities = [] opportunities_with_const = [] - for block, links in mkentrymap(graph).items(): - if block is graph.startblock: - continue + for block, links in mkinsideentrymap(graph).items(): assert links for n, inputvar in enumerate(block.inputargs): vars = [block, inputvar] @@ -124,3 +122,92 @@ vct = [getattr(v, 'concretetype', None) for v in vlist] assert vct == vct[:1] * len(vct), ( "variables called %s have mixed concretetypes: %r" % (vname, vct)) + +# ____________________________________________________________ + +def mkinsideentrymap(graph_or_blocks): + # graph_or_blocks can be a full FunctionGraph, or a mapping + # {block: reachable-from-outside-flag}. + if isinstance(graph_or_blocks, dict): + blocks = graph_or_blocks + entrymap = {} + for block in blocks: + for link in block.exits: + if link.target in blocks and not blocks[link.target]: + entrymap.setdefault(link.target, []).append(link) + return entrymap + else: + graph = graph_or_blocks + entrymap = mkentrymap(graph) + del entrymap[graph.startblock] + return entrymap + +def variables_created_in(block): + result = {} + for v in block.inputargs: + result[v] = True + for op in block.operations: + result[op.result] = True + return result + + +def SSA_to_SSI(blocks, annotator=None): + """Turn a number of blocks belonging to a flow graph into valid (i.e. SSI) + form, assuming that they are only in SSA form (i.e. they can use each + other's variables directly, without having to pass and rename them along + links). + + 'blocks' is a mapping {block: reachable-from-outside-flag}. + """ + from pypy.translator.unsimplify import copyvar + + entrymap = mkinsideentrymap(blocks) + variable_families = DataFlowFamilyBuilder(blocks).get_variable_families() + + pending = [] # list of (block, var-used-but-not-defined) + + for block in blocks: + variables_created = variables_created_in(block) + variables_used = {} + for op in block.operations: + for v in op.args: + if isinstance(v, Variable): + variables_used[v] = True + if isinstance(block.exitswitch, Variable): + variables_used[v] = True + for link in block.exits: + for v in link.args: + if isinstance(v, Variable): + variables_used[v] = True + + for v in variables_used: + if v not in variables_created: + pending.append((block, v)) + + while pending: + block, v = pending.pop() + v_rep = variable_families.find_rep(v) + variables_created = variables_created_in(block) + if v in variables_created: + continue # already ok + for w in variables_created: + w_rep = variable_families.find_rep(w) + if v_rep is w_rep: + # 'w' is in the same family as 'v', so we can simply + # reuse its value for 'v' + block.renamevariables({v: w}) + break + else: + # didn't find it. Add it to all incoming links. + try: + links = entrymap[block] + except KeyError: + raise Exception("SSA_to_SSI failed: no way to give a value to" + " %r in %r" % (v, block)) + w = copyvar(annotator, v) + variable_families.union(v, w) + block.renamevariables({v: w}) + block.inputargs.append(w) + for link in links: + link.args.append(v) + pending.append((link.prevblock, v)) Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py (original) +++ pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py Tue Sep 19 16:57:37 2006 @@ -1,6 +1,7 @@ from pypy.translator.backendopt.ssa import * from pypy.translator.translator import TranslationContext -from pypy.objspace.flow.model import flatten, Block +from pypy.objspace.flow.model import flatten, Block, Link, Variable, Constant +from pypy.objspace.flow.model import SpaceOperation def test_data_flow_families(): @@ -49,3 +50,63 @@ allvars += [v.name for v in block.getvariables()] # see comments above for where the 8 remaining variables are expected to be assert len(dict.fromkeys(allvars)) == 8 + + +def test_SSA_to_SSI(): + c = Variable('c') + x = Variable('x') + y = Variable('y') + b1 = Block([c]) + b2 = Block([x]) + b3 = Block([]) + + b2.operations.append(SpaceOperation('add', [x, c], y)) + b2.exitswitch = y + + b1.closeblock(Link([Constant(0)], b2)) + b2.closeblock(Link([y], b2), Link([], b3)) + b3.closeblock(Link([y, c], None)) + + SSA_to_SSI({b1: True, # reachable from outside + b2: False, + b3: False}) + + assert len(b1.inputargs) == 1 + assert len(b2.inputargs) == 2 + assert len(b3.inputargs) == 2 + + assert b2.inputargs == b2.operations[0].args + assert len(b1.exits[0].args) == 2 + assert b1.exits[0].args[1] is c + assert len(b2.exits[0].args) == 2 + assert b2.exits[0].args == [y, b2.inputargs[1]] + assert len(b2.exits[1].args) == 2 + assert len(b3.exits[0].args) == 2 + + index = b3.inputargs.index(b3.exits[0].args[0]) + assert b2.exits[1].args[index] is b2.operations[0].result + + index = b3.inputargs.index(b3.exits[0].args[1]) + assert b2.exits[1].args[index] is b2.inputargs[1] + + +def test_SSA_to_SSI_2(): + x = Variable('x') + y = Variable('y') + z = Variable('z') + b1 = Block([x]) + b2 = Block([y]) + b3 = Block([]) + + b3.operations.append(SpaceOperation('hello', [y], z)) + b1.closeblock(Link([x], b2), Link([], b3)) + + SSA_to_SSI({b1: True, # reachable from outside + b2: False, + b3: False}) + + assert b1.inputargs == [x] + assert b2.inputargs == [y] + assert b3.inputargs == [b3.operations[0].args[0]] + assert b1.exits[0].args == [x] + assert b1.exits[1].args == [x] From arigo at codespeak.net Tue Sep 19 19:01:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 19:01:13 +0200 (CEST) Subject: [pypy-svn] r32505 - pypy/branch/timeshift-refactoring/pypy/translator/backendopt Message-ID: <20060919170113.C8B1310081@code0.codespeak.net> Author: arigo Date: Tue Sep 19 19:01:12 2006 New Revision: 32505 Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py Log: (arre, arigo) The SSA_to_SSI() helper can also take complete graphs, if really. Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py (original) +++ pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py Tue Sep 19 19:01:12 2006 @@ -151,22 +151,25 @@ return result -def SSA_to_SSI(blocks, annotator=None): +def SSA_to_SSI(graph_or_blocks, annotator=None): """Turn a number of blocks belonging to a flow graph into valid (i.e. SSI) form, assuming that they are only in SSA form (i.e. they can use each other's variables directly, without having to pass and rename them along links). - 'blocks' is a mapping {block: reachable-from-outside-flag}. + 'graph_or_blocks' can be a graph, or just a dict that lists some blocks + from a graph, as follows: {block: reachable-from-outside-flag}. """ from pypy.translator.unsimplify import copyvar - entrymap = mkinsideentrymap(blocks) - variable_families = DataFlowFamilyBuilder(blocks).get_variable_families() + entrymap = mkinsideentrymap(graph_or_blocks) + builder = DataFlowFamilyBuilder(graph_or_blocks) + variable_families = builder.get_variable_families() + del builder pending = [] # list of (block, var-used-but-not-defined) - for block in blocks: + for block in entrymap: variables_created = variables_created_in(block) variables_used = {} for op in block.operations: From arigo at codespeak.net Tue Sep 19 19:01:47 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 19:01:47 +0200 (CEST) Subject: [pypy-svn] r32506 - pypy/branch/timeshift-refactoring/pypy/rpython Message-ID: <20060919170147.4EB1310087@code0.codespeak.net> Author: arigo Date: Tue Sep 19 19:01:45 2006 New Revision: 32506 Modified: pypy/branch/timeshift-refactoring/pypy/rpython/rtyper.py Log: (arre, arigo) Allow high-level graphs to contain switches with a 'default' link too. Modified: pypy/branch/timeshift-refactoring/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/rpython/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/rpython/rtyper.py Tue Sep 19 19:01:45 2006 @@ -375,7 +375,7 @@ self.insert_link_conversions(extrablock) def _convert_link(self, block, link): - if link.exitcase is not None: + if link.exitcase is not None and link.exitcase != 'default': if isinstance(block.exitswitch, Variable): r_case = self.bindingrepr(block.exitswitch) else: From arigo at codespeak.net Tue Sep 19 19:03:27 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Sep 2006 19:03:27 +0200 (CEST) Subject: [pypy-svn] r32508 - pypy/branch/timeshift-refactoring/pypy/jit/timeshifter Message-ID: <20060919170327.8E23E10083@code0.codespeak.net> Author: arigo Date: Tue Sep 19 19:03:25 2006 New Revision: 32508 Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Log: (arre, arigo) Reimplemented splits and the dispatcher, in the graph transformer and as rtyped operations. There is more work to be done in rtimeshift. Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py Tue Sep 19 19:03:25 2006 @@ -194,8 +194,7 @@ states_dic[key] = frozen, newblock start_new_block._annspecialcase_ = "specialize:arglltype(2)" -def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes): - save_locals(jitstate, redboxes) +def retrieve_jitstate_for_merge(states_dic, jitstate, key): if key not in states_dic: start_new_block(states_dic, jitstate, key) return False # continue @@ -229,30 +228,23 @@ jitstate.enter_block(incoming, memo) enter_next_block(jitstate, incoming) -def leave_block_split(jitstate, switchredbox, exitindex, - redboxes_true, redboxes_false): - if switchredbox.is_constant(): - return rvalue.ll_getvalue(switchredbox, lltype.Bool) - else: - exitgvar = switchredbox.getgenvar(jitstate.curbuilder) - later_builder = jitstate.curbuilder.jump_if_false(exitgvar) - save_locals(jitstate, redboxes_false) - jitstate.split(later_builder, exitindex) - save_locals(jitstate, redboxes_true) - enter_block(jitstate) - return True +def split(jitstate, switchredbox, resumepoint, *greens_gv): + exitgvar = switchredbox.getgenvar(jitstate.curbuilder) + later_builder = jitstate.curbuilder.jump_if_false(exitgvar) + jitstate.split(later_builder, resumepoint, list(greens_gv)) -def dispatch_next(oldjitstate, return_cache): +def dispatch_next(oldjitstate): split_queue = oldjitstate.frame.split_queue if split_queue: jitstate = split_queue.pop() enter_block(jitstate) return jitstate else: - return leave_graph(oldjitstate.frame.return_queue, return_cache) + oldjitstate.resumepoint = -1 + return oldjitstate -def getexitindex(jitstate): - return jitstate.exitindex +def getresumepoint(jitstate): + return jitstate.resumepoint def save_locals(jitstate, *redboxes): redboxes = list(redboxes) @@ -262,6 +254,9 @@ def getlocalbox(jitstate, i): return jitstate.frame.local_boxes[i] +def getgreenbox(jitstate, i, T): + return jitstate.greens[i].revealconst(T) + def getreturnbox(jitstate): return jitstate.returnbox @@ -380,20 +375,22 @@ returnbox = None def __init__(self, builder, frame, exc_type_box, exc_value_box, - exitindex=-1): + resumepoint=-1, newgreens=[]): self.curbuilder = builder self.frame = frame self.exc_type_box = exc_type_box self.exc_value_box = exc_value_box - self.exitindex = exitindex + self.resumepoint = resumepoint + self.greens = newgreens - def split(self, newbuilder, newexitindex): + def split(self, newbuilder, newresumepoint, newgreens): memo = rvalue.copy_memo() later_jitstate = JITState(newbuilder, self.frame.copy(memo), self.exc_type_box .copy(memo), self.exc_value_box.copy(memo), - newexitindex) + newresumepoint, + newgreens) self.frame.split_queue.append(later_jitstate) def enter_block(self, incoming, memo): @@ -417,17 +414,21 @@ def enter_graph(jitstate): jitstate.frame = VirtualFrame(jitstate.frame, [], []) -def leave_graph(jitstate): -## for jitstate in return_queue[:-1]: -## res = retrieve_jitstate_for_merge(return_cache, jitstate, (), -## # XXX strange next argument -## jitstate.frame.local_boxes) -## assert res is True # finished -## frozen, block = return_cache[()] -## jitstate = return_queue[-1] +def leave_graph_red(jitstate): + return_queue = jitstate.frame.return_queue + return_cache = {} + still_pending = [] + for jitstate in return_queue: + res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + if res is False: # not finished + still_pending.append(jitstate) + for jitstate in still_pending[:-1]: + res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + assert res is True # finished + jitstate = still_pending[-1] myframe = jitstate.frame if myframe.local_boxes: # else it's a green Void return jitstate.returnbox = myframe.local_boxes[0] # ^^^ fetched by a 'fetch_return' operation jitstate.frame = myframe.backframe -## jitstate.exitindex = -1 + return jitstate Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Tue Sep 19 19:03:25 2006 @@ -563,29 +563,55 @@ [v_jitstate ], annmodel.s_None) - def translate_op_leave_graph(self, hop): + def translate_op_leave_graph_red(self, hop): v_jitstate = hop.llops.getjitstate() - hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph, - [self.s_JITState], - [v_jitstate ], - annmodel.s_None) + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_red, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_newjs) def translate_op_save_locals(self, hop): - ts = self v_jitstate = hop.llops.getjitstate() - boxes_s = [ts.s_RedBox] * len(hop.args_v) - boxes_v = hop.args_v + boxes_r = [self.getredrepr(originalconcretetype(hs)) + for hs in hop.args_s] + boxes_v = hop.inputargs(*boxes_r) + boxes_s = [self.s_RedBox] * len(hop.args_v) hop.llops.genmixlevelhelpercall(rtimeshift.save_locals, - [ts.s_JITState] + boxes_s, - [v_jitstate ] + boxes_v, + [self.s_JITState] + boxes_s, + [v_jitstate ] + boxes_v, + annmodel.s_None) + + def translate_op_enter_block(self, hop): + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(rtimeshift.enter_block, + [self.s_JITState], + [v_jitstate ], annmodel.s_None) def translate_op_restore_local(self, hop): - ts = self assert isinstance(hop.args_v[0], flowmodel.Constant) index = hop.args_v[0].value + c_index = hop.inputconst(lltype.Signed, index) v_jitstate = hop.llops.getjitstate() - return ts.read_out_box(hop.llops, v_jitstate, index) + return hop.llops.genmixlevelhelpercall(rtimeshift.getlocalbox, + [self.s_JITState, annmodel.SomeInteger(nonneg=True)], + [v_jitstate , c_index ], + self.s_RedBox) + + def translate_op_restore_green(self, hop): + assert isinstance(hop.args_v[0], flowmodel.Constant) + index = hop.args_v[0].value + c_index = hop.inputconst(lltype.Signed, index) + TYPE = originalconcretetype(hop.s_result) + s_TYPE = self.rtyper.annotator.bookkeeper.immutablevalue(TYPE) + c_TYPE = hop.inputconst(lltype.Void, TYPE) + s_result = annmodel.lltype_to_annotation(TYPE) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.getgreenbox, + [self.s_JITState, annmodel.SomeInteger(nonneg=True), s_TYPE], + [v_jitstate , c_index , c_TYPE], + s_result) def translate_op_fetch_return(self, hop): ts = self @@ -595,6 +621,77 @@ [v_jitstate ], ts.s_RedBox) + def translate_op_is_constant(self, hop): + hs = hop.args_s[0] + r_arg = self.getredrepr(originalconcretetype(hs)) + [v_arg] = hop.inputargs(r_arg) + return hop.llops.genmixlevelhelpercall(rvalue.ll_is_constant, + [self.s_RedBox], + [v_arg ], + annmodel.SomeBool()) + + def translate_op_revealconst(self, hop): + hs = hop.args_s[0] + TYPE = originalconcretetype(hs) + r_arg = self.getredrepr(TYPE) + [v_arg] = hop.inputargs(r_arg) + s_TYPE = self.rtyper.annotator.bookkeeper.immutablevalue(TYPE) + c_TYPE = hop.inputconst(lltype.Void, TYPE) + s_result = annmodel.lltype_to_annotation(TYPE) + return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue, + [self.s_RedBox, s_TYPE], + [v_arg , c_TYPE], + s_result) + + def wrap_green_vars(self, llops, vars): + v_jitstate = llops.getjitstate() + for var in vars: + s_var = annmodel.lltype_to_annotation(var.concretetype) + yield llops.genmixlevelhelpercall(rvalue.ll_gv_fromvalue, + [self.s_JITState, s_var], + [v_jitstate, var ], + self.s_ConstOrVar) + + def translate_op_split(self, hop): + r_switch = self.getredrepr(lltype.Bool) + GREENS = [v.concretetype for v in hop.args_v[2:]] + greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS] + vlist = hop.inputargs(r_switch, lltype.Signed, *greens_r) + + v_jitstate = hop.llops.getjitstate() + v_switch = vlist[0] + c_resumepoint = vlist[1] + greens_v = list(self.wrap_green_vars(hop.llops, vlist[2:])) + + s_Int = annmodel.SomeInteger(nonneg=True) + args_s = [self.s_JITState, self.s_RedBox, s_Int] + args_s += [self.s_ConstOrVar] * len(greens_v) + args_v = [v_jitstate, v_switch, c_resumepoint] + args_v += greens_v + hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v, + annmodel.s_None) + + def translate_op_save_return(self, hop): + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.save_return, + [self.s_JITState], + [v_jitstate ], + annmodel.s_None) + + def translate_op_dispatch_next(self, hop): + v_jitstate = hop.llops.getjitstate() + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.dispatch_next, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_newjs) + return hop.llops.genmixlevelhelpercall(rtimeshift.getresumepoint, + [self.s_JITState], + [v_newjs ], + annmodel.SomeInteger()) + + # handling of the various kinds of calls + def handle_oopspec_call(self, hop): # special-cased call, for things like list methods from pypy.jit.timeshifter.oop import OopSpecDesc, Index Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py Tue Sep 19 19:03:25 2006 @@ -90,10 +90,9 @@ def ll_fromvalue(jitstate, value): "Make a constant RedBox from a low-level value." - rgenop = jitstate.curbuilder.rgenop + gv = ll_gv_fromvalue(jitstate, value) T = lltype.typeOf(value) - kind = rgenop.kindToken(T) - gv = rgenop.genconst(value) + kind = jitstate.curbuilder.rgenop.kindToken(T) cls = ll_redboxcls(T) return cls(kind, gv) @@ -104,10 +103,19 @@ cls = ll_redboxcls(T) return cls(kind, gv) +def ll_gv_fromvalue(jitstate, value): + rgenop = jitstate.curbuilder.rgenop + gv = rgenop.genconst(value) + return gv + def ll_getvalue(box, T): "Return the content of a known-to-be-constant RedBox." return box.genvar.revealconst(T) +def ll_is_constant(box): + "Check if a red box is known to be constant." + return box.is_constant() + class IntRedBox(RedBox): "A red box that contains a constant integer-like value." Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Tue Sep 19 19:03:25 2006 @@ -1,10 +1,12 @@ -from pypy.objspace.flow import model as flowmodel +from pypy.objspace.flow.model import Variable, Constant, Block, Link +from pypy.objspace.flow.model import SpaceOperation from pypy.annotation import model as annmodel from pypy.jit.hintannotator import model as hintmodel from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.rmodel import inputconst from pypy.translator.unsimplify import varoftype, copyvar from pypy.translator.unsimplify import split_block, split_block_at_start +from pypy.translator.backendopt.ssa import SSA_to_SSI class HintGraphTransformer(object): @@ -12,16 +14,18 @@ def __init__(self, hannotator, graph): self.hannotator = hannotator self.graph = graph - self.dispatch_to = [] - self.latestexitindex = -1 + self.resumepoints = {} def transform(self): + self.insert_save_return() + self.insert_splits() + self.insert_dispatcher() self.insert_enter_graph() self.insert_leave_graph() # __________ helpers __________ - def genop(self, llops, opname, args, result_type=None): + def genop(self, block, opname, args, result_type=None): # 'result_type' can be a LowLevelType (for green returns) # or a template variable whose hintannotation is copied if result_type is None: @@ -30,16 +34,24 @@ v_res = varoftype(result_type) hs = hintmodel.SomeLLAbstractConstant(result_type, {}) self.hannotator.setbinding(v_res, hs) - elif isinstance(result_type, flowmodel.Variable): + elif isinstance(result_type, Variable): var = result_type v_res = copyvar(self.hannotator, var) else: raise TypeError("result_type=%r" % (result_type,)) - spaceop = flowmodel.SpaceOperation(opname, args, v_res) - llops.append(spaceop) + spaceop = SpaceOperation(opname, args, v_res) + block.operations.append(spaceop) return v_res + def genswitch(self, block, v_exitswitch, false, true): + block.exitswitch = v_exitswitch + link_f = Link([], false) + link_f.exitcase = False + link_t = Link([], true) + link_t.exitcase = True + block.recloseblock(link_f, link_t) + def new_void_var(self, name=None): v_res = varoftype(lltype.Void, name) self.hannotator.setbinding(v_res, annmodel.s_ImpossibleValue) @@ -48,24 +60,23 @@ def new_block_before(self, block): newinputargs = [copyvar(self.hannotator, var) for var in block.inputargs] - newblock = flowmodel.Block(newinputargs) - bridge = flowmodel.Link(newinputargs, block) + newblock = Block(newinputargs) + bridge = Link(newinputargs, block) newblock.closeblock(bridge) return newblock - # __________ transformation steps __________ - - def insert_enter_graph(self): - entryblock = self.new_block_before(self.graph.startblock) - entryblock.isstartblock = True - self.graph.startblock.isstartblock = False - self.graph.startblock = entryblock - - self.genop(entryblock.operations, 'enter_graph', []) + def sort_by_color(self, vars): + reds = [] + greens = [] + for v in vars: + if self.hannotator.binding(v).is_green(): + greens.append(v) + else: + reds.append(v) + return reds, greens - def insert_leave_graph(self): + def before_return_block(self): block = self.graph.returnblock - [v_retbox] = block.inputargs block.operations = [] split_block(self.hannotator, block, 0) [link] = block.exits @@ -74,6 +85,112 @@ link.target.inputargs = [self.new_void_var('dummy')] self.graph.returnblock = link.target self.graph.returnblock.operations = () + return block + + # __________ transformation steps __________ + + def insert_splits(self): + hannotator = self.hannotator + for block in self.graph.iterblocks(): + if block.exitswitch is not None: + assert isinstance(block.exitswitch, Variable) + hs_switch = hannotator.binding(block.exitswitch) + if not hs_switch.is_green(): + self.insert_split_handling(block) + + def insert_split_handling(self, block): + v_redswitch = block.exitswitch + link_f, link_t = block.exits + if link_f.exitcase: + link_f, link_t = link_t, link_f + assert link_f.exitcase is False + assert link_t.exitcase is True + + constant_block = Block([]) + nonconstant_block = Block([]) + + v_flag = self.genop(block, 'is_constant', [v_redswitch], + result_type = lltype.Bool) + self.genswitch(block, v_flag, true = constant_block, + false = nonconstant_block) + + v_greenswitch = self.genop(constant_block, 'revealconst', + [v_redswitch], + result_type = lltype.Bool) + constant_block.exitswitch = v_greenswitch + constant_block.closeblock(link_f, link_t) + + reds, greens = self.sort_by_color(link_f.args) + self.genop(nonconstant_block, 'save_locals', reds) + resumepoint = self.get_resume_point(link_f.target) + c_resumepoint = inputconst(lltype.Signed, resumepoint) + self.genop(nonconstant_block, 'split', + [v_redswitch, c_resumepoint] + greens) + + reds, greens = self.sort_by_color(link_t.args) + self.genop(nonconstant_block, 'save_locals', reds) + self.genop(nonconstant_block, 'enter_block', []) + nonconstant_block.closeblock(Link(link_t.args, link_t.target)) + + SSA_to_SSI({block : True, # reachable from outside + constant_block : False, + nonconstant_block: False}, self.hannotator) + + def get_resume_point(self, block): + try: + reenter_link = self.resumepoints[block] + except KeyError: + resumeblock = Block([]) + redcount = 0 + greencount = 0 + newvars = [] + for v in block.inputargs: + if self.hannotator.binding(v).is_green(): + c = inputconst(lltype.Signed, greencount) + v1 = self.genop(resumeblock, 'restore_green', [c], + result_type = v) + greencount += 1 + else: + c = inputconst(lltype.Signed, redcount) + v1 = self.genop(resumeblock, 'restore_local', [c], + result_type = v) + redcount += 1 + newvars.append(v1) + + resumeblock.closeblock(Link(newvars, block)) + reenter_link = Link([], resumeblock) + N = len(self.resumepoints) + reenter_link.exitcase = N + self.resumepoints[block] = reenter_link + return reenter_link.exitcase + + def insert_dispatcher(self): + if self.resumepoints: + block = self.before_return_block() + v_switchcase = self.genop(block, 'dispatch_next', [], + result_type = lltype.Signed) + block.exitswitch = v_switchcase + defaultlink = block.exits[0] + defaultlink.exitcase = 'default' + links = self.resumepoints.values() + links.sort(lambda l, r: cmp(l.exitcase, r.exitcase)) + links.append(defaultlink) + block.recloseblock(*links) + + def insert_save_return(self): + block = self.before_return_block() + [v_retbox] = block.inputargs + self.genop(block, 'save_locals', [v_retbox]) + self.genop(block, 'save_return', []) + + def insert_enter_graph(self): + entryblock = self.new_block_before(self.graph.startblock) + entryblock.isstartblock = True + self.graph.startblock.isstartblock = False + self.graph.startblock = entryblock + + self.genop(entryblock, 'enter_graph', []) - self.genop(block.operations, 'save_locals', [v_retbox]) - self.genop(block.operations, 'leave_graph', []) + def insert_leave_graph(self): + block = self.before_return_block() + self.genop(block, 'leave_graph_red', []) From arigo at codespeak.net Wed Sep 20 09:45:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 09:45:36 +0200 (CEST) Subject: [pypy-svn] r32515 - pypy/branch/timeshift-refactoring/pypy/translator/c/test Message-ID: <20060920074536.ADE8110076@code0.codespeak.net> Author: arigo Date: Wed Sep 20 09:45:33 2006 New Revision: 32515 Modified: pypy/branch/timeshift-refactoring/pypy/translator/c/test/test_extfunc.py Log: Fix test for Windows. Modified: pypy/branch/timeshift-refactoring/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/timeshift-refactoring/pypy/translator/c/test/test_extfunc.py Wed Sep 20 09:45:33 2006 @@ -496,13 +496,20 @@ tmpfile = str(udir.join('test_os_chmod.txt')) f = open(tmpfile, 'w') f.close() + # use a witness for the permissions we should expect - + # on Windows it is not possible to change all the bits with chmod() + tmpfile2 = str(udir.join('test_os_chmod_witness.txt')) + f = open(tmpfile2, 'w') + f.close() def does_stuff(mode): os.chmod(tmpfile, mode) f1 = compile(does_stuff, [int]) f1(0000) - assert os.stat(tmpfile).st_mode & 0777 == 0000 + os.chmod(tmpfile2, 0000) + assert os.stat(tmpfile).st_mode & 0777 == os.stat(tmpfile2).st_mode & 0777 f1(0644) - assert os.stat(tmpfile).st_mode & 0777 == 0644 + os.chmod(tmpfile2, 0644) + assert os.stat(tmpfile).st_mode & 0777 == os.stat(tmpfile2).st_mode & 0777 def test_os_rename(): tmpfile1 = str(udir.join('test_os_rename_1.txt')) From arigo at codespeak.net Wed Sep 20 09:52:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 09:52:25 +0200 (CEST) Subject: [pypy-svn] r32516 - in pypy/branch/timeshift-refactoring/pypy/module/mmap: . test Message-ID: <20060920075225.8F4EE10076@code0.codespeak.net> Author: arigo Date: Wed Sep 20 09:52:23 2006 New Revision: 32516 Modified: pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py pypy/branch/timeshift-refactoring/pypy/module/mmap/test/test_mmap.py Log: The return value of mmap().flush() is not well-defined in CPython either. Modified: pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py (original) +++ pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py Wed Sep 20 09:52:23 2006 @@ -427,6 +427,8 @@ start = self.getptr(offset) if _MS_WINDOWS: res = FlushViewOfFile(start, size) + # XXX res == 0 means that an error occurred, but in CPython + # this is not checked return self.space.wrap(res) elif _POSIX: ## XXX why is this code here? There is no equivalent in CPython Modified: pypy/branch/timeshift-refactoring/pypy/module/mmap/test/test_mmap.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/module/mmap/test/test_mmap.py (original) +++ pypy/branch/timeshift-refactoring/pypy/module/mmap/test/test_mmap.py Wed Sep 20 09:52:23 2006 @@ -247,7 +247,7 @@ raises(TypeError, m.flush, 1, 2, 3) raises(TypeError, m.flush, 1, "a") raises(ValueError, m.flush, 0, 99) - assert m.flush() == 0 + m.flush() # return value is a bit meaningless, platform-dependent m.close() f.close() From arigo at codespeak.net Wed Sep 20 09:54:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 09:54:56 +0200 (CEST) Subject: [pypy-svn] r32517 - pypy/branch/timeshift-refactoring/pypy/module/mmap Message-ID: <20060920075456.670EE1007B@code0.codespeak.net> Author: arigo Date: Wed Sep 20 09:54:55 2006 New Revision: 32517 Modified: pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py Log: Fix in the Windows part of the code. Now let's wait tomorrow for Scott's automated test runner and see what's my next bug :-) Modified: pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py (original) +++ pypy/branch/timeshift-refactoring/pypy/module/mmap/interp_mmap.py Wed Sep 20 09:54:55 2006 @@ -181,7 +181,7 @@ dwErr = GetLastError() if low.value == INVALID_FILE_SIZE and dwErr != NO_ERROR: raise OperationError(space.w_EnvironmentError, - space.wrap(_get_error_msg(dwErr))) + space.wrap(os.strerror(dwErr))) return low.value, high.value def _get_error_msg(): From arigo at codespeak.net Wed Sep 20 10:18:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 10:18:28 +0200 (CEST) Subject: [pypy-svn] r32518 - pypy/dist/pypy/module/mmap Message-ID: <20060920081828.2CCB810075@code0.codespeak.net> Author: arigo Date: Wed Sep 20 10:18:28 2006 New Revision: 32518 Added: pypy/dist/pypy/module/mmap/ - copied from r32517, pypy/branch/timeshift-refactoring/pypy/module/mmap/ Log: Merge fixes accidentally checked in on the branch. From arigo at codespeak.net Wed Sep 20 10:21:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 10:21:08 +0200 (CEST) Subject: [pypy-svn] r32519 - pypy/dist/pypy/translator/c/test Message-ID: <20060920082108.69C2C10075@code0.codespeak.net> Author: arigo Date: Wed Sep 20 10:21:08 2006 New Revision: 32519 Added: pypy/dist/pypy/translator/c/test/test_extfunc.py - copied unchanged from r32518, pypy/branch/timeshift-refactoring/pypy/translator/c/test/test_extfunc.py Log: Another check-in that went into the branch by mistake. From arigo at codespeak.net Wed Sep 20 10:22:30 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 10:22:30 +0200 (CEST) Subject: [pypy-svn] r32520 - pypy/dist/pypy/interpreter/test Message-ID: <20060920082230.D00DC10075@code0.codespeak.net> Author: arigo Date: Wed Sep 20 10:22:29 2006 New Revision: 32520 Modified: pypy/dist/pypy/interpreter/test/test_main.py Log: Create the temporary module/package files in udir, not in the current directory. Modified: pypy/dist/pypy/interpreter/test/test_main.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_main.py (original) +++ pypy/dist/pypy/interpreter/test/test_main.py Wed Sep 20 10:22:29 2006 @@ -38,53 +38,43 @@ capturefile.close() assert capturefn.read(mode='rU') == expected_output -testfn = 'tmp_hello_world.py' +testfn = udir.join('tmp_hello_world.py') testmodule = 'tmp_hello_module' testpackage = 'tmp_package' class TestMain: def setup_class(cls): - ofile = open(testfn, 'w') - ofile.write(testcode) - ofile.close() - omodulefile = open(testmodule + '.py', 'w') - omodulefile.write(testmodulecode) - omodulefile.close() - import os - os.mkdir(testpackage) - open(os.path.join(testpackage, '__init__.py'), 'w').close() - file_name = os.path.join(testpackage, testmodule) + '.py' - omodulefile = open(file_name,'w') - omodulefile.write(testmodulecode) - omodulefile.close() - + testfn.write(testcode, 'w') + udir.join(testmodule + '.py').write(testmodulecode, 'w') + udir.ensure(testpackage, '__init__.py') + udir.join(testpackage, testmodule + '.py').write(testmodulecode, 'w') + space = cls.space + cls.w_oldsyspath = space.appexec([space.wrap(str(udir))], """(udir): + import sys + old = sys.path[:] + sys.path.insert(0, udir) + return old + """) def teardown_class(cls): - import os - def remove_if_exists(fn): - if os.path.exists(fn): - os.remove(fn) - remove_if_exists(testfn) - remove_if_exists(testmodule + '.py') - remove_if_exists(os.path.join(testpackage, '__init__.py')) - remove_if_exists(os.path.join(testpackage, '__init__.pyc')) - remove_if_exists(os.path.join(testpackage, testmodule) + '.py') - os.rmdir(testpackage) - + cls.space.appexec([cls.w_oldsyspath], """(old): + import sys + sys.path[:] = old + """) def test_run_file(self): - checkoutput(self.space, testresultoutput,main.run_file,testfn) + checkoutput(self.space, testresultoutput, main.run_file, str(testfn)) def test_run_string(self): checkoutput(self.space, testresultoutput, - main.run_string,testcode,testfn) + main.run_string, testcode, str(testfn)) def test_eval_string(self): w_x = main.eval_string('2+2', space=self.space) assert self.space.eq_w(w_x, self.space.wrap(4)) def test_run_module(self): - checkoutput(self.space, testresultoutput, main.run_module, - testmodule, ['hello world']) - checkoutput(self.space, testresultoutput, main.run_module, - testpackage + '.' + testmodule, ['hello world']) + checkoutput(self.space, testresultoutput, main.run_module, + testmodule, ['hello world']) + checkoutput(self.space, testresultoutput, main.run_module, + testpackage + '.' + testmodule, ['hello world']) From benyoung at codespeak.net Wed Sep 20 12:44:48 2006 From: benyoung at codespeak.net (benyoung at codespeak.net) Date: Wed, 20 Sep 2006 12:44:48 +0200 (CEST) Subject: [pypy-svn] r32522 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060920104448.890DA1007F@code0.codespeak.net> Author: benyoung Date: Wed Sep 20 12:44:29 2006 New Revision: 32522 Modified: pypy/dist/pypy/module/_random/interp_random.py pypy/dist/pypy/module/_random/test/test_random.py Log: Make the _random tests pass on Windows Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Wed Sep 20 12:44:29 2006 @@ -53,7 +53,7 @@ def getstate(self, space): state = [None] * (rpy_random.N + 1) for i in range(rpy_random.N): - state[i] = space.newint(int(self._rnd.state[i])) + state[i] = space.newlong(self._rnd.state[i]) state[rpy_random.N] = space.newint(self._rnd.index) return space.newtuple(state) getstate.unwrap_spec = ['self', ObjSpace] @@ -69,7 +69,7 @@ w_item = space.getitem(w_state, space.newint(i)) self._rnd.state[i] = space.uint_w(w_item) w_item = space.getitem(w_state, space.newint(rpy_random.N)) - self._rnd.index = space.uint_w(w_item) + self._rnd.index = space.int_w(w_item) setstate.unwrap_spec = ['self', ObjSpace, W_Root] def jumpahead(self, n): Modified: pypy/dist/pypy/module/_random/test/test_random.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_random.py (original) +++ pypy/dist/pypy/module/_random/test/test_random.py Wed Sep 20 12:44:29 2006 @@ -31,7 +31,8 @@ rnd1.random() rnd2 = _random.Random() assert rnd1.getstate() != rnd2.getstate() - rnd1.setstate(rnd2.getstate()) + state = rnd2.getstate() + rnd1.setstate(state) assert [rnd1.random() for i in range(100)] == [ rnd2.random() for i in range(100)] From arigo at codespeak.net Wed Sep 20 13:20:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 13:20:53 +0200 (CEST) Subject: [pypy-svn] r32524 - pypy/branch/timeshift-refactoring/pypy/jit/timeshifter Message-ID: <20060920112053.7751D10080@code0.codespeak.net> Author: arigo Date: Wed Sep 20 13:20:52 2006 New Revision: 32524 Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Log: (arre, arigo) Merge point support again. Some tests pass again. Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py Wed Sep 20 13:20:52 2006 @@ -1,6 +1,7 @@ import operator, weakref from pypy.rpython.lltypesystem import lltype, lloperation, llmemory from pypy.jit.timeshifter import rvalue +from pypy.rpython.unroll import unrolling_iterable FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops()) @@ -234,7 +235,7 @@ jitstate.split(later_builder, resumepoint, list(greens_gv)) def dispatch_next(oldjitstate): - split_queue = oldjitstate.frame.split_queue + split_queue = oldjitstate.frame.dispatch_queue.split_queue if split_queue: jitstate = split_queue.pop() enter_block(jitstate) @@ -273,7 +274,7 @@ jitstate.exc_value_box = box def save_return(jitstate): - jitstate.frame.return_queue.append(jitstate) + jitstate.frame.dispatch_queue.return_queue.append(jitstate) def ll_gvar_from_redbox(jitstate, redbox): return redbox.getgenvar(jitstate.curbuilder) @@ -283,6 +284,22 @@ # ____________________________________________________________ +class BaseDispatchQueue(object): + def __init__(self): + self.split_queue = [] # XXX could be turned into a linked list + self.return_queue = [] # XXX could be turned into a linked list + +def build_dispatch_subclass(attrnames): + if len(attrnames) == 0: + return BaseDispatchQueue + attrnames = unrolling_iterable(attrnames) + class DispatchQueue(BaseDispatchQueue): + def __init__(self): + BaseDispatchQueue.__init__(self) + for name in attrnames: + setattr(self, name, {}) # the new dicts have various types! + return DispatchQueue + class FrozenVirtualFrame(object): fz_backframe = None @@ -332,10 +349,9 @@ class VirtualFrame(object): - def __init__(self, backframe, split_queue, return_queue): + def __init__(self, backframe, dispatch_queue): self.backframe = backframe - self.split_queue = split_queue - self.return_queue = return_queue + self.dispatch_queue = dispatch_queue #self.local_boxes = ... set by callers def enter_block(self, incoming, memo): @@ -357,9 +373,7 @@ newbackframe = None else: newbackframe = self.backframe.copy(memo) - result = VirtualFrame(newbackframe, - self.split_queue, - self.return_queue) + result = VirtualFrame(newbackframe, self.dispatch_queue) result.local_boxes = [box.copy(memo) for box in self.local_boxes] return result @@ -391,7 +405,7 @@ self.exc_value_box.copy(memo), newresumepoint, newgreens) - self.frame.split_queue.append(later_jitstate) + self.frame.dispatch_queue.split_queue.append(later_jitstate) def enter_block(self, incoming, memo): self.frame.enter_block(incoming, memo) @@ -411,11 +425,13 @@ self.exc_value_box = self.exc_value_box.replace(memo) -def enter_graph(jitstate): - jitstate.frame = VirtualFrame(jitstate.frame, [], []) +def enter_graph(jitstate, DispatchQueueClass): + jitstate.frame = VirtualFrame(jitstate.frame, DispatchQueueClass()) +enter_graph._annspecialcase_ = 'specialize:arg(1)' +# XXX is that too many specializations? ^^^ def leave_graph_red(jitstate): - return_queue = jitstate.frame.return_queue + return_queue = jitstate.frame.dispatch_queue.return_queue return_cache = {} still_pending = [] for jitstate in return_queue: Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Wed Sep 20 13:20:52 2006 @@ -58,6 +58,7 @@ self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper) self.timeshift_mapping = {} self.sigs = {} + self.dispatchsubclasses = {} (self.s_CodeGenerator, self.r_CodeGenerator) = self.s_r_instanceof(cgmodel.CodeGenerator) @@ -226,6 +227,15 @@ self.color_cache[id(hs)] = color return color + def get_dispatch_subclass(self, mergepointfamily): + try: + return self.dispatchsubclasses[mergepointfamily] + except KeyError: + attrnames = mergepointfamily.getattrnames() + subclass = rtimeshift.build_dispatch_subclass(attrnames) + self.dispatchsubclasses[mergepointfamily] = subclass + return subclass + def insert_v_jitstate_everywhere(self, graph): from pypy.translator.unsimplify import varoftype for block in graph.iterblocks(): @@ -557,10 +567,14 @@ # special operations inserted by the HintGraphTransformer def translate_op_enter_graph(self, hop): + mpfamily = hop.args_v[0].value + subclass = self.get_dispatch_subclass(mpfamily) + s_subclass = self.rtyper.annotator.bookkeeper.immutablevalue(subclass) + c_subclass = inputconst(lltype.Void, subclass) v_jitstate = hop.llops.getjitstate() hop.llops.genmixlevelhelpercall(rtimeshift.enter_graph, - [self.s_JITState], - [v_jitstate ], + [self.s_JITState, s_subclass], + [v_jitstate , c_subclass], annmodel.s_None) def translate_op_leave_graph_red(self, hop): @@ -671,6 +685,23 @@ hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v, annmodel.s_None) + def translate_op_merge_point(self, hop): + mpfamily = hop.args_v[0].value + attrname = hop.args_v[1].value + DispatchQueueSubclass = self.get_dispatch_subclass(mpfamily) + + def merge_point(jitstate, *key): + dispatch_queue = jitstate.frame.dispatch_queue + assert isinstance(dispatch_queue, DispatchQueueSubclass) + states_dic = getattr(dispatch_queue, attrname) + return rtimeshift.retrieve_jitstate_for_merge(states_dic, + jitstate, key) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(merge_point, + [self.s_JITState] + hop.args_s[2:], + [v_jitstate ] + hop.args_v[2:], + annmodel.SomeBool()) + def translate_op_save_return(self, hop): v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.save_return, Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Wed Sep 20 13:20:52 2006 @@ -1,5 +1,5 @@ from pypy.objspace.flow.model import Variable, Constant, Block, Link -from pypy.objspace.flow.model import SpaceOperation +from pypy.objspace.flow.model import SpaceOperation, mkentrymap from pypy.annotation import model as annmodel from pypy.jit.hintannotator import model as hintmodel from pypy.rpython.lltypesystem import lltype, llmemory @@ -9,20 +9,42 @@ from pypy.translator.backendopt.ssa import SSA_to_SSI +class MergePointFamily(object): + def __init__(self): + self.count = 0 + def add(self): + result = self.count + self.count += 1 + return 'mp%d' % result + def getattrnames(self): + return ['mp%d' % i for i in range(self.count)] + + class HintGraphTransformer(object): def __init__(self, hannotator, graph): self.hannotator = hannotator self.graph = graph self.resumepoints = {} + self.mergepointfamily = MergePointFamily() + self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily) def transform(self): + mergepoints = list(self.enumerate_merge_points()) self.insert_save_return() self.insert_splits() + for block in mergepoints: + self.insert_merge(block) self.insert_dispatcher() self.insert_enter_graph() self.insert_leave_graph() + def enumerate_merge_points(self): + entrymap = mkentrymap(self.graph) + for block, links in entrymap.items(): + if len(links) > 1 and block is not self.graph.returnblock: + yield block + # __________ helpers __________ def genop(self, block, opname, args, result_type=None): @@ -41,7 +63,10 @@ raise TypeError("result_type=%r" % (result_type,)) spaceop = SpaceOperation(opname, args, v_res) - block.operations.append(spaceop) + if isinstance(block, list): + block.append(spaceop) + else: + block.operations.append(spaceop) return v_res def genswitch(self, block, v_exitswitch, false, true): @@ -65,6 +90,16 @@ newblock.closeblock(bridge) return newblock + def naive_split_block(self, block, position): + newblock = Block([]) + newblock.operations = block.operations[position:] + del block.operations[position:] + newblock.exitswitch = block.exitswitch + block.exitswitch = None + newblock.recloseblock(*block.exits) + block.recloseblock(Link([], newblock)) + return newblock + def sort_by_color(self, vars): reds = [] greens = [] @@ -164,6 +199,36 @@ self.resumepoints[block] = reenter_link return reenter_link.exitcase + def insert_merge(self, block): + reds, greens = self.sort_by_color(block.inputargs) + nextblock = self.naive_split_block(block, 0) + + self.genop(block, 'save_locals', reds) + mp = self.mergepointfamily.add() + c_mp = inputconst(lltype.Void, mp) + v_finished_flag = self.genop(block, 'merge_point', + [self.c_mpfamily, c_mp] + greens, + result_type = lltype.Bool) + block.exitswitch = v_finished_flag + [link_f] = block.exits + link_t = Link([inputconst(lltype.Void, None)], self.graph.returnblock) + link_f.exitcase = False + link_t.exitcase = True + block.recloseblock(link_f, link_t) + + restoreops = [] + mapping = {} + for i, v in enumerate(reds): + c = inputconst(lltype.Signed, i) + v1 = self.genop(restoreops, 'restore_local', [c], + result_type = v) + mapping[v] = v1 + nextblock.renamevariables(mapping) + nextblock.operations[:0] = restoreops + + SSA_to_SSI({block : True, # reachable from outside + nextblock: False}, self.hannotator) + def insert_dispatcher(self): if self.resumepoints: block = self.before_return_block() @@ -189,7 +254,7 @@ self.graph.startblock.isstartblock = False self.graph.startblock = entryblock - self.genop(entryblock, 'enter_graph', []) + self.genop(entryblock, 'enter_graph', [self.c_mpfamily]) def insert_leave_graph(self): block = self.before_return_block() From arigo at codespeak.net Wed Sep 20 14:40:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 14:40:26 +0200 (CEST) Subject: [pypy-svn] r32525 - pypy/branch/timeshift-refactoring/pypy/jit/timeshifter Message-ID: <20060920124026.46C2310077@code0.codespeak.net> Author: arigo Date: Wed Sep 20 14:40:25 2006 New Revision: 32525 Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Log: (arre, arigo) Oups, bug fix. Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Wed Sep 20 14:40:25 2006 @@ -696,10 +696,14 @@ states_dic = getattr(dispatch_queue, attrname) return rtimeshift.retrieve_jitstate_for_merge(states_dic, jitstate, key) + + greens_v = hop.args_v[2:] + greens_s = [annmodel.lltype_to_annotation(originalconcretetype(hs)) + for hs in hop.args_s[2:]] v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(merge_point, - [self.s_JITState] + hop.args_s[2:], - [v_jitstate ] + hop.args_v[2:], + [self.s_JITState] + greens_s, + [v_jitstate ] + greens_v, annmodel.SomeBool()) def translate_op_save_return(self, hop): From pedronis at codespeak.net Wed Sep 20 15:41:13 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Sep 2006 15:41:13 +0200 (CEST) Subject: [pypy-svn] r32526 - in pypy/dist/pypy: interpreter objspace/cpy Message-ID: <20060920134113.214771007F@code0.codespeak.net> Author: pedronis Date: Wed Sep 20 15:40:56 2006 New Revision: 32526 Modified: pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/objspace/cpy/function.py Log: cosmetic refactoring: all recipe now share the dispatch method name, also avoid the strange return modified argument pattern Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Wed Sep 20 15:40:56 2006 @@ -47,11 +47,11 @@ def signature(self): return self.argnames, self.varargname, self.kwargname - def apply_unwrap_spec(self, unwrap_spec, recipe, new_sig): + def apply_unwrap_spec(self, unwrap_spec, recipe, dest_sig): self._argiter = iter(self.argnames) + dispatch = recipe.dispatch for el in unwrap_spec: - recipe(el, self, new_sig) - return new_sig + dispatch(el, self, dest_sig) class UnwrapSpecRecipe: @@ -399,8 +399,9 @@ def make_builtin_frame_factory(func, orig_sig, unwrap_spec): "NOT_RPYTHON" name = (getattr(func, '__module__', None) or '')+'_'+func.__name__ - emit_sig = orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Emit().dispatch, - BuiltinCodeSignature(name=name, unwrap_spec=unwrap_spec)) + emit_sig = BuiltinCodeSignature(name=name, unwrap_spec=unwrap_spec) + orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Emit(), + dest_sig = emit_sig) return emit_sig.make_frame_factory(func) class FastFuncNotSupported(Exception): @@ -489,8 +490,9 @@ orig_sig = Signature(func, argnames, varargname, kwargname) - app_sig = orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Check().dispatch, - Signature(func)) + app_sig = Signature(func) + orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Check(), + dest_sig = app_sig) self.sig = argnames, varargname, kwargname = app_sig.signature() Modified: pypy/dist/pypy/objspace/cpy/function.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/function.py (original) +++ pypy/dist/pypy/objspace/cpy/function.py Wed Sep 20 15:40:56 2006 @@ -98,6 +98,10 @@ factory = func.code.framefactory bltin = factory.behavior unwrap_spec = factory.unwrap_spec + from pypy.interpreter import pycode + argnames, varargname, kwargname = pycode.cpython_code_signature( + bltin.func_code) + orig_sig = Signature(bltin, argnames, varargname, kwargname) tramp = TrampolineSignature() tramp.miniglobals = { @@ -107,15 +111,9 @@ '___OperationError': OperationError, '___reraise': reraise, } - - from pypy.interpreter import pycode - argnames, varargname, kwargname = pycode.cpython_code_signature( - bltin.func_code) - orig_sig = Signature(bltin, argnames, varargname, kwargname) - orig_sig.apply_unwrap_spec(unwrap_spec, - UnwrapSpec_Trampoline().dispatch, - tramp) + UnwrapSpec_Trampoline(), + dest_sig = tramp) sourcelines = ['def trampoline(%s):' % (', '.join(tramp.inputargs),)] # this description is to aid viewing in graphviewer From benyoung at codespeak.net Wed Sep 20 16:03:33 2006 From: benyoung at codespeak.net (benyoung at codespeak.net) Date: Wed, 20 Sep 2006 16:03:33 +0200 (CEST) Subject: [pypy-svn] r32527 - pypy/dist/pypy/translator/c Message-ID: <20060920140333.2AB4110075@code0.codespeak.net> Author: benyoung Date: Wed Sep 20 16:03:25 2006 New Revision: 32527 Modified: pypy/dist/pypy/translator/c/node.py Log: Fix the initialisation of unions Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Wed Sep 20 16:03:25 2006 @@ -460,6 +460,11 @@ for name in self.T._names: data.append((name, getattr(self.obj, name))) + # You can only initialise the first field of a union in c + # XXX what if later fields have some initialisation? + if hasattr(self.T, "_hints") and self.T._hints.get('union'): + data = data[0:1] + for name, value in data: if isinstance(value, _pyobjheader): # hack node = self.db.getcontainernode(value) From arigo at codespeak.net Wed Sep 20 16:34:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 16:34:42 +0200 (CEST) Subject: [pypy-svn] r32528 - in pypy/branch/timeshift-refactoring/pypy/jit: hintannotator timeshifter Message-ID: <20060920143442.5777A10075@code0.codespeak.net> Author: arigo Date: Wed Sep 20 16:34:40 2006 New Revision: 32528 Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Log: (arre, arigo) Red and void-returning calls pass again. We had to compute and cache in the hintannotator, at fix-point, the green-ness of the OriginFlags objects, because the graphs are now modified before the hrtyper tries to do the caching. Should work nicely, though. Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py Wed Sep 20 16:34:40 2006 @@ -110,6 +110,11 @@ return origin def compute_at_fixpoint(self): + # compute and cache the green-ness of OriginFlags objects + # while we can do so (i.e. before the graphs are modified) + for origin in self.originflags.values(): + if origin.spaceop is not None: + origin.greenargs_cached = origin.greenargs() # compute and cache the signature of the graphs before they are # modified by further code ha = self.annotator Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py Wed Sep 20 16:34:40 2006 @@ -32,6 +32,7 @@ fixed = False read_positions = None + greenargs_cached = None def __init__(self, bookkeeper=None, spaceop=None): self.bookkeeper = bookkeeper @@ -61,6 +62,8 @@ def greenargs(self, frame=None): annotator = self.bookkeeper.annotator if frame is None: + if self.greenargs_cached is not None: + return self.greenargs_cached frame = GreenHandlerFrame(annotator) if self.spaceop.opname == 'direct_call': # ah haa return frame.greencallresult(self.spaceop) @@ -229,6 +232,12 @@ else: return hs_v1 +def originalconcretetype(hs): + if isinstance(hs, annmodel.SomeImpossibleValue): + return lltype.Void + else: + return hs.concretetype + # ____________________________________________________________ # operations Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py Wed Sep 20 16:34:40 2006 @@ -1,5 +1,6 @@ import operator, weakref from pypy.rpython.lltypesystem import lltype, lloperation, llmemory +from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.timeshifter import rvalue from pypy.rpython.unroll import unrolling_iterable @@ -43,7 +44,6 @@ _opdesc_cache = {} def make_opdesc(hop): - from pypy.jit.timeshifter.rtyper import originalconcretetype hrtyper = hop.rtyper op_key = (hrtyper.RGenOp, hop.spaceop.opname, tuple([originalconcretetype(s_arg) for s_arg in hop.args_s]), @@ -276,11 +276,11 @@ def save_return(jitstate): jitstate.frame.dispatch_queue.return_queue.append(jitstate) -def ll_gvar_from_redbox(jitstate, redbox): - return redbox.getgenvar(jitstate.curbuilder) +##def ll_gvar_from_redbox(jitstate, redbox): +## return redbox.getgenvar(jitstate.curbuilder) -def ll_gvar_from_constant(jitstate, ll_value): - return jitstate.curbuilder.rgenop.genconst(ll_value) +##def ll_gvar_from_constant(jitstate, ll_value): +## return jitstate.curbuilder.rgenop.genconst(ll_value) # ____________________________________________________________ @@ -430,7 +430,7 @@ enter_graph._annspecialcase_ = 'specialize:arg(1)' # XXX is that too many specializations? ^^^ -def leave_graph_red(jitstate): +def merge_returning_jitstates(jitstate): return_queue = jitstate.frame.dispatch_queue.return_queue return_cache = {} still_pending = [] @@ -441,10 +441,18 @@ for jitstate in still_pending[:-1]: res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) assert res is True # finished - jitstate = still_pending[-1] + return still_pending[-1] + +def leave_graph_red(jitstate): + jitstate = merge_returning_jitstates(jitstate) + myframe = jitstate.frame + jitstate.returnbox = myframe.local_boxes[0] + # ^^^ fetched by a 'fetch_return' operation + jitstate.frame = myframe.backframe + return jitstate + +def leave_graph_void(jitstate): + jitstate = merge_returning_jitstates(jitstate) myframe = jitstate.frame - if myframe.local_boxes: # else it's a green Void return - jitstate.returnbox = myframe.local_boxes[0] - # ^^^ fetched by a 'fetch_return' operation jitstate.frame = myframe.backframe return jitstate Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Wed Sep 20 16:34:40 2006 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.hintannotator import model as hintmodel from pypy.jit.hintannotator import container as hintcontainer +from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, oop from pypy.jit.timeshifter.transform import HintGraphTransformer from pypy.jit.codegen import model as cgmodel @@ -38,12 +39,6 @@ # ___________________________________________________________ -def originalconcretetype(hs): - if isinstance(hs, annmodel.SomeImpossibleValue): - return lltype.Void - else: - return hs.concretetype - class HintRTyper(RPythonTyper): def __init__(self, hannotator, rtyper, RGenOp): @@ -53,7 +48,7 @@ self.RGenOp = RGenOp self.green_reprs = PRECOMPUTED_GREEN_REPRS.copy() self.red_reprs = {} - self.color_cache = {} + #self.color_cache = {} self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper) self.timeshift_mapping = {} @@ -216,16 +211,16 @@ self.red_reprs[lowleveltype] = r return r - def gethscolor(self, hs): - try: - return self.color_cache[id(hs)] - except KeyError: - if hs.is_green(): - color = "green" - else: - color = "red" - self.color_cache[id(hs)] = color - return color +## def gethscolor(self, hs): +## try: +## return self.color_cache[id(hs)] +## except KeyError: +## if hs.is_green(): +## color = "green" +## else: +## color = "red" +## self.color_cache[id(hs)] = color +## return color def get_dispatch_subclass(self, mergepointfamily): try: @@ -236,6 +231,20 @@ self.dispatchsubclasses[mergepointfamily] = subclass return subclass + def get_timeshifted_fnptr(self, graph, specialization_key): + bk = self.annotator.bookkeeper + tsgraph = bk.get_graph_by_key(graph, specialization_key) + args_hs, hs_res = self.get_sig_hs(tsgraph) + args_r = [self.getrepr(hs_arg) for hs_arg in args_hs] + ARGS = [self.r_JITState.lowleveltype] + ARGS += [r.lowleveltype for r in args_r] + RESULT = self.r_JITState.lowleveltype + fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), + tsgraph.name, + graph=tsgraph, + _callable = graph.func) + return fnptr, args_r + def insert_v_jitstate_everywhere(self, graph): from pypy.translator.unsimplify import varoftype for block in graph.iterblocks(): @@ -511,33 +520,8 @@ return self.translate_op_ptr_nonzero(hop, reverse=True) - def guess_call_kind(self, spaceop): - if spaceop.opname == 'indirect_call': - return 'red' # for now - assert spaceop.opname == 'direct_call' - c_func = spaceop.args[0] - fnobj = c_func.value._obj - s_result = self.annotator.binding(spaceop.result) - r_result = self.getrepr(s_result) - if hasattr(fnobj._callable, 'oopspec'): - return 'oopspec' - elif (originalconcretetype(s_result) is not lltype.Void and - isinstance(r_result, GreenRepr)): - for v in spaceop.args: - s_arg = self.annotator.binding(v) - r_arg = self.getrepr(s_arg) - if not isinstance(r_arg, GreenRepr): - return 'yellow' - return 'green' - else: - return 'red' - - def translate_op_direct_call(self, hop): - kind = self.guess_call_kind(hop.spaceop) - meth = getattr(self, 'handle_%s_call' % (kind,)) - return meth(hop) - def translate_op_indirect_call(self, hop): + XXX bk = self.annotator.bookkeeper ts = self v_jitstate = hop.llops.getjitstate() @@ -585,6 +569,14 @@ self.s_JITState) hop.llops.setjitstate(v_newjs) + def translate_op_leave_graph_void(self, hop): + v_jitstate = hop.llops.getjitstate() + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_void, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_newjs) + def translate_op_save_locals(self, hop): v_jitstate = hop.llops.getjitstate() boxes_r = [self.getredrepr(originalconcretetype(hs)) @@ -697,9 +689,17 @@ return rtimeshift.retrieve_jitstate_for_merge(states_dic, jitstate, key) - greens_v = hop.args_v[2:] - greens_s = [annmodel.lltype_to_annotation(originalconcretetype(hs)) - for hs in hop.args_s[2:]] + greens_v = [] + greens_s = [] + for r, v in zip(hop.args_r[2:], hop.args_v[2:]): + s_precise_type = r.annotation() + s_erased_type = r.erased_annotation() + r_precise_type = self.rtyper.getrepr(s_precise_type) + r_erased_type = self.rtyper.getrepr(s_erased_type) + greens_v.append(hop.llops.convertvar(v, r_precise_type, + r_erased_type)) + greens_s.append(s_erased_type) + v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(merge_point, [self.s_JITState] + greens_s, @@ -784,7 +784,7 @@ v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype) return v - def handle_red_call(self, hop): + def translate_op_red_call(self, hop): bk = self.annotator.bookkeeper ts = self v_jitstate = hop.llops.getjitstate() @@ -855,14 +855,14 @@ class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractValue)): def rtyper_makerepr((ts, hs_c), hrtyper): - if hrtyper.gethscolor(hs_c) == 'green': + if hs_c.is_green(): return hrtyper.getgreenrepr(hs_c.concretetype) else: return hrtyper.getredrepr(hs_c.concretetype) def rtyper_makekey((ts, hs_c), hrtyper): - color = hrtyper.gethscolor(hs_c) - return hs_c.__class__, color, hs_c.concretetype + is_green = hs_c.is_green() + return hs_c.__class__, is_green, hs_c.concretetype class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractContainer)): @@ -909,13 +909,13 @@ self.lowleveltype = hrtyper.r_RedBox.lowleveltype self.hrtyper = hrtyper - def get_genop_var(self, v, llops): - ts = self.hrtyper - v_jitstate = hop.llops.getjitstate() - return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox, - [ts.s_JITState, llops.hrtyper.s_RedBox], - [v_jitstate, v], - ts.s_ConstOrVar) +## def get_genop_var(self, v, llops): +## ts = self.hrtyper +## v_jitstate = hop.llops.getjitstate() +## return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox, +## [ts.s_JITState, llops.hrtyper.s_RedBox], +## [v_jitstate, v], +## ts.s_ConstOrVar) def convert_const(self, ll_value): RGenOp = self.hrtyper.RGenOp @@ -963,13 +963,13 @@ else: return annmodel.SomeInteger() - def get_genop_var(self, v, llops): - ts = self.hrtyper - v_jitstate = hop.llops.getjitstate() - return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant, - [ts.s_JITState, self.annotation()], - [v_jitstate, v], - ts.s_ConstOrVar) +## def get_genop_var(self, v, llops): +## ts = self.hrtyper +## v_jitstate = hop.llops.getjitstate() +## return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant, +## [ts.s_JITState, self.annotation()], +## [v_jitstate, v], +## ts.s_ConstOrVar) def convert_const(self, ll_value): return ll_value Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Wed Sep 20 16:34:40 2006 @@ -2,6 +2,7 @@ from pypy.objspace.flow.model import SpaceOperation, mkentrymap from pypy.annotation import model as annmodel from pypy.jit.hintannotator import model as hintmodel +from pypy.jit.hintannotator.model import originalconcretetype from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.rmodel import inputconst from pypy.translator.unsimplify import varoftype, copyvar @@ -35,6 +36,7 @@ self.insert_splits() for block in mergepoints: self.insert_merge(block) + self.split_after_calls() self.insert_dispatcher() self.insert_enter_graph() self.insert_leave_graph() @@ -47,20 +49,17 @@ # __________ helpers __________ - def genop(self, block, opname, args, result_type=None): + def genop(self, block, opname, args, result_type=None, result_like=None): # 'result_type' can be a LowLevelType (for green returns) # or a template variable whose hintannotation is copied - if result_type is None: - v_res = self.new_void_var() - elif isinstance(result_type, lltype.LowLevelType): + if result_type is not None: v_res = varoftype(result_type) hs = hintmodel.SomeLLAbstractConstant(result_type, {}) self.hannotator.setbinding(v_res, hs) - elif isinstance(result_type, Variable): - var = result_type - v_res = copyvar(self.hannotator, var) + elif result_like is not None: + v_res = copyvar(self.hannotator, result_like) else: - raise TypeError("result_type=%r" % (result_type,)) + v_res = self.new_void_var() spaceop = SpaceOperation(opname, args, v_res) if isinstance(block, list): @@ -100,6 +99,19 @@ block.recloseblock(Link([], newblock)) return newblock + def variables_alive(self, block, before_position): + created_before = dict.fromkeys(block.inputargs) + for op in block.operations[:before_position]: + created_before[op.result] = True + used = {} + for op in block.operations[before_position:]: + for v in op.args: + used[v] = True + for link in block.exits: + for v in link.args: + used[v] = True + return [v for v in used if v in created_before] + def sort_by_color(self, vars): reds = [] greens = [] @@ -183,12 +195,12 @@ if self.hannotator.binding(v).is_green(): c = inputconst(lltype.Signed, greencount) v1 = self.genop(resumeblock, 'restore_green', [c], - result_type = v) + result_like = v) greencount += 1 else: c = inputconst(lltype.Signed, redcount) v1 = self.genop(resumeblock, 'restore_local', [c], - result_type = v) + result_like = v) redcount += 1 newvars.append(v1) @@ -221,7 +233,7 @@ for i, v in enumerate(reds): c = inputconst(lltype.Signed, i) v1 = self.genop(restoreops, 'restore_local', [c], - result_type = v) + result_like = v) mapping[v] = v1 nextblock.renamevariables(mapping) nextblock.operations[:0] = restoreops @@ -245,7 +257,13 @@ def insert_save_return(self): block = self.before_return_block() [v_retbox] = block.inputargs - self.genop(block, 'save_locals', [v_retbox]) + hs_retbox = self.hannotator.binding(v_retbox) + if originalconcretetype(hs_retbox) is lltype.Void: + self.leave_graph_opname = 'leave_graph_void' + self.genop(block, 'save_locals', []) + else: + self.leave_graph_opname = 'leave_graph_red' + self.genop(block, 'save_locals', [v_retbox]) self.genop(block, 'save_return', []) def insert_enter_graph(self): @@ -258,4 +276,74 @@ def insert_leave_graph(self): block = self.before_return_block() - self.genop(block, 'leave_graph_red', []) + self.genop(block, self.leave_graph_opname, []) + + # __________ handling of the various kinds of calls __________ + + def guess_call_kind(self, spaceop): + if spaceop.opname == 'indirect_call': + return 'red' # for now + assert spaceop.opname == 'direct_call' + c_func = spaceop.args[0] + fnobj = c_func.value._obj + s_result = self.hannotator.binding(spaceop.result) + if hasattr(fnobj._callable, 'oopspec'): + return 'oopspec' + elif (originalconcretetype(s_result) is not lltype.Void and + s_result.is_green()): + for v in spaceop.args: + s_arg = self.hannotator.binding(v) + if not s_arg.is_green(): + return 'yellow' + return 'green' + else: + return 'red' + + def split_after_calls(self): + for block in list(self.graph.iterblocks()): + for i in range(len(block.operations)-1, -1, -1): + op = block.operations[i] + if op.opname in ('direct_call', 'indirect_call'): + call_kind = self.guess_call_kind(op) + handler = getattr(self, 'handle_%s_call' % (call_kind,)) + handler(block, i) + + def handle_red_call(self, block, pos): + # the 'save_locals' pseudo-operation is used to save all + # alive local variables into the current JITState + beforeops = block.operations[:pos] + op = block.operations[pos] + afterops = block.operations[pos+1:] + + varsalive = self.variables_alive(block, pos+1) + try: + varsalive.remove(op.result) + uses_retval = True # it will be restored by 'fetch_return' + except ValueError: + uses_retval = False + reds, greens = self.sort_by_color(varsalive) + + newops = [] + self.genop(newops, 'save_locals', reds) + self.genop(newops, 'red_call', op.args) # Void result, + # because the call doesn't return its redbox result, but only + # has the hidden side-effect of putting it in the jitstate + mapping = {} + for i, var in enumerate(reds): + c_index = Constant(i, concretetype=lltype.Signed) + newvar = self.genop(newops, 'restore_local', [c_index], + result_like = var) + mapping[var] = newvar + + if uses_retval and not self.hannotator.binding(op.result).is_green(): + var = op.result + newvar = self.genop(newops, 'fetch_return', [], + result_like = var) + mapping[var] = newvar + + saved = block.inputargs + block.inputargs = [] # don't rename these! + block.operations = afterops + block.renamevariables(mapping) + block.inputargs = saved + block.operations[:0] = beforeops + newops From arigo at codespeak.net Wed Sep 20 17:18:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 17:18:25 +0200 (CEST) Subject: [pypy-svn] r32531 - in pypy/branch/timeshift-refactoring/pypy/jit: hintannotator timeshifter timeshifter/test Message-ID: <20060920151825.40DAE1007B@code0.codespeak.net> Author: arigo Date: Wed Sep 20 17:18:22 2006 New Revision: 32531 Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/oop.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/vlist.py Log: (arre, arigo) 'oopspec' and 'green' calls. Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py Wed Sep 20 17:18:22 2006 @@ -96,6 +96,8 @@ ## import pdb; pdb.set_trace() args_hs = [self.annotator.binding(v) for v in spaceop.args] hs_result = self.annotator.binding(spaceop.result) + if not isinstance(hs_result, SomeLLAbstractConstant): + return False # was generalized, e.g. to SomeLLAbstractVariable hs_f1 = args_hs.pop(0) fnobj = hs_f1.const._obj if (getattr(self.annotator.policy, 'oopspec', False) and Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/oop.py Wed Sep 20 17:18:22 2006 @@ -2,6 +2,7 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, rtimeshift +from pypy.translator.c import exceptiontransform class Index: @@ -13,7 +14,6 @@ __metaclass__ = cachedtype def __init__(self, hrtyper, fnobj): - ts = hrtyper.timeshifter ll_func = fnobj._callable FUNCTYPE = lltype.typeOf(fnobj) nb_args = len(FUNCTYPE.ARGS) @@ -45,7 +45,7 @@ if FUNCTYPE.RESULT is lltype.Void: self.errorbox = None else: - error_value = ts.error_value(FUNCTYPE.RESULT) + error_value = exceptiontransform.error_value(FUNCTYPE.RESULT) self.errorbox = rvalue.redbox_from_prebuilt_value(RGenOp, error_value) self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT) @@ -64,8 +64,9 @@ # exception handling graph = fnobj.graph - self.can_raise = ts.etrafo.raise_analyzer.analyze_direct_call(graph) - self.fetch_global_excdata = ts.fetch_global_excdata + etrafo = hrtyper.etrafo + self.can_raise = etrafo.raise_analyzer.analyze_direct_call(graph) + self.fetch_global_excdata = hrtyper.fetch_global_excdata def residual_call(self, jitstate, argboxes): builder = jitstate.curbuilder Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Wed Sep 20 17:18:22 2006 @@ -727,7 +727,7 @@ # handling of the various kinds of calls - def handle_oopspec_call(self, hop): + def translate_op_oopspec_call(self, hop): # special-cased call, for things like list methods from pypy.jit.timeshifter.oop import OopSpecDesc, Index @@ -776,9 +776,7 @@ [v_jitstate, c_oopspecdesc] + args_v, s_result) - def handle_green_call(self, hop): - # green-returning call, for now (XXX) we assume it's an - # all-green function that we can just call + def translate_op_green_call(self, hop): for r_arg in hop.args_r: assert isinstance(r_arg, GreenRepr) v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype) Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py Wed Sep 20 17:18:22 2006 @@ -887,6 +887,18 @@ res = self.timeshift(ll_function, [3], [], policy=P_NOVIRTUAL) assert res == 3 + def test_green_call(self): + def ll_add_one(x): + return x+1 + def ll_function(y): + z = ll_add_one(y) + z = hint(z, concrete=True) + return hint(z, variable=True) + + res = self.timeshift(ll_function, [3], [0], policy=P_NOVIRTUAL) + assert res == 4 + self.check_insns({}) + def test_split_on_green_return(self): py.test.skip("in-progress") def ll_two(x): Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Wed Sep 20 17:18:22 2006 @@ -347,3 +347,15 @@ block.renamevariables(mapping) block.inputargs = saved block.operations[:0] = beforeops + newops + + def handle_oopspec_call(self, block, pos): + op = block.operations[pos] + assert op.opname == 'direct_call' + op.opname = 'oopspec_call' + + def handle_green_call(self, block, pos): + # green-returning call, for now (XXX) we assume it's an + # all-green function that we can just call + op = block.operations[pos] + assert op.opname == 'direct_call' + op.opname = 'green_call' Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/vlist.py Wed Sep 20 17:18:22 2006 @@ -8,7 +8,7 @@ def __init__(self, hrtyper, LIST): RGenOp = hrtyper.RGenOp - rtyper = hrtyper.timeshifter.rtyper + rtyper = hrtyper.rtyper self.LIST = LIST self.LISTPTR = lltype.Ptr(LIST) self.ptrkind = RGenOp.kindToken(self.LISTPTR) From arigo at codespeak.net Wed Sep 20 17:41:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 17:41:55 +0200 (CEST) Subject: [pypy-svn] r32537 - pypy/branch/timeshift-refactoring/pypy/jit/timeshifter Message-ID: <20060920154155.E86C91007F@code0.codespeak.net> Author: arigo Date: Wed Sep 20 17:41:54 2006 New Revision: 32537 Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Log: (arre, arigo) Trivial fix. Now all tests seem to pass again! Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py Wed Sep 20 17:41:54 2006 @@ -255,7 +255,7 @@ def getlocalbox(jitstate, i): return jitstate.frame.local_boxes[i] -def getgreenbox(jitstate, i, T): +def ll_getgreenbox(jitstate, i, T): return jitstate.greens[i].revealconst(T) def getreturnbox(jitstate): Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Wed Sep 20 17:41:54 2006 @@ -614,7 +614,7 @@ c_TYPE = hop.inputconst(lltype.Void, TYPE) s_result = annmodel.lltype_to_annotation(TYPE) v_jitstate = hop.llops.getjitstate() - return hop.llops.genmixlevelhelpercall(rtimeshift.getgreenbox, + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_getgreenbox, [self.s_JITState, annmodel.SomeInteger(nonneg=True), s_TYPE], [v_jitstate , c_index , c_TYPE], s_result) From cfbolz at codespeak.net Wed Sep 20 18:43:04 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Sep 2006 18:43:04 +0200 (CEST) Subject: [pypy-svn] r32538 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060920164304.5F19210070@code0.codespeak.net> Author: cfbolz Date: Wed Sep 20 18:43:02 2006 New Revision: 32538 Modified: pypy/dist/pypy/module/_random/interp_random.py pypy/dist/pypy/module/_random/test/test_random.py Log: fix overflow error. Fix some problems in getrandbits that made the method produce too many random bits. Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Wed Sep 20 18:43:02 2006 @@ -7,7 +7,7 @@ import time -def descr_new__(space, w_subtype, w_anything=NoneNotWrapped): +def descr_new__(space, w_subtype, w_anything=None): x = space.allocate_instance(W_Random, w_subtype) W_Random.__init__(x, space, w_anything) return space.wrap(x) @@ -22,7 +22,7 @@ return space.newfloat(self._rnd.random()) random.unwrap_spec = ['self', ObjSpace] - def seed(self, space, w_n=NoneNotWrapped): + def seed(self, space, w_n=None): if w_n is None: w_n = space.newint(int(time.time())) else: @@ -53,7 +53,7 @@ def getstate(self, space): state = [None] * (rpy_random.N + 1) for i in range(rpy_random.N): - state[i] = space.newlong(self._rnd.state[i]) + state[i] = space.newlong(int(self._rnd.state[i])) state[rpy_random.N] = space.newint(self._rnd.index) return space.newtuple(state) getstate.unwrap_spec = ['self', ObjSpace] @@ -65,8 +65,14 @@ if space.int_w(space.len(w_state)) != rpy_random.N + 1: errstring = space.wrap("state vector is the wrong size") raise OperationError(space.w_TypeError, errstring) + w_zero = space.newint(0) + # independent of platfrom, since the below condition is only + # true on 32 bit platforms anyway + w_add = space.pow(space.newint(2), space.newint(32), space.w_None) for i in range(rpy_random.N): w_item = space.getitem(w_state, space.newint(i)) + if space.is_true(space.lt(w_item, w_zero)): + w_item = space.add(w_item, w_add) self._rnd.state[i] = space.uint_w(w_item) w_item = space.getitem(w_state, space.newint(rpy_random.N)) self._rnd.index = space.int_w(w_item) @@ -83,21 +89,23 @@ bytes = ((k - 1) // 32 + 1) * 4 bytesarray = [0] * bytes for i in range(0, bytes, 4): - k -= 32 r = self._rnd.genrand32() - if k < 0: - k >>= (32 - k) + if k < 32: + r >>= (32 - k) bytesarray[i + 0] = r & r_uint(0xff) bytesarray[i + 1] = (r >> 8) & r_uint(0xff) bytesarray[i + 2] = (r >> 16) & r_uint(0xff) bytesarray[i + 3] = (r >> 24) & r_uint(0xff) + k -= 32 + print bytesarray # XXX so far this is quadratic w_result = space.newlong(0) w_eight = space.newlong(8) - for byte in bytesarray: - w_result = space.lshift( - space.or_(w_result, space.newlong(int(byte))), w_eight) + for i in range(len(bytesarray) - 1, -1, -1): + byte = bytesarray[i] + w_result = space.or_(space.lshift(w_result, w_eight), + space.newlong(int(byte))) return w_result getrandbits.unwrap_spec = ['self', ObjSpace, int] Modified: pypy/dist/pypy/module/_random/test/test_random.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_random.py (original) +++ pypy/dist/pypy/module/_random/test/test_random.py Wed Sep 20 18:43:02 2006 @@ -36,6 +36,13 @@ assert [rnd1.random() for i in range(100)] == [ rnd2.random() for i in range(100)] + def test_setstate_negative(self): + # XXX does only make sense on a 32 bit platform + import _random + rnd1 = _random.Random() + # does not crash + rnd1.setstate((-1, ) * 624 + (0, )) + def test_seed(self): import _random rnd = _random.Random() @@ -69,6 +76,6 @@ import math import _random rnd = _random.Random() - for n in range(10, 200, 10): - n = rnd.getrandbits(n) - assert int(math.log(n) / math.log(2)) <= n + for n in range(1, 10) + range(10, 1000, 15): + k = rnd.getrandbits(n) + assert 0 <= k < 2 ** n From cfbolz at codespeak.net Wed Sep 20 18:45:27 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Sep 2006 18:45:27 +0200 (CEST) Subject: [pypy-svn] r32539 - pypy/dist/pypy/module/_random Message-ID: <20060920164527.EFC5110070@code0.codespeak.net> Author: cfbolz Date: Wed Sep 20 18:45:26 2006 New Revision: 32539 Modified: pypy/dist/pypy/module/_random/interp_random.py Log: fix exception type Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Wed Sep 20 18:45:26 2006 @@ -64,7 +64,7 @@ raise OperationError(space.w_TypeError, errstring) if space.int_w(space.len(w_state)) != rpy_random.N + 1: errstring = space.wrap("state vector is the wrong size") - raise OperationError(space.w_TypeError, errstring) + raise OperationError(space.w_ValueError, errstring) w_zero = space.newint(0) # independent of platfrom, since the below condition is only # true on 32 bit platforms anyway From cfbolz at codespeak.net Wed Sep 20 18:47:07 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Sep 2006 18:47:07 +0200 (CEST) Subject: [pypy-svn] r32540 - pypy/dist/pypy/module/_random Message-ID: <20060920164707.C07BA1007B@code0.codespeak.net> Author: cfbolz Date: Wed Sep 20 18:47:06 2006 New Revision: 32540 Modified: pypy/dist/pypy/module/_random/interp_random.py Log: remove debug print Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Wed Sep 20 18:47:06 2006 @@ -97,7 +97,6 @@ bytesarray[i + 2] = (r >> 16) & r_uint(0xff) bytesarray[i + 3] = (r >> 24) & r_uint(0xff) k -= 32 - print bytesarray # XXX so far this is quadratic w_result = space.newlong(0) From cfbolz at codespeak.net Wed Sep 20 18:51:15 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Sep 2006 18:51:15 +0200 (CEST) Subject: [pypy-svn] r32541 - in pypy/dist/pypy/module/_random: . test Message-ID: <20060920165115.D80B21007B@code0.codespeak.net> Author: cfbolz Date: Wed Sep 20 18:51:14 2006 New Revision: 32541 Modified: pypy/dist/pypy/module/_random/rpy_random.py pypy/dist/pypy/module/_random/test/test_mersenne.py Log: rpy_random is translatable, not so sure about the whole python module Modified: pypy/dist/pypy/module/_random/rpy_random.py ============================================================================== --- pypy/dist/pypy/module/_random/rpy_random.py (original) +++ pypy/dist/pypy/module/_random/rpy_random.py Wed Sep 20 18:51:14 2006 @@ -11,6 +11,14 @@ MATRIX_A = r_uint(0x9908b0df) # constant vector a UPPER_MASK = r_uint(0x80000000) # most significant w-r bits LOWER_MASK = r_uint(0x7fffffff) # least significant r bits +MASK_32 = r_uint(0xffffffff) +TEMPERING_MASK_A = r_uint(0x9d2c5680) +TEMPERING_MASK_B = r_uint(0xefc60000) +MAGIC_CONSTANT_A = r_uint(1812433253) +MAGIC_CONSTANT_B = r_uint(19650218) +MAGIC_CONSTANT_C = r_uint(1664525) +MAGIC_CONSTANT_D = r_uint(1566083941) + class Random(object): def __init__(self, seed=r_uint(0)): @@ -21,21 +29,21 @@ def init_genrand(self, s): mt = self.state - mt[0]= s & r_uint(0xffffffff) + mt[0]= s & MASK_32 for mti in range(1, N): - mt[mti] = (r_uint(1812433253) * + mt[mti] = (MAGIC_CONSTANT_A * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti) # See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. # In the previous versions, MSBs of the seed affect # only MSBs of the array mt[]. # for >32 bit machines - mt[mti] &= r_uint(0xffffffff) - self.index = mti + 1 + mt[mti] &= MASK_32 + self.index = N def init_by_array(self, init_key): key_length = len(init_key) mt = self.state - self.init_genrand(r_uint(19650218)) + self.init_genrand(MAGIC_CONSTANT_B) i = 1 j = 0 if N > key_length: @@ -44,9 +52,9 @@ max_k = key_length for k in range(max_k, 0, -1): mt[i] = ((mt[i] ^ - ((mt[i - 1] ^ (mt[i - 1] >> 30)) * r_uint(1664525))) + ((mt[i - 1] ^ (mt[i - 1] >> 30)) * MAGIC_CONSTANT_C)) + init_key[j] + j) # non linear - mt[i] &= r_uint(0xffffffff) # for WORDSIZE > 32 machines + mt[i] &= MASK_32 # for WORDSIZE > 32 machines i += 1 j += 1 if i >= N: @@ -56,14 +64,14 @@ j = 0 for k in range(N - 1, 0, -1): mt[i] = ((mt[i] ^ - ((mt[i - 1] ^ (mt[i - 1] >> 30)) * r_uint(1566083941))) + ((mt[i - 1] ^ (mt[i - 1] >> 30)) * MAGIC_CONSTANT_D)) - i) # non linear - mt[i] &= r_uint(0xffffffff) # for WORDSIZE > 32 machines + mt[i] &= MASK_32 # for WORDSIZE > 32 machines i += 1 if (i>=N): mt[0] = mt[N - 1] i = 1 - mt[0] = r_uint(0x80000000) + mt[0] = UPPER_MASK def genrand32(self): mag01 = [0, MATRIX_A] @@ -81,8 +89,8 @@ y = mt[self.index] self.index += 1 y ^= y >> 11 - y ^= (y << 7) & r_uint(0x9d2c5680) - y ^= (y << 15) & r_uint(0xefc60000) + y ^= (y << 7) & TEMPERING_MASK_A + y ^= (y << 15) & TEMPERING_MASK_B y ^= (y >> 18) return y Modified: pypy/dist/pypy/module/_random/test/test_mersenne.py ============================================================================== --- pypy/dist/pypy/module/_random/test/test_mersenne.py (original) +++ pypy/dist/pypy/module/_random/test/test_mersenne.py Wed Sep 20 18:51:14 2006 @@ -35,3 +35,14 @@ rnd.jumpahead(100) cpyrandom.jumpahead(100) assert tuple(rnd.state) + (rnd.index, ) == cpyrandom.getstate() + +def test_translate(): + from pypy.translator.interactive import Translation + def f(x, y): + rnd = Random(x) + rnd.init_by_array([x, y]) + rnd.jumpahead(y) + return rnd.genrand32(), rnd.random() + t = Translation(f) + fc = t.compile_c([int, int]) + assert fc(1, 2) == f(1, 2) From arigo at codespeak.net Wed Sep 20 20:16:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 20:16:45 +0200 (CEST) Subject: [pypy-svn] r32542 - pypy/branch/timeshift-refactoring/pypy/translator Message-ID: <20060920181645.9D6A310075@code0.codespeak.net> Author: arigo Date: Wed Sep 20 20:16:44 2006 New Revision: 32542 Modified: pypy/branch/timeshift-refactoring/pypy/translator/simplify.py Log: (arre, arigo) Wrongly placed assert! An empty infinite loop produced by the JIT by mistake caused an infinite look in eliminate_empty_blocks(). Modified: pypy/branch/timeshift-refactoring/pypy/translator/simplify.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/translator/simplify.py (original) +++ pypy/branch/timeshift-refactoring/pypy/translator/simplify.py Wed Sep 20 20:16:44 2006 @@ -63,10 +63,10 @@ if (len(link.target.exits) != 1 and link.target.exitswitch != c_last_exception): break - assert link.target is not link.prevblock, ( - "the graph contains an empty infinite loop") block1 = link.target exit = block1.exits[0] + assert block1 is not exit.target, ( + "the graph contains an empty infinite loop") outputargs = [] for v in exit.args: if isinstance(v, Variable): From arigo at codespeak.net Wed Sep 20 20:18:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 20:18:40 +0200 (CEST) Subject: [pypy-svn] r32543 - in pypy/branch/timeshift-refactoring/pypy/jit/timeshifter: . test Message-ID: <20060920181840.986E21007B@code0.codespeak.net> Author: arigo Date: Wed Sep 20 20:18:39 2006 New Revision: 32543 Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Log: (arre, arigo) Yellow calls! The first real progress of the week, but it was worth the effort. Turned the dispatch_queue's lists of jitstates into chains (linked lists) to make it easier to give a type to "list of jitstates": it's the same as "jitstate". (It's also more efficient, and less readable.) Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py Wed Sep 20 20:18:39 2006 @@ -234,10 +234,26 @@ later_builder = jitstate.curbuilder.jump_if_false(exitgvar) jitstate.split(later_builder, resumepoint, list(greens_gv)) +def collect_split(jitstate_chain, resumepoint, *greens_gv): + greens_gv = list(greens_gv) + pending = jitstate_chain + while True: + jitstate = pending + pending = pending.next + jitstate.greens.extend(greens_gv) # item 0 is the return value + jitstate.resumepoint = resumepoint + if pending is None: + break + dispatch_queue = jitstate_chain.frame.dispatch_queue + jitstate.next = dispatch_queue.split_chain + dispatch_queue.split_chain = jitstate_chain.next + # XXX obscurity++ above + def dispatch_next(oldjitstate): - split_queue = oldjitstate.frame.dispatch_queue.split_queue - if split_queue: - jitstate = split_queue.pop() + dispatch_queue = oldjitstate.frame.dispatch_queue + if dispatch_queue.split_chain is not None: + jitstate = dispatch_queue.split_chain + dispatch_queue.split_chain = jitstate.next enter_block(jitstate) return jitstate else: @@ -252,6 +268,9 @@ assert None not in redboxes jitstate.frame.local_boxes = redboxes +def save_greens(jitstate, *greens_gv): + jitstate.greens = list(greens_gv) + def getlocalbox(jitstate, i): return jitstate.frame.local_boxes[i] @@ -274,7 +293,10 @@ jitstate.exc_value_box = box def save_return(jitstate): - jitstate.frame.dispatch_queue.return_queue.append(jitstate) + # add 'jitstate' to the chain of return-jitstates + dispatch_queue = jitstate.frame.dispatch_queue + jitstate.next = dispatch_queue.return_chain + dispatch_queue.return_chain = jitstate ##def ll_gvar_from_redbox(jitstate, redbox): ## return redbox.getgenvar(jitstate.curbuilder) @@ -286,8 +308,8 @@ class BaseDispatchQueue(object): def __init__(self): - self.split_queue = [] # XXX could be turned into a linked list - self.return_queue = [] # XXX could be turned into a linked list + self.split_chain = None + self.return_chain = None def build_dispatch_subclass(attrnames): if len(attrnames) == 0: @@ -387,6 +409,7 @@ class JITState(object): returnbox = None + next = None # for linked lists def __init__(self, builder, frame, exc_type_box, exc_value_box, resumepoint=-1, newgreens=[]): @@ -405,7 +428,10 @@ self.exc_value_box.copy(memo), newresumepoint, newgreens) - self.frame.dispatch_queue.split_queue.append(later_jitstate) + # add the later_jitstate to the chain of pending-for-dispatch_next() + dispatch_queue = self.frame.dispatch_queue + later_jitstate.next = dispatch_queue.split_chain + dispatch_queue.split_chain = later_jitstate def enter_block(self, incoming, memo): self.frame.enter_block(incoming, memo) @@ -431,17 +457,25 @@ # XXX is that too many specializations? ^^^ def merge_returning_jitstates(jitstate): - return_queue = jitstate.frame.dispatch_queue.return_queue + return_chain = jitstate.frame.dispatch_queue.return_chain return_cache = {} - still_pending = [] - for jitstate in return_queue: + still_pending = None + while return_chain is not None: + jitstate = return_chain + return_chain = return_chain.next res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) if res is False: # not finished - still_pending.append(jitstate) - for jitstate in still_pending[:-1]: + jitstate.next = still_pending + still_pending = jitstate + assert still_pending is not None + most_general_jitstate = still_pending + still_pending = still_pending.next + while still_pending is not None: + jitstate = still_pending + still_pending = still_pending.next res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) assert res is True # finished - return still_pending[-1] + return most_general_jitstate def leave_graph_red(jitstate): jitstate = merge_returning_jitstates(jitstate) @@ -456,3 +490,11 @@ myframe = jitstate.frame jitstate.frame = myframe.backframe return jitstate + +def leave_graph_yellow(jitstate): + return_chain = jitstate.frame.dispatch_queue.return_chain + jitstate = return_chain + while jitstate is not None: + jitstate.frame = jitstate.frame.backframe + jitstate = jitstate.next + return return_chain # a jitstate, which is the head of the chain Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py Wed Sep 20 20:18:39 2006 @@ -577,6 +577,14 @@ self.s_JITState) hop.llops.setjitstate(v_newjs) + def translate_op_leave_graph_yellow(self, hop): + v_jitstate = hop.llops.getjitstate() + v_njs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_njs) + def translate_op_save_locals(self, hop): v_jitstate = hop.llops.getjitstate() boxes_r = [self.getredrepr(originalconcretetype(hs)) @@ -588,6 +596,15 @@ [v_jitstate ] + boxes_v, annmodel.s_None) + def translate_op_save_greens(self, hop): + v_jitstate = hop.llops.getjitstate() + greens_v = list(self.wrap_green_vars(hop.llops, hop.args_v)) + greens_s = [self.s_ConstOrVar] * len(greens_v) + return hop.llops.genmixlevelhelpercall(rtimeshift.save_greens, + [self.s_JITState] + greens_s, + [v_jitstate ] + greens_v, + annmodel.s_None) + def translate_op_enter_block(self, hop): v_jitstate = hop.llops.getjitstate() hop.llops.genmixlevelhelpercall(rtimeshift.enter_block, @@ -677,6 +694,24 @@ hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v, annmodel.s_None) + def translate_op_collect_split(self, hop): + GREENS = [v.concretetype for v in hop.args_v[1:]] + greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS] + vlist = hop.inputargs(lltype.Signed, *greens_r) + + v_jitstate = hop.llops.getjitstate() + c_resumepoint = vlist[0] + greens_v = list(self.wrap_green_vars(hop.llops, vlist[1:])) + + s_Int = annmodel.SomeInteger(nonneg=True) + args_s = [self.s_JITState, s_Int] + args_s += [self.s_ConstOrVar] * len(greens_v) + args_v = [v_jitstate, c_resumepoint] + args_v += greens_v + hop.llops.genmixlevelhelpercall(rtimeshift.collect_split, + args_s, args_v, + annmodel.s_None) + def translate_op_merge_point(self, hop): mpfamily = hop.args_v[0].value attrname = hop.args_v[1].value @@ -800,6 +835,8 @@ v_newjitstate = hop.genop('direct_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) + translate_op_yellow_call = translate_op_red_call + class HintLowLevelOpList(LowLevelOpList): """Warning: the HintLowLevelOpList's rtyper is the *original* Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py Wed Sep 20 20:18:39 2006 @@ -900,7 +900,6 @@ self.check_insns({}) def test_split_on_green_return(self): - py.test.skip("in-progress") def ll_two(x): if x > 0: return 17 @@ -908,7 +907,7 @@ return 22 def ll_function(x): n = ll_two(x) - return n+1 + return hint(n+1, variable=True) res = self.timeshift(ll_function, [-70], []) assert res == 23 self.check_insns({'int_gt': 1}) Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Wed Sep 20 20:18:39 2006 @@ -8,6 +8,7 @@ from pypy.translator.unsimplify import varoftype, copyvar from pypy.translator.unsimplify import split_block, split_block_at_start from pypy.translator.backendopt.ssa import SSA_to_SSI +from pypy.translator.backendopt import support class MergePointFamily(object): @@ -22,6 +23,7 @@ class HintGraphTransformer(object): + c_dummy = inputconst(lltype.Void, None) def __init__(self, hannotator, graph): self.hannotator = hannotator @@ -128,7 +130,7 @@ split_block(self.hannotator, block, 0) [link] = block.exits assert len(link.args) == 0 - link.args = [inputconst(lltype.Void, None)] + link.args = [self.c_dummy] link.target.inputargs = [self.new_void_var('dummy')] self.graph.returnblock = link.target self.graph.returnblock.operations = () @@ -183,9 +185,9 @@ constant_block : False, nonconstant_block: False}, self.hannotator) - def get_resume_point(self, block): + def get_resume_point_link(self, block): try: - reenter_link = self.resumepoints[block] + return self.resumepoints[block] except KeyError: resumeblock = Block([]) redcount = 0 @@ -209,7 +211,10 @@ N = len(self.resumepoints) reenter_link.exitcase = N self.resumepoints[block] = reenter_link - return reenter_link.exitcase + return reenter_link + + def get_resume_point(self, block): + return self.get_resume_point_link(block).exitcase def insert_merge(self, block): reds, greens = self.sort_by_color(block.inputargs) @@ -223,7 +228,7 @@ result_type = lltype.Bool) block.exitswitch = v_finished_flag [link_f] = block.exits - link_t = Link([inputconst(lltype.Void, None)], self.graph.returnblock) + link_t = Link([self.c_dummy], self.graph.returnblock) link_f.exitcase = False link_t.exitcase = True block.recloseblock(link_f, link_t) @@ -261,6 +266,9 @@ if originalconcretetype(hs_retbox) is lltype.Void: self.leave_graph_opname = 'leave_graph_void' self.genop(block, 'save_locals', []) + elif hs_retbox.is_green(): + self.leave_graph_opname = 'leave_graph_yellow' + self.genop(block, 'save_greens', [v_retbox]) else: self.leave_graph_opname = 'leave_graph_red' self.genop(block, 'save_locals', [v_retbox]) @@ -359,3 +367,32 @@ op = block.operations[pos] assert op.opname == 'direct_call' op.opname = 'green_call' + + def handle_yellow_call(self, block, pos): + link = support.split_block_with_keepalive(block, pos+1, + annotator=self.hannotator) + op = block.operations.pop(pos) + assert len(block.operations) == pos + nextblock = link.target + varsalive = link.args + try: + index = varsalive.index(op.result) + except ValueError: + XXX-later + + del varsalive[index] + v_result = nextblock.inputargs.pop(index) + nextblock.inputargs.insert(0, v_result) + + reds, greens = self.sort_by_color(varsalive) + self.genop(block, 'save_locals', reds) + self.genop(block, 'yellow_call', op.args) # Void result, like red_call + + resumepoint = self.get_resume_point(nextblock) + c_resumepoint = inputconst(lltype.Signed, resumepoint) + self.genop(block, 'collect_split', [c_resumepoint] + greens) + link.args = [] + link.target = self.get_resume_point_link(nextblock).target + + self.insert_merge(nextblock) # to merge some of the possibly many + # return jitstates From pedronis at codespeak.net Wed Sep 20 21:27:53 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Sep 2006 21:27:53 +0200 (CEST) Subject: [pypy-svn] r32544 - in pypy/dist/pypy: interpreter interpreter/test objspace/cpy Message-ID: <20060920192753.49E9810074@code0.codespeak.net> Author: pedronis Date: Wed Sep 20 21:27:50 2006 New Revision: 32544 Modified: pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/interpreter/test/test_gateway.py pypy/dist/pypy/objspace/cpy/function.py Log: killing builtin frames as such. first pass at killing the convoluted setup in gateway.py. Still using instances called activations to share code for similar patterns of unwrap specs: whether is worth to be checked later by trying to go for just attaching directly a "run" function to the builtin code object. PyPy is slightly smaller. The emit recipe can/needs to be simplified further. Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Wed Sep 20 21:27:50 2006 @@ -158,61 +158,61 @@ "obj = %s(scope_w[%d])" % (name, cur)) emit_sig.miniglobals[name] = func emit_sig.setfastscope.append( - "self.%s_arg%d = obj" % (name,cur)) + "%s_arg%d = obj" % (name,cur)) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("self.%s_arg%d" % (name,cur)) + emit_sig.run_args.append("%s_arg%d" % (name,cur)) def visit__Wrappable(self, el, orig_sig, emit_sig): name = el.__name__ cur = emit_sig.through_scope_w emit_sig.setfastscope.append( - "obj = self.space.interp_w(%s, scope_w[%d])" % (name, cur)) + "obj = space.interp_w(%s, scope_w[%d])" % (name, cur)) emit_sig.miniglobals[name] = el emit_sig.setfastscope.append( - "self.%s_arg%d = obj" % (name,cur)) + "%s_arg%d = obj" % (name,cur)) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("self.%s_arg%d" % (name,cur)) + emit_sig.run_args.append("%s_arg%d" % (name,cur)) def visit__ObjSpace(self, el, orig_sig, emit_sig): - emit_sig.run_args.append('self.space') + emit_sig.run_args.append('space') def visit__W_Root(self, el, orig_sig, emit_sig): cur = emit_sig.through_scope_w emit_sig.setfastscope.append( - "self.w_arg%d = scope_w[%d]" % (cur,cur)) + "w_arg%d = scope_w[%d]" % (cur,cur)) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("self.w_arg%d" % cur) + emit_sig.run_args.append("w_arg%d" % cur) def visit__Arguments(self, el, orig_sig, emit_sig): cur = emit_sig.through_scope_w emit_sig.through_scope_w += 2 emit_sig.miniglobals['Arguments'] = Arguments emit_sig.setfastscope.append( - "self.arguments_arg = " - "Arguments.frompacked(self.space,scope_w[%d],scope_w[%d])" + "arguments_arg = " + "Arguments.frompacked(space,scope_w[%d],scope_w[%d])" % (cur, cur+1)) - emit_sig.run_args.append("self.arguments_arg") + emit_sig.run_args.append("arguments_arg") def visit_starargs(self, el, orig_sig, emit_sig): emit_sig.setfastscope.append( - "self.starargs_arg_w = self.space.unpacktuple(scope_w[%d])" % + "starargs_arg_w = space.unpacktuple(scope_w[%d])" % (emit_sig.through_scope_w)) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("*self.starargs_arg_w") + emit_sig.run_args.append("*starargs_arg_w") def visit_args_w(self, el, orig_sig, emit_sig): emit_sig.setfastscope.append( - "self.args_w = self.space.unpacktuple(scope_w[%d])" % + "args_w = space.unpacktuple(scope_w[%d])" % (emit_sig.through_scope_w)) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("self.args_w") + emit_sig.run_args.append("args_w") def visit_w_args(self, el, orig_sig, emit_sig): cur = emit_sig.through_scope_w emit_sig.setfastscope.append( - "self.w_args = scope_w[%d]" % cur) + "w_args = scope_w[%d]" % cur) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("self.w_args") + emit_sig.run_args.append("w_args") def visit__object(self, el, orig_sig, emit_sig): if el not in (int, str, float): @@ -220,10 +220,10 @@ name = el.__name__ cur = emit_sig.through_scope_w emit_sig.setfastscope.append( - "self.%s_arg%d = self.space.%s_w(scope_w[%d])" % + "%s_arg%d = space.%s_w(scope_w[%d])" % (name,cur,name,cur)) emit_sig.through_scope_w += 1 - emit_sig.run_args.append("self.%s_arg%d" % (name,cur)) + emit_sig.run_args.append("%s_arg%d" % (name,cur)) class UnwrapSpec_FastFunc_Unwrap(UnwrapSpecRecipe): @@ -269,51 +269,16 @@ info.narg +=1 -class BuiltinFrame(eval.Frame): - "Frame emulation for BuiltinCode." - # Subclasses of this are defined with the function to delegate to attached through miniglobals. - # Initialization of locals is already done by the time run() is called, - # via the interface defined in eval.Frame. - - def __init__(self, space, code, w_globals=None, numlocals=-1): - self.bltn_code = code - eval.Frame.__init__(self, space, w_globals, numlocals) +class BuiltinActivation(object): - def getcode(self): - return self.bltn_code - - def setfastscope(self, scope_w): - """Subclasses with behavior specific for an unwrap spec are generated""" - raise TypeError, "abstract" - - def getfastscope(self): - raise OperationError(self.space.w_TypeError, - self.space.wrap("cannot get fastscope of a BuiltinFrame")) - - def run(self): - try: - w_result = self._run() - except KeyboardInterrupt: - raise OperationError(self.space.w_KeyboardInterrupt, self.space.w_None) - except MemoryError: - raise OperationError(self.space.w_MemoryError, self.space.w_None) - except RuntimeError, e: - raise OperationError(self.space.w_RuntimeError, - self.space.wrap("internal error: " + str(e))) - if w_result is None: - w_result = self.space.w_None - return w_result + def __init__(self, behavior): + """NOT_RPYTHON""" + self.behavior = behavior - def _run(self): + def _run(self, space, scope_w): """Subclasses with behavior specific for an unwrap spec are generated""" raise TypeError, "abstract" -class BuiltinFrameFactory(object): - """Subclasses can create builtin frames for a associated builtin""" - - def create(self, space, code, w_globals): - raise TypeError, "abstract" - class BuiltinCodeSignature(Signature): "NOT_RPYTHON" @@ -326,12 +291,12 @@ self.through_scope_w = 0 self.miniglobals = {} - def _make_unwrap_frame_factory_class(self, cache={}): + def _make_unwrap_activation_class(self, cache={}): try: key = tuple(self.unwrap_spec) - frame_factory_cls, run_args = cache[key] + activation_factory_cls, run_args = cache[key] assert run_args == self.run_args,"unexpected: same spec, different run_args" - return frame_factory_cls + return activation_factory_cls except KeyError: parts = [] for el in self.unwrap_spec: @@ -341,68 +306,39 @@ parts.append(getattr(el, '__name__', el)) label = '_'.join(parts) #print label + setfastscope = self.setfastscope if not setfastscope: setfastscope = ["pass"] - setfastscope = ["def setfastscope_UWS_%s(self, scope_w):" % label, - #"print 'ENTER',self.code.func.__name__", - #"print scope_w" - ] + setfastscope - setfastscope = '\n '.join(setfastscope) - # Python 2.2 SyntaxError without newline: Bug #501622 - setfastscope += '\n' - d = {} - exec compile2(setfastscope) in self.miniglobals, d - d['setfastscope'] = d['setfastscope_UWS_%s' % label] - del d['setfastscope_UWS_%s' % label] + setfastscope = '\n '.join(setfastscope) # xxx indentation below - self.miniglobals['OperationError'] = OperationError - self.miniglobals['os'] = os + d = {} source = """if 1: - def _run_UWS_%s(self): - try: - return self.behavior(%s) - except MemoryError: - os.write(2, 'Fail in _run() of ' + self.b_name + '\\n') - raise - \n""" % (label, ','.join(self.run_args)) + def _run_UWS_%s(self, space, scope_w): + %s + return self.behavior(%s) + \n""" % (label, setfastscope, ','.join(self.run_args)) exec compile2(source) in self.miniglobals, d d['_run'] = d['_run_UWS_%s' % label] del d['_run_UWS_%s' % label] - frame_cls = type("BuiltinFrame_UwS_%s" % label, (BuiltinFrame,), d) - - class MyBuiltinFrameFactory(BuiltinFrameFactory): - # export 'unwrap_spec' for inspection from outside gateway.py - unwrap_spec = self.unwrap_spec + activation_cls = type("BuiltinActivation_UwS_%s" % label, + (BuiltinActivation,), d) - def create(self, space, code, w_globals): - newframe = frame_cls(space, code, w_globals) - newframe.behavior = self.behavior - newframe.b_name = self.b_name - return newframe + cache[key] = activation_cls, self.run_args + return activation_cls - MyBuiltinFrameFactory.__name__ = 'BuiltinFrameFactory_UwS_%s' % label - - cache[key] = MyBuiltinFrameFactory, self.run_args - return MyBuiltinFrameFactory - - def make_frame_factory(self, func): - frame_uw_factory_cls = self._make_unwrap_frame_factory_class() + def make_activation(self, func): + activation_uw_cls = self._make_unwrap_activation_class() + return activation_uw_cls(func) - factory = frame_uw_factory_cls() - factory.behavior = func - factory.b_name = func.__name__ - - return factory - -def make_builtin_frame_factory(func, orig_sig, unwrap_spec): +def make_builtin_activation(func, orig_sig, unwrap_spec): "NOT_RPYTHON" name = (getattr(func, '__module__', None) or '')+'_'+func.__name__ emit_sig = BuiltinCodeSignature(name=name, unwrap_spec=unwrap_spec) orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Emit(), dest_sig = emit_sig) - return emit_sig.make_frame_factory(func) + return emit_sig.make_activation(func) class FastFuncNotSupported(Exception): pass @@ -451,6 +387,8 @@ # When a BuiltinCode is stored in a Function object, # you get the functionality of CPython's built-in function type. + NOT_RPYTHON_ATTRIBUTES = ['_bltin', '_unwrap_spec'] + def __init__(self, func, unwrap_spec = None, self_type = None): "NOT_RPYTHON" # 'implfunc' is the interpreter-level function. @@ -502,7 +440,9 @@ else: self.maxargs = self.minargs - self.framefactory = make_builtin_frame_factory(func, orig_sig, unwrap_spec) + self.activation = make_builtin_activation(func, orig_sig, unwrap_spec) + self._bltin = func + self._unwrap_spec = unwrap_spec # speed hack if 0 <= len(unwrap_spec) <= 5: @@ -519,9 +459,8 @@ self.__class__ = globals()['BuiltinCode%d' % arity] setattr(self, 'fastfunc_%d' % arity, fastfunc) - def create_frame(self, space, w_globals, closure=None): - return self.framefactory.create(space, self, w_globals) + raise NotImplementedError def signature(self): return self.sig @@ -529,6 +468,23 @@ def getdocstring(self): return self.docstring + def funcrun(self, func, args): + space = func.space + activation = self.activation + scope_w = args.parse(func.name, self.sig, func.defs_w) + try: + w_result = activation._run(space, scope_w) + except KeyboardInterrupt: + raise OperationError(space.w_KeyboardInterrupt, + space.w_None) + except MemoryError: + raise OperationError(space.w_MemoryError, space.w_None) + except RuntimeError, e: + raise OperationError(space.w_RuntimeError, + space.wrap("internal error: " + str(e))) + if w_result is None: + w_result = space.w_None + return w_result # (verbose) performance hack below Modified: pypy/dist/pypy/interpreter/test/test_gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_gateway.py (original) +++ pypy/dist/pypy/interpreter/test/test_gateway.py Wed Sep 20 21:27:50 2006 @@ -1,9 +1,17 @@ import autopath from pypy.interpreter import gateway +from pypy.interpreter import argument import py import sys +class FakeFunc(object): + + def __init__(self, space, name): + self.space = space + self.name = name + self.defs_w = [] + class TestBuiltinCode: def test_signature(self): def c(space, w_x, w_y, *hello_w): @@ -39,8 +47,8 @@ gateway.W_Root, 'starargs']) w = self.space.wrap - w_dict = w({'x': 123, 'y': 23, 'hello': (0, True)}) - w_result = code.exec_code(self.space, w_dict, w_dict) + args = argument.Arguments(self.space, [w(123), w(23), w(0), w(True)]) + w_result = code.funcrun(FakeFunc(self.space, "c"), args) assert self.space.eq_w(w_result, w(102)) def test_call_args(self): @@ -55,9 +63,10 @@ gateway.W_Root, gateway.Arguments]) w = self.space.wrap - w_dict = w({'x': 123, 'y': 23, 'args': (0, True), - 'keywords': {'boo': 10}}) - w_result = code.exec_code(self.space, w_dict, w_dict) + args = argument.Arguments(self.space, [w(123), w(23)], {}, + w_stararg = w((0, True)), + w_starstararg = w({'boo': 10})) + w_result = code.funcrun(FakeFunc(self.space, "c"), args) assert self.space.eq_w(w_result, w(1020)) class TestGateway: Modified: pypy/dist/pypy/objspace/cpy/function.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/function.py (original) +++ pypy/dist/pypy/objspace/cpy/function.py Wed Sep 20 21:27:50 2006 @@ -95,9 +95,8 @@ space = cache.space # make a built-in function assert isinstance(func.code, BuiltinCode) # XXX - factory = func.code.framefactory - bltin = factory.behavior - unwrap_spec = factory.unwrap_spec + bltin = func.code._bltin + unwrap_spec = func.code._unwrap_spec from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature( bltin.func_code) From arigo at codespeak.net Wed Sep 20 22:21:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Sep 2006 22:21:22 +0200 (CEST) Subject: [pypy-svn] r32545 - in pypy/branch/timeshift-refactoring/pypy/jit: codegen/i386/test hintannotator Message-ID: <20060920202122.57B8010074@code0.codespeak.net> Author: arigo Date: Wed Sep 20 22:21:20 2006 New Revision: 32545 Modified: pypy/branch/timeshift-refactoring/pypy/jit/codegen/i386/test/test_genc_ts.py pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py Log: Minor fix, and some more hacking at greenargs(). Modified: pypy/branch/timeshift-refactoring/pypy/jit/codegen/i386/test/test_genc_ts.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/codegen/i386/test/test_genc_ts.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/codegen/i386/test/test_genc_ts.py Wed Sep 20 22:21:20 2006 @@ -15,7 +15,7 @@ SEPLINE = 'running residual graph...\n' def annotate_interface_functions(self): - annhelper = self.htshift.annhelper + annhelper = self.hrtyper.annhelper RGenOp = self.RGenOp SEPLINE = self.SEPLINE ml_generate_code = self.ml_generate_code Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py Wed Sep 20 22:21:20 2006 @@ -33,6 +33,7 @@ fixed = False read_positions = None greenargs_cached = None + is_call_result = False def __init__(self, bookkeeper=None, spaceop=None): self.bookkeeper = bookkeeper @@ -65,7 +66,7 @@ if self.greenargs_cached is not None: return self.greenargs_cached frame = GreenHandlerFrame(annotator) - if self.spaceop.opname == 'direct_call': # ah haa + if self.is_call_result: return frame.greencallresult(self.spaceop) else: for v in self.spaceop.args: @@ -345,6 +346,7 @@ if isinstance(hs_res, SomeLLAbstractConstant): hs_res.myorigin = bookkeeper.myorigin() + hs_res.myorigin.is_call_result = True # we need to make sure that hs_res does not become temporarily less # general as a result of calling another specialized version of the From cfbolz at codespeak.net Thu Sep 21 00:12:30 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 21 Sep 2006 00:12:30 +0200 (CEST) Subject: [pypy-svn] r32546 - in pypy/dist/pypy/objspace/cpy: . test Message-ID: <20060920221230.4A58710074@code0.codespeak.net> Author: cfbolz Date: Thu Sep 21 00:12:25 2006 New Revision: 32546 Modified: pypy/dist/pypy/objspace/cpy/capi.py pypy/dist/pypy/objspace/cpy/objspace.py pypy/dist/pypy/objspace/cpy/test/test_objspace.py Log: add newfloat and newlong to cpy object space Modified: pypy/dist/pypy/objspace/cpy/capi.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/capi.py (original) +++ pypy/dist/pypy/objspace/cpy/capi.py Thu Sep 21 00:12:25 2006 @@ -252,6 +252,10 @@ PyFloat_AsDouble.argtypes = [W_Object] PyFloat_AsDouble.restype = c_double +PyLong_FromLong = cpyapi.PyLong_FromLong +PyLong_FromLong.argtypes = [c_long] +PyLong_FromLong.restype = W_Object + PyLong_FromUnsignedLong = cpyapi.PyLong_FromUnsignedLong PyLong_FromUnsignedLong.argtypes = [c_ulong] PyLong_FromUnsignedLong.restype = W_Object Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Thu Sep 21 00:12:25 2006 @@ -69,7 +69,7 @@ return PyInt_FromLong(x) if isinstance(x, str): return PyString_FromStringAndSize(x, len(x)) - if isinstance(x, float): + if isinstance(x, float): return PyFloat_FromDouble(x) if isinstance(x, r_uint): return PyLong_FromUnsignedLong(x) @@ -189,6 +189,12 @@ def newint(self, intval): return PyInt_FromLong(intval) + def newlong(self, intval): + return PyLong_FromLong(intval) + + def newfloat(self, floatval): + return PyFloat_FromDouble(floatval) + def newdict(self): return PyDict_New() Modified: pypy/dist/pypy/objspace/cpy/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/test/test_objspace.py Thu Sep 21 00:12:25 2006 @@ -134,3 +134,16 @@ space = CPyObjSpace() assert space.is_true(space.callable(space.w_int)) assert not space.is_true(space.callable(space.w_Ellipsis)) + +def test_newfloat(): + space = CPyObjSpace() + fl1 = space.wrap(1.4) + fl2 = space.newfloat(1.4) + assert space.is_true(space.eq(fl1, fl2)) + +def test_newlong(): + space = CPyObjSpace() + i1 = space.newlong(42) + i2 = space.newint(42) + assert space.is_true(space.eq(i1, i2)) + assert space.is_true(space.ne(space.type(i1), space.type(i2))) From cfbolz at codespeak.net Thu Sep 21 00:14:10 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 21 Sep 2006 00:14:10 +0200 (CEST) Subject: [pypy-svn] r32547 - pypy/dist/pypy/module/_random Message-ID: <20060920221410.0FD3810074@code0.codespeak.net> Author: cfbolz Date: Thu Sep 21 00:14:04 2006 New Revision: 32547 Modified: pypy/dist/pypy/module/_random/interp_random.py Log: some translatability fixes, now _random translated with compilemodule Modified: pypy/dist/pypy/module/_random/interp_random.py ============================================================================== --- pypy/dist/pypy/module/_random/interp_random.py (original) +++ pypy/dist/pypy/module/_random/interp_random.py Thu Sep 21 00:14:04 2006 @@ -2,13 +2,14 @@ from pypy.interpreter.typedef import TypeDef from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app from pypy.interpreter.baseobjspace import Wrappable -from pypy.rpython.rarithmetic import r_uint +from pypy.rpython.rarithmetic import r_uint, intmask from pypy.module._random import rpy_random import time def descr_new__(space, w_subtype, w_anything=None): x = space.allocate_instance(W_Random, w_subtype) + x = space.interp_w(W_Random, x) W_Random.__init__(x, space, w_anything) return space.wrap(x) @@ -34,9 +35,9 @@ # XXX not perfectly like CPython w_n = space.abs(space.hash(w_n)) key = [] - w_one = space.newlong(1) - w_two = space.newlong(2) - w_thirtytwo = space.newlong(32) + w_one = space.newint(1) + w_two = space.newint(2) + w_thirtytwo = space.newint(32) # 0xffffffff w_masklower = space.sub(space.pow(w_two, w_thirtytwo, space.w_None), w_one) @@ -53,7 +54,7 @@ def getstate(self, space): state = [None] * (rpy_random.N + 1) for i in range(rpy_random.N): - state[i] = space.newlong(int(self._rnd.state[i])) + state[i] = space.newint(intmask(self._rnd.state[i])) state[rpy_random.N] = space.newint(self._rnd.index) return space.newtuple(state) getstate.unwrap_spec = ['self', ObjSpace] @@ -99,12 +100,12 @@ k -= 32 # XXX so far this is quadratic - w_result = space.newlong(0) - w_eight = space.newlong(8) + w_result = space.newint(0) + w_eight = space.newint(8) for i in range(len(bytesarray) - 1, -1, -1): byte = bytesarray[i] w_result = space.or_(space.lshift(w_result, w_eight), - space.newlong(int(byte))) + space.newint(intmask(byte))) return w_result getrandbits.unwrap_spec = ['self', ObjSpace, int] From pedronis at codespeak.net Thu Sep 21 00:32:00 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Sep 2006 00:32:00 +0200 (CEST) Subject: [pypy-svn] r32549 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20060920223200.5CFC010074@code0.codespeak.net> Author: pedronis Date: Thu Sep 21 00:31:57 2006 New Revision: 32549 Modified: pypy/dist/pypy/translator/backendopt/support.py pypy/dist/pypy/translator/backendopt/test/test_support.py Log: issue258 testing fixed compute_reachability. with a simple test. didn't seem to make any difference (size/speed/breakage) on a whole PyPy translation (?) Modified: pypy/dist/pypy/translator/backendopt/support.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/support.py (original) +++ pypy/dist/pypy/translator/backendopt/support.py Thu Sep 21 00:31:57 2006 @@ -146,17 +146,20 @@ def compute_reachability(graph): reachable = {} - for block in graph.iterblocks(): + blocks = list(graph.iterblocks()) + for block in reversed(blocks): # this order should make the reuse path more likely reach = {} scheduled = [block] while scheduled: current = scheduled.pop() for link in current.exits: if link.target in reachable: + reach[link.target] = True reach = setunion(reach, reachable[link.target]) continue if link.target not in reach: reach[link.target] = True + scheduled.append(link.target) reachable[block] = reach return reachable Modified: pypy/dist/pypy/translator/backendopt/test/test_support.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_support.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_support.py Thu Sep 21 00:31:57 2006 @@ -2,7 +2,7 @@ from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.support import \ needs_conservative_livevar_calculation, split_block_with_keepalive, \ - find_loop_blocks, find_backedges + find_loop_blocks, find_backedges, compute_reachability from pypy.rpython.rtyper import LowLevelOpList from pypy.rpython.lltypesystem import lltype @@ -90,6 +90,27 @@ assert 'keepalive' in [op.opname for op in link.target.operations] #__________________________________________________________ +# test compute_reachability + +def test_simple_compute_reachability(): + def f(x): + if x < 0: + if x == -1: + return x+1 + else: + return x+2 + else: + if x == 1: + return x-1 + else: + return x-2 + t = TranslationContext() + g = t.buildflowgraph(f) + reach = compute_reachability(g) + assert len(reach[g.startblock]) == 7 + assert len(reach[g.startblock.exits[0].target]) == 3 + assert len(reach[g.startblock.exits[1].target]) == 3 +#__________________________________________________________ # test loop detection def test_find_backedges(): From arigo at codespeak.net Thu Sep 21 11:00:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 11:00:17 +0200 (CEST) Subject: [pypy-svn] r32553 - pypy/dist/pypy/translator/goal Message-ID: <20060921090017.6FE9510080@code0.codespeak.net> Author: arigo Date: Thu Sep 21 11:00:11 2006 New Revision: 32553 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: sys.argv == [''] when running pypy-c with no argument at all. Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Thu Sep 21 11:00:11 2006 @@ -210,6 +210,7 @@ sys.path.insert(0, scriptdir) run_toplevel(execfile, sys.argv[0], mainmodule.__dict__) else: + sys.argv.append('') go_interactive = True if go_interactive: print >> sys.stderr, "debug: importing code" From cfbolz at codespeak.net Thu Sep 21 11:09:15 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 21 Sep 2006 11:09:15 +0200 (CEST) Subject: [pypy-svn] r32554 - in pypy/dist/pypy: config lib Message-ID: <20060921090915.DA5FB10081@code0.codespeak.net> Author: cfbolz Date: Thu Sep 21 11:09:08 2006 New Revision: 32554 Removed: pypy/dist/pypy/lib/random.py Modified: pypy/dist/pypy/config/pypyoption.py Log: remove app-level random.py and use _random by default. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Thu Sep 21 11:09:08 2006 @@ -9,7 +9,7 @@ default_modules = dict.fromkeys( ["unicodedata", "_codecs", "gc", "_weakref", "array", "marshal", "errno", "math", "_sre", "_pickle_support", "sys", "exceptions", "__builtins__", - "recparser", "symbol"]) + "recparser", "symbol", "_random"]) pypy_optiondescription = OptionDescription("pypy", [ OptionDescription("objspace", [ From arigo at codespeak.net Thu Sep 21 11:09:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 11:09:55 +0200 (CEST) Subject: [pypy-svn] r32555 - pypy/dist/pypy/translator/goal Message-ID: <20060921090955.03EE610081@code0.codespeak.net> Author: arigo Date: Thu Sep 21 11:09:53 2006 New Revision: 32555 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: Read the PYTHONINSPECT environment variable, like CPython does. Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Thu Sep 21 11:09:53 2006 @@ -212,7 +212,7 @@ else: sys.argv.append('') go_interactive = True - if go_interactive: + if go_interactive or os.environ.get('PYTHONINSPECT'): print >> sys.stderr, "debug: importing code" import code print >> sys.stderr, "debug: calling code.interact()" From ac at codespeak.net Thu Sep 21 11:30:28 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 21 Sep 2006 11:30:28 +0200 (CEST) Subject: [pypy-svn] r32556 - in pypy/dist/pypy: jit/codegen/i386/test jit/hintannotator jit/timeshifter jit/timeshifter/test rpython translator translator/backendopt translator/backendopt/test Message-ID: <20060921093028.9F3F810070@code0.codespeak.net> Author: ac Date: Thu Sep 21 11:30:27 2006 New Revision: 32556 Added: pypy/dist/pypy/jit/timeshifter/transform.py - copied unchanged from r32555, pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py Removed: pypy/dist/pypy/jit/timeshifter/timeshift.py Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py pypy/dist/pypy/jit/hintannotator/annotator.py pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/timeshifter/oop.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/vlist.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/backendopt/ssa.py pypy/dist/pypy/translator/backendopt/test/test_ssa.py pypy/dist/pypy/translator/simplify.py Log: (arigo, arre) Merging from branch: svn merge -r 32480:32555 svn+ssh://codespeak.net/svn/pypy/branch/timeshift-refactoring . Refactoring timeshifting into a graph shape transform and a rtyping phase. Added a SSA_to_SSI helper to make graph transforming easier. (rev. 32501) Added support for yellow calls, i.e. calling a function with some red arguments but getting a green return. Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py Thu Sep 21 11:30:27 2006 @@ -15,7 +15,7 @@ SEPLINE = 'running residual graph...\n' def annotate_interface_functions(self): - annhelper = self.htshift.annhelper + annhelper = self.hrtyper.annhelper RGenOp = self.RGenOp SEPLINE = self.SEPLINE ml_generate_code = self.ml_generate_code Modified: pypy/dist/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/annotator.py Thu Sep 21 11:30:27 2006 @@ -20,9 +20,6 @@ flowgraph = desc.specialize(input_args_hs) return self.build_graph_types(flowgraph, input_args_hs) - def simplify(self): - pass - def consider_op_malloc(self, hs_TYPE): TYPE = hs_TYPE.const if getattr(self.policy, 'novirtualcontainer', False): Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Thu Sep 21 11:30:27 2006 @@ -65,6 +65,7 @@ self.descs = {} self.tsgraph_maximal_call_families = UnionFind(TsGraphCallFamily) self.annotator = hannotator + self.tsgraphsigs = {} # circular imports hack global hintmodel from pypy.jit.hintannotator import model as hintmodel @@ -109,7 +110,18 @@ return origin def compute_at_fixpoint(self): - pass + # compute and cache the green-ness of OriginFlags objects + # while we can do so (i.e. before the graphs are modified) + for origin in self.originflags.values(): + if origin.spaceop is not None: + origin.greenargs_cached = origin.greenargs() + # compute and cache the signature of the graphs before they are + # modified by further code + ha = self.annotator + for tsgraph in ha.translator.graphs: + sig_hs = ([ha.binding(v) for v in tsgraph.getargs()], + ha.binding(tsgraph.getreturnvar())) + self.tsgraphsigs[tsgraph] = sig_hs def immutableconstant(self, const): res = hintmodel.SomeLLAbstractConstant(const.concretetype, {}) Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Thu Sep 21 11:30:27 2006 @@ -32,6 +32,8 @@ fixed = False read_positions = None + greenargs_cached = None + is_call_result = False def __init__(self, bookkeeper=None, spaceop=None): self.bookkeeper = bookkeeper @@ -61,8 +63,10 @@ def greenargs(self, frame=None): annotator = self.bookkeeper.annotator if frame is None: + if self.greenargs_cached is not None: + return self.greenargs_cached frame = GreenHandlerFrame(annotator) - if self.spaceop.opname == 'direct_call': # ah haa + if self.is_call_result: return frame.greencallresult(self.spaceop) else: for v in self.spaceop.args: @@ -93,6 +97,8 @@ ## import pdb; pdb.set_trace() args_hs = [self.annotator.binding(v) for v in spaceop.args] hs_result = self.annotator.binding(spaceop.result) + if not isinstance(hs_result, SomeLLAbstractConstant): + return False # was generalized, e.g. to SomeLLAbstractVariable hs_f1 = args_hs.pop(0) fnobj = hs_f1.const._obj if (getattr(self.annotator.policy, 'oopspec', False) and @@ -229,6 +235,12 @@ else: return hs_v1 +def originalconcretetype(hs): + if isinstance(hs, annmodel.SomeImpossibleValue): + return lltype.Void + else: + return hs.concretetype + # ____________________________________________________________ # operations @@ -334,6 +346,7 @@ if isinstance(hs_res, SomeLLAbstractConstant): hs_res.myorigin = bookkeeper.myorigin() + hs_res.myorigin.is_call_result = True # we need to make sure that hs_res does not become temporarily less # general as a result of calling another specialized version of the Modified: pypy/dist/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/oop.py (original) +++ pypy/dist/pypy/jit/timeshifter/oop.py Thu Sep 21 11:30:27 2006 @@ -2,6 +2,7 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.jit.timeshifter.rcontainer import cachedtype from pypy.jit.timeshifter import rvalue, rtimeshift +from pypy.translator.c import exceptiontransform class Index: @@ -13,7 +14,6 @@ __metaclass__ = cachedtype def __init__(self, hrtyper, fnobj): - ts = hrtyper.timeshifter ll_func = fnobj._callable FUNCTYPE = lltype.typeOf(fnobj) nb_args = len(FUNCTYPE.ARGS) @@ -45,7 +45,7 @@ if FUNCTYPE.RESULT is lltype.Void: self.errorbox = None else: - error_value = ts.error_value(FUNCTYPE.RESULT) + error_value = exceptiontransform.error_value(FUNCTYPE.RESULT) self.errorbox = rvalue.redbox_from_prebuilt_value(RGenOp, error_value) self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT) @@ -64,8 +64,9 @@ # exception handling graph = fnobj.graph - self.can_raise = ts.etrafo.raise_analyzer.analyze_direct_call(graph) - self.fetch_global_excdata = ts.fetch_global_excdata + etrafo = hrtyper.etrafo + self.can_raise = etrafo.raise_analyzer.analyze_direct_call(graph) + self.fetch_global_excdata = hrtyper.fetch_global_excdata def residual_call(self, jitstate, argboxes): builder = jitstate.curbuilder Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Thu Sep 21 11:30:27 2006 @@ -1,6 +1,8 @@ import operator, weakref from pypy.rpython.lltypesystem import lltype, lloperation, llmemory +from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.timeshifter import rvalue +from pypy.rpython.unroll import unrolling_iterable FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops()) @@ -44,8 +46,8 @@ def make_opdesc(hop): hrtyper = hop.rtyper op_key = (hrtyper.RGenOp, hop.spaceop.opname, - tuple([hrtyper.originalconcretetype(s_arg) for s_arg in hop.args_s]), - hrtyper.originalconcretetype(hop.s_result)) + tuple([originalconcretetype(s_arg) for s_arg in hop.args_s]), + originalconcretetype(hop.s_result)) try: return _opdesc_cache[op_key] except KeyError: @@ -193,8 +195,7 @@ states_dic[key] = frozen, newblock start_new_block._annspecialcase_ = "specialize:arglltype(2)" -def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes): - save_locals(jitstate, redboxes) +def retrieve_jitstate_for_merge(states_dic, jitstate, key): if key not in states_dic: start_new_block(states_dic, jitstate, key) return False # continue @@ -228,38 +229,54 @@ jitstate.enter_block(incoming, memo) enter_next_block(jitstate, incoming) -def leave_block_split(jitstate, switchredbox, exitindex, - redboxes_true, redboxes_false): - if switchredbox.is_constant(): - return rvalue.ll_getvalue(switchredbox, lltype.Bool) - else: - exitgvar = switchredbox.getgenvar(jitstate.curbuilder) - later_builder = jitstate.curbuilder.jump_if_false(exitgvar) - save_locals(jitstate, redboxes_false) - jitstate.split(later_builder, exitindex) - save_locals(jitstate, redboxes_true) - enter_block(jitstate) - return True - -def dispatch_next(oldjitstate, return_cache): - split_queue = oldjitstate.frame.split_queue - if split_queue: - jitstate = split_queue.pop() +def split(jitstate, switchredbox, resumepoint, *greens_gv): + exitgvar = switchredbox.getgenvar(jitstate.curbuilder) + later_builder = jitstate.curbuilder.jump_if_false(exitgvar) + jitstate.split(later_builder, resumepoint, list(greens_gv)) + +def collect_split(jitstate_chain, resumepoint, *greens_gv): + greens_gv = list(greens_gv) + pending = jitstate_chain + while True: + jitstate = pending + pending = pending.next + jitstate.greens.extend(greens_gv) # item 0 is the return value + jitstate.resumepoint = resumepoint + if pending is None: + break + dispatch_queue = jitstate_chain.frame.dispatch_queue + jitstate.next = dispatch_queue.split_chain + dispatch_queue.split_chain = jitstate_chain.next + # XXX obscurity++ above + +def dispatch_next(oldjitstate): + dispatch_queue = oldjitstate.frame.dispatch_queue + if dispatch_queue.split_chain is not None: + jitstate = dispatch_queue.split_chain + dispatch_queue.split_chain = jitstate.next enter_block(jitstate) return jitstate else: - return leave_graph(oldjitstate.frame.return_queue, return_cache) + oldjitstate.resumepoint = -1 + return oldjitstate -def getexitindex(jitstate): - return jitstate.exitindex +def getresumepoint(jitstate): + return jitstate.resumepoint -def save_locals(jitstate, redboxes): +def save_locals(jitstate, *redboxes): + redboxes = list(redboxes) assert None not in redboxes jitstate.frame.local_boxes = redboxes +def save_greens(jitstate, *greens_gv): + jitstate.greens = list(greens_gv) + def getlocalbox(jitstate, i): return jitstate.frame.local_boxes[i] +def ll_getgreenbox(jitstate, i, T): + return jitstate.greens[i].revealconst(T) + def getreturnbox(jitstate): return jitstate.returnbox @@ -276,16 +293,35 @@ jitstate.exc_value_box = box def save_return(jitstate): - jitstate.frame.return_queue.append(jitstate) + # add 'jitstate' to the chain of return-jitstates + dispatch_queue = jitstate.frame.dispatch_queue + jitstate.next = dispatch_queue.return_chain + dispatch_queue.return_chain = jitstate -def ll_gvar_from_redbox(jitstate, redbox): - return redbox.getgenvar(jitstate.curbuilder) +##def ll_gvar_from_redbox(jitstate, redbox): +## return redbox.getgenvar(jitstate.curbuilder) -def ll_gvar_from_constant(jitstate, ll_value): - return jitstate.curbuilder.rgenop.genconst(ll_value) +##def ll_gvar_from_constant(jitstate, ll_value): +## return jitstate.curbuilder.rgenop.genconst(ll_value) # ____________________________________________________________ +class BaseDispatchQueue(object): + def __init__(self): + self.split_chain = None + self.return_chain = None + +def build_dispatch_subclass(attrnames): + if len(attrnames) == 0: + return BaseDispatchQueue + attrnames = unrolling_iterable(attrnames) + class DispatchQueue(BaseDispatchQueue): + def __init__(self): + BaseDispatchQueue.__init__(self) + for name in attrnames: + setattr(self, name, {}) # the new dicts have various types! + return DispatchQueue + class FrozenVirtualFrame(object): fz_backframe = None @@ -335,10 +371,9 @@ class VirtualFrame(object): - def __init__(self, backframe, split_queue, return_queue): + def __init__(self, backframe, dispatch_queue): self.backframe = backframe - self.split_queue = split_queue - self.return_queue = return_queue + self.dispatch_queue = dispatch_queue #self.local_boxes = ... set by callers def enter_block(self, incoming, memo): @@ -360,9 +395,7 @@ newbackframe = None else: newbackframe = self.backframe.copy(memo) - result = VirtualFrame(newbackframe, - self.split_queue, - self.return_queue) + result = VirtualFrame(newbackframe, self.dispatch_queue) result.local_boxes = [box.copy(memo) for box in self.local_boxes] return result @@ -376,23 +409,29 @@ class JITState(object): returnbox = None + next = None # for linked lists def __init__(self, builder, frame, exc_type_box, exc_value_box, - exitindex=-1): + resumepoint=-1, newgreens=[]): self.curbuilder = builder self.frame = frame self.exc_type_box = exc_type_box self.exc_value_box = exc_value_box - self.exitindex = exitindex + self.resumepoint = resumepoint + self.greens = newgreens - def split(self, newbuilder, newexitindex): + def split(self, newbuilder, newresumepoint, newgreens): memo = rvalue.copy_memo() later_jitstate = JITState(newbuilder, self.frame.copy(memo), self.exc_type_box .copy(memo), self.exc_value_box.copy(memo), - newexitindex) - self.frame.split_queue.append(later_jitstate) + newresumepoint, + newgreens) + # add the later_jitstate to the chain of pending-for-dispatch_next() + dispatch_queue = self.frame.dispatch_queue + later_jitstate.next = dispatch_queue.split_chain + dispatch_queue.split_chain = later_jitstate def enter_block(self, incoming, memo): self.frame.enter_block(incoming, memo) @@ -412,21 +451,50 @@ self.exc_value_box = self.exc_value_box.replace(memo) -def enter_graph(jitstate): - jitstate.frame = VirtualFrame(jitstate.frame, [], []) - -def leave_graph(return_queue, return_cache): - for jitstate in return_queue[:-1]: - res = retrieve_jitstate_for_merge(return_cache, jitstate, (), - # XXX strange next argument - jitstate.frame.local_boxes) +def enter_graph(jitstate, DispatchQueueClass): + jitstate.frame = VirtualFrame(jitstate.frame, DispatchQueueClass()) +enter_graph._annspecialcase_ = 'specialize:arg(1)' +# XXX is that too many specializations? ^^^ + +def merge_returning_jitstates(jitstate): + return_chain = jitstate.frame.dispatch_queue.return_chain + return_cache = {} + still_pending = None + while return_chain is not None: + jitstate = return_chain + return_chain = return_chain.next + res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + if res is False: # not finished + jitstate.next = still_pending + still_pending = jitstate + assert still_pending is not None + most_general_jitstate = still_pending + still_pending = still_pending.next + while still_pending is not None: + jitstate = still_pending + still_pending = still_pending.next + res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) assert res is True # finished - frozen, block = return_cache[()] - jitstate = return_queue[-1] + return most_general_jitstate + +def leave_graph_red(jitstate): + jitstate = merge_returning_jitstates(jitstate) myframe = jitstate.frame - if myframe.local_boxes: # else it's a green Void return - jitstate.returnbox = myframe.local_boxes[0] - # ^^^ fetched by a 'fetch_return' operation + jitstate.returnbox = myframe.local_boxes[0] + # ^^^ fetched by a 'fetch_return' operation jitstate.frame = myframe.backframe - jitstate.exitindex = -1 return jitstate + +def leave_graph_void(jitstate): + jitstate = merge_returning_jitstates(jitstate) + myframe = jitstate.frame + jitstate.frame = myframe.backframe + return jitstate + +def leave_graph_yellow(jitstate): + return_chain = jitstate.frame.dispatch_queue.return_chain + jitstate = return_chain + while jitstate is not None: + jitstate.frame = jitstate.frame.backframe + jitstate = jitstate.next + return return_chain # a jitstate, which is the head of the chain Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 21 11:30:27 2006 @@ -10,7 +10,10 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.hintannotator import model as hintmodel from pypy.jit.hintannotator import container as hintcontainer -from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer +from pypy.jit.hintannotator.model import originalconcretetype +from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, oop +from pypy.jit.timeshifter.transform import HintGraphTransformer +from pypy.jit.codegen import model as cgmodel class HintTypeSystem(LowLevelTypeSystem): name = "hinttypesystem" @@ -36,27 +39,156 @@ # ___________________________________________________________ -def originalconcretetype(hs): - if isinstance(hs, annmodel.SomeImpossibleValue): - return lltype.Void - else: - return hs.concretetype - class HintRTyper(RPythonTyper): - def __init__(self, hannotator, timeshifter): + def __init__(self, hannotator, rtyper, RGenOp): RPythonTyper.__init__(self, hannotator, type_system=HintTypeSystem.instance) + self.rtyper = rtyper + self.RGenOp = RGenOp self.green_reprs = PRECOMPUTED_GREEN_REPRS.copy() self.red_reprs = {} - self.color_cache = {} - self.timeshifter = timeshifter - self.RGenOp = timeshifter.RGenOp + #self.color_cache = {} + + self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper) + self.timeshift_mapping = {} + self.sigs = {} + self.dispatchsubclasses = {} + + (self.s_CodeGenerator, + self.r_CodeGenerator) = self.s_r_instanceof(cgmodel.CodeGenerator) + (self.s_JITState, + self.r_JITState) = self.s_r_instanceof(rtimeshift.JITState) + (self.s_RedBox, + self.r_RedBox) = self.s_r_instanceof(rvalue.RedBox) + (self.s_OopSpecDesc, + self.r_OopSpecDesc) = self.s_r_instanceof(oop.OopSpecDesc) + (self.s_ConstOrVar, + self.r_ConstOrVar) = self.s_r_instanceof(cgmodel.GenVarOrConst) + (self.s_Block, + self.r_Block) = self.s_r_instanceof(cgmodel.CodeGenBlock) + + self.etrafo = hannotator.exceptiontransformer + self.cexcdata = self.etrafo.cexcdata + self.exc_data_ptr = self.cexcdata.value + gv_excdata = RGenOp.constPrebuiltGlobal(self.exc_data_ptr) + LL_EXC_TYPE = rtyper.exceptiondata.lltype_of_exception_type + LL_EXC_VALUE = rtyper.exceptiondata.lltype_of_exception_value + null_exc_type_box = rvalue.redbox_from_prebuilt_value(RGenOp, + lltype.nullptr(LL_EXC_TYPE.TO)) + null_exc_value_box = rvalue.redbox_from_prebuilt_value(RGenOp, + lltype.nullptr(LL_EXC_VALUE.TO)) + + p = self.etrafo.rpyexc_fetch_type_ptr.value + gv_rpyexc_fetch_type = RGenOp.constPrebuiltGlobal(p) + tok_fetch_type = RGenOp.sigToken(lltype.typeOf(p).TO) + kind_etype = RGenOp.kindToken(LL_EXC_TYPE) + + p = self.etrafo.rpyexc_fetch_value_ptr.value + gv_rpyexc_fetch_value = RGenOp.constPrebuiltGlobal(p) + tok_fetch_value = RGenOp.sigToken(lltype.typeOf(p).TO) + kind_evalue = RGenOp.kindToken(LL_EXC_VALUE) + + p = self.etrafo.rpyexc_clear_ptr.value + gv_rpyexc_clear = RGenOp.constPrebuiltGlobal(p) + tok_clear = RGenOp.sigToken(lltype.typeOf(p).TO) + + p = self.etrafo.rpyexc_raise_ptr.value + gv_rpyexc_raise = RGenOp.constPrebuiltGlobal(p) + tok_raise = RGenOp.sigToken(lltype.typeOf(p).TO) + + def fetch_global_excdata(jitstate): + builder = jitstate.curbuilder + gv_etype = builder.genop_call(tok_fetch_type, + gv_rpyexc_fetch_type, []) + gv_evalue = builder.genop_call(tok_fetch_value, + gv_rpyexc_fetch_value, []) + builder.genop_call(tok_clear, gv_rpyexc_clear, []) + etypebox = rvalue.PtrRedBox(kind_etype, gv_etype) + evaluebox = rvalue.PtrRedBox(kind_evalue, gv_evalue) + rtimeshift.setexctypebox (jitstate, etypebox) + rtimeshift.setexcvaluebox(jitstate, evaluebox) + self.fetch_global_excdata = fetch_global_excdata + + def store_global_excdata(jitstate): + builder = jitstate.curbuilder + etypebox = jitstate.exc_type_box + if etypebox.is_constant(): + ll_etype = rvalue.ll_getvalue(etypebox, llmemory.Address) + if not ll_etype: + return # we known there is no exception set + evaluebox = jitstate.exc_value_box + gv_etype = etypebox .getgenvar(builder) + gv_evalue = evaluebox.getgenvar(builder) + builder.genop_call(tok_raise, + gv_rpyexc_raise, [gv_etype, gv_evalue]) + self.store_global_excdata = store_global_excdata + + def ll_fresh_jitstate(builder): + return rtimeshift.JITState(builder, None, + null_exc_type_box, + null_exc_value_box) + self.ll_fresh_jitstate = ll_fresh_jitstate + + def ll_finish_jitstate(jitstate, graphsigtoken): + returnbox = rtimeshift.getreturnbox(jitstate) + gv_ret = returnbox.getgenvar(jitstate.curbuilder) + store_global_excdata(jitstate) + jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret) + self.ll_finish_jitstate = ll_finish_jitstate + + def specialize(self, view=False): + """ + Driver for running the timeshifter. + """ + graphs = self.annotator.translator.graphs + if view: + for graph in graphs: + self.transform_graph(graph) + self.annotator.translator.view() # in the middle + for graph in graphs: + self.timeshift_graph(graph) - originalconcretetype = staticmethod(originalconcretetype) + else: + # do the whole transformation graph-by-graph if there is no + # need to view the intermediate result + for graph in graphs: + self.transform_graph(graph) + self.timeshift_graph(graph) + + def transform_graph(self, graph): + # prepare the graphs by inserting all bookkeeping/dispatching logic + # as special operations + assert graph.startblock in self.annotator.annotated + transformer = HintGraphTransformer(self.annotator, graph) + transformer.transform() + flowmodel.checkgraph(graph) # for now + + def timeshift_graph(self, graph): + # specialize all blocks of this graph + for block in graph.iterblocks(): + self.annotator.annotated[block] = graph + self.specialize_block(block) + # "normalize" the graphs by putting an explicit v_jitstate variable + # everywhere + self.insert_v_jitstate_everywhere(graph) + # the graph is now timeshifted, so it is *itself* no longer + # exception-transformed... + del graph.exceptiontransformed + + # ____________________________________________________________ + + def s_r_instanceof(self, cls, can_be_None=True): + # Return a SomeInstance / InstanceRepr pair correspnding to the specified class. + return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None) + + def get_sig_hs(self, tsgraph): + # the signature annotations are cached on the HintBookkeeper because + # the graph is transformed already + return self.annotator.bookkeeper.tsgraphsigs[tsgraph] def make_new_lloplist(self, block): - return HintLowLevelOpList(self.timeshifter) + return HintLowLevelOpList(self) def getgreenrepr(self, lowleveltype): try: @@ -75,20 +207,65 @@ if isinstance(lowleveltype, lltype.Ptr): if isinstance(lowleveltype.TO, lltype.Struct): redreprcls = RedStructRepr - r = redreprcls(lowleveltype, self.timeshifter) + r = redreprcls(lowleveltype, self) self.red_reprs[lowleveltype] = r return r - def gethscolor(self, hs): +## def gethscolor(self, hs): +## try: +## return self.color_cache[id(hs)] +## except KeyError: +## if hs.is_green(): +## color = "green" +## else: +## color = "red" +## self.color_cache[id(hs)] = color +## return color + + def get_dispatch_subclass(self, mergepointfamily): try: - return self.color_cache[id(hs)] + return self.dispatchsubclasses[mergepointfamily] except KeyError: - if hs.is_green(): - color = "green" - else: - color = "red" - self.color_cache[id(hs)] = color - return color + attrnames = mergepointfamily.getattrnames() + subclass = rtimeshift.build_dispatch_subclass(attrnames) + self.dispatchsubclasses[mergepointfamily] = subclass + return subclass + + def get_timeshifted_fnptr(self, graph, specialization_key): + bk = self.annotator.bookkeeper + tsgraph = bk.get_graph_by_key(graph, specialization_key) + args_hs, hs_res = self.get_sig_hs(tsgraph) + args_r = [self.getrepr(hs_arg) for hs_arg in args_hs] + ARGS = [self.r_JITState.lowleveltype] + ARGS += [r.lowleveltype for r in args_r] + RESULT = self.r_JITState.lowleveltype + fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), + tsgraph.name, + graph=tsgraph, + _callable = graph.func) + return fnptr, args_r + + def insert_v_jitstate_everywhere(self, graph): + from pypy.translator.unsimplify import varoftype + for block in graph.iterblocks(): + v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate') + if block is graph.returnblock: + assert block.inputargs[0].concretetype is lltype.Void + del block.inputargs[0] + block.inputargs = [v_jitstate] + block.inputargs + for op in block.operations: + if op.opname == 'getjitstate': + op.opname = 'same_as' + op.args = [v_jitstate] + elif op.opname == 'setjitstate': + [v_jitstate] = op.args + for i in range(len(block.operations)-1, -1, -1): + if block.operations[i].opname == 'setjitstate': + del block.operations[i] + for link in block.exits: + if link.target is graph.returnblock: + del link.args[0] # Void + link.args = [v_jitstate] + link.args def generic_translate_operation(self, hop, force=False): # detect constant-foldable all-green operations @@ -114,7 +291,7 @@ ll_generate = rtimeshift.ll_gen1 elif opdesc.nb_args == 2: ll_generate = rtimeshift.ll_gen2 - ts = self.timeshifter + ts = self c_opdesc = inputconst(lltype.Void, opdesc) s_opdesc = ts.rtyper.annotator.bookkeeper.immutablevalue(opdesc) v_jitstate = hop.llops.getjitstate() @@ -133,7 +310,7 @@ T = originalconcretetype(hop.args_s[0]) v_redbox = hop.inputarg(self.getredrepr(T), arg=0) assert isinstance(hop.r_result, GreenRepr) - ts = self.timeshifter + ts = self c_T = hop.inputconst(lltype.Void, T) s_T = ts.rtyper.annotator.bookkeeper.immutablevalue(T) s_res = annmodel.lltype_to_annotation(T) @@ -157,7 +334,7 @@ def translate_op_getfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_getfield(hop) - ts = self.timeshifter + ts = self if hop.args_v[0] == ts.cexcdata: # reading one of the exception boxes (exc_type or exc_value) fieldname = hop.args_v[1].value @@ -198,7 +375,7 @@ if res is not None: return res - ts = self.timeshifter + ts = self v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed)) fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) @@ -217,7 +394,7 @@ return res PTRTYPE = originalconcretetype(hop.args_s[0]) - ts = self.timeshifter + ts = self [v_argbox] = hop.inputargs(self.getredrepr(PTRTYPE)) fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO) @@ -234,7 +411,7 @@ def translate_op_setfield(self, hop): if isinstance(hop.args_r[0], BlueRepr): return hop.args_r[0].timeshift_setfield(hop) - ts = self.timeshifter + ts = self PTRTYPE = originalconcretetype(hop.args_s[0]) VALUETYPE = originalconcretetype(hop.args_s[2]) if hop.args_v[0] == ts.cexcdata: @@ -271,7 +448,7 @@ def translate_op_setarrayitem(self, hop): PTRTYPE = originalconcretetype(hop.args_s[0]) VALUETYPE = PTRTYPE.TO.OF - ts = self.timeshifter + ts = self v_argbox, v_index, v_valuebox= hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed), self.getredrepr(VALUETYPE)) @@ -287,7 +464,7 @@ def translate_op_getsubstruct(self, hop): ##if isinstance(hop.args_r[0], BlueRepr): ## return hop.args_r[0].timeshift_getsubstruct(hop) - ts = self.timeshifter + ts = self PTRTYPE = originalconcretetype(hop.args_s[0]) v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE), green_void_repr) @@ -311,7 +488,7 @@ return r_result.create(hop) def translate_op_malloc_varsize(self, hop): - ts = self.timeshifter + ts = self assert isinstance(hop.r_result, RedRepr) PTRTYPE = originalconcretetype(hop.s_result) TYPE = PTRTYPE.TO @@ -329,7 +506,7 @@ def translate_op_ptr_nonzero(self, hop, reverse=False): - ts = self.timeshifter + ts = self PTRTYPE = originalconcretetype(hop.args_s[0]) v_argbox, = hop.inputargs(self.getredrepr(PTRTYPE)) v_jitstate = hop.llops.getjitstate() @@ -343,35 +520,10 @@ return self.translate_op_ptr_nonzero(hop, reverse=True) - def guess_call_kind(self, spaceop): - if spaceop.opname == 'indirect_call': - return 'red' # for now - assert spaceop.opname == 'direct_call' - c_func = spaceop.args[0] - fnobj = c_func.value._obj - s_result = self.annotator.binding(spaceop.result) - r_result = self.getrepr(s_result) - if hasattr(fnobj._callable, 'oopspec'): - return 'oopspec' - elif (originalconcretetype(s_result) is not lltype.Void and - isinstance(r_result, GreenRepr)): - for v in spaceop.args: - s_arg = self.annotator.binding(v) - r_arg = self.getrepr(s_arg) - if not isinstance(r_arg, GreenRepr): - return 'yellow' - return 'green' - else: - return 'red' - - def translate_op_direct_call(self, hop): - kind = self.guess_call_kind(hop.spaceop) - meth = getattr(self, 'handle_%s_call' % (kind,)) - return meth(hop) - def translate_op_indirect_call(self, hop): + XXX bk = self.annotator.bookkeeper - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() v_funcbox = hop.args_v[0] graph_list = hop.args_v[-1].value @@ -396,32 +548,221 @@ v_newjitstate = hop.genop('indirect_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) + # special operations inserted by the HintGraphTransformer + + def translate_op_enter_graph(self, hop): + mpfamily = hop.args_v[0].value + subclass = self.get_dispatch_subclass(mpfamily) + s_subclass = self.rtyper.annotator.bookkeeper.immutablevalue(subclass) + c_subclass = inputconst(lltype.Void, subclass) + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(rtimeshift.enter_graph, + [self.s_JITState, s_subclass], + [v_jitstate , c_subclass], + annmodel.s_None) + + def translate_op_leave_graph_red(self, hop): + v_jitstate = hop.llops.getjitstate() + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_red, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_newjs) + + def translate_op_leave_graph_void(self, hop): + v_jitstate = hop.llops.getjitstate() + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_void, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_newjs) + + def translate_op_leave_graph_yellow(self, hop): + v_jitstate = hop.llops.getjitstate() + v_njs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_njs) def translate_op_save_locals(self, hop): - ts = self.timeshifter v_jitstate = hop.llops.getjitstate() - v_boxes = ts.build_box_list(hop.llops, hop.args_v) + boxes_r = [self.getredrepr(originalconcretetype(hs)) + for hs in hop.args_s] + boxes_v = hop.inputargs(*boxes_r) + boxes_s = [self.s_RedBox] * len(hop.args_v) hop.llops.genmixlevelhelpercall(rtimeshift.save_locals, - [ts.s_JITState, ts.s_box_list], - [v_jitstate, v_boxes], + [self.s_JITState] + boxes_s, + [v_jitstate ] + boxes_v, + annmodel.s_None) + + def translate_op_save_greens(self, hop): + v_jitstate = hop.llops.getjitstate() + greens_v = list(self.wrap_green_vars(hop.llops, hop.args_v)) + greens_s = [self.s_ConstOrVar] * len(greens_v) + return hop.llops.genmixlevelhelpercall(rtimeshift.save_greens, + [self.s_JITState] + greens_s, + [v_jitstate ] + greens_v, + annmodel.s_None) + + def translate_op_enter_block(self, hop): + v_jitstate = hop.llops.getjitstate() + hop.llops.genmixlevelhelpercall(rtimeshift.enter_block, + [self.s_JITState], + [v_jitstate ], annmodel.s_None) def translate_op_restore_local(self, hop): - ts = self.timeshifter assert isinstance(hop.args_v[0], flowmodel.Constant) index = hop.args_v[0].value + c_index = hop.inputconst(lltype.Signed, index) v_jitstate = hop.llops.getjitstate() - return ts.read_out_box(hop.llops, v_jitstate, index) + return hop.llops.genmixlevelhelpercall(rtimeshift.getlocalbox, + [self.s_JITState, annmodel.SomeInteger(nonneg=True)], + [v_jitstate , c_index ], + self.s_RedBox) + + def translate_op_restore_green(self, hop): + assert isinstance(hop.args_v[0], flowmodel.Constant) + index = hop.args_v[0].value + c_index = hop.inputconst(lltype.Signed, index) + TYPE = originalconcretetype(hop.s_result) + s_TYPE = self.rtyper.annotator.bookkeeper.immutablevalue(TYPE) + c_TYPE = hop.inputconst(lltype.Void, TYPE) + s_result = annmodel.lltype_to_annotation(TYPE) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_getgreenbox, + [self.s_JITState, annmodel.SomeInteger(nonneg=True), s_TYPE], + [v_jitstate , c_index , c_TYPE], + s_result) def translate_op_fetch_return(self, hop): - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.getreturnbox, [ts.s_JITState], [v_jitstate ], ts.s_RedBox) - def handle_oopspec_call(self, hop): + def translate_op_is_constant(self, hop): + hs = hop.args_s[0] + r_arg = self.getredrepr(originalconcretetype(hs)) + [v_arg] = hop.inputargs(r_arg) + return hop.llops.genmixlevelhelpercall(rvalue.ll_is_constant, + [self.s_RedBox], + [v_arg ], + annmodel.SomeBool()) + + def translate_op_revealconst(self, hop): + hs = hop.args_s[0] + TYPE = originalconcretetype(hs) + r_arg = self.getredrepr(TYPE) + [v_arg] = hop.inputargs(r_arg) + s_TYPE = self.rtyper.annotator.bookkeeper.immutablevalue(TYPE) + c_TYPE = hop.inputconst(lltype.Void, TYPE) + s_result = annmodel.lltype_to_annotation(TYPE) + return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue, + [self.s_RedBox, s_TYPE], + [v_arg , c_TYPE], + s_result) + + def wrap_green_vars(self, llops, vars): + v_jitstate = llops.getjitstate() + for var in vars: + s_var = annmodel.lltype_to_annotation(var.concretetype) + yield llops.genmixlevelhelpercall(rvalue.ll_gv_fromvalue, + [self.s_JITState, s_var], + [v_jitstate, var ], + self.s_ConstOrVar) + + def translate_op_split(self, hop): + r_switch = self.getredrepr(lltype.Bool) + GREENS = [v.concretetype for v in hop.args_v[2:]] + greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS] + vlist = hop.inputargs(r_switch, lltype.Signed, *greens_r) + + v_jitstate = hop.llops.getjitstate() + v_switch = vlist[0] + c_resumepoint = vlist[1] + greens_v = list(self.wrap_green_vars(hop.llops, vlist[2:])) + + s_Int = annmodel.SomeInteger(nonneg=True) + args_s = [self.s_JITState, self.s_RedBox, s_Int] + args_s += [self.s_ConstOrVar] * len(greens_v) + args_v = [v_jitstate, v_switch, c_resumepoint] + args_v += greens_v + hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v, + annmodel.s_None) + + def translate_op_collect_split(self, hop): + GREENS = [v.concretetype for v in hop.args_v[1:]] + greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS] + vlist = hop.inputargs(lltype.Signed, *greens_r) + + v_jitstate = hop.llops.getjitstate() + c_resumepoint = vlist[0] + greens_v = list(self.wrap_green_vars(hop.llops, vlist[1:])) + + s_Int = annmodel.SomeInteger(nonneg=True) + args_s = [self.s_JITState, s_Int] + args_s += [self.s_ConstOrVar] * len(greens_v) + args_v = [v_jitstate, c_resumepoint] + args_v += greens_v + hop.llops.genmixlevelhelpercall(rtimeshift.collect_split, + args_s, args_v, + annmodel.s_None) + + def translate_op_merge_point(self, hop): + mpfamily = hop.args_v[0].value + attrname = hop.args_v[1].value + DispatchQueueSubclass = self.get_dispatch_subclass(mpfamily) + + def merge_point(jitstate, *key): + dispatch_queue = jitstate.frame.dispatch_queue + assert isinstance(dispatch_queue, DispatchQueueSubclass) + states_dic = getattr(dispatch_queue, attrname) + return rtimeshift.retrieve_jitstate_for_merge(states_dic, + jitstate, key) + + greens_v = [] + greens_s = [] + for r, v in zip(hop.args_r[2:], hop.args_v[2:]): + s_precise_type = r.annotation() + s_erased_type = r.erased_annotation() + r_precise_type = self.rtyper.getrepr(s_precise_type) + r_erased_type = self.rtyper.getrepr(s_erased_type) + greens_v.append(hop.llops.convertvar(v, r_precise_type, + r_erased_type)) + greens_s.append(s_erased_type) + + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(merge_point, + [self.s_JITState] + greens_s, + [v_jitstate ] + greens_v, + annmodel.SomeBool()) + + def translate_op_save_return(self, hop): + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.save_return, + [self.s_JITState], + [v_jitstate ], + annmodel.s_None) + + def translate_op_dispatch_next(self, hop): + v_jitstate = hop.llops.getjitstate() + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.dispatch_next, + [self.s_JITState], + [v_jitstate ], + self.s_JITState) + hop.llops.setjitstate(v_newjs) + return hop.llops.genmixlevelhelpercall(rtimeshift.getresumepoint, + [self.s_JITState], + [v_newjs ], + annmodel.SomeInteger()) + + # handling of the various kinds of calls + + def translate_op_oopspec_call(self, hop): # special-cased call, for things like list methods from pypy.jit.timeshifter.oop import OopSpecDesc, Index @@ -442,7 +783,7 @@ # if the ll_handler() takes more arguments, it must be 'None' defaults. # Pass them as constant Nones. - ts = self.timeshifter + ts = self ll_handler = oopspecdesc.ll_handler missing_args = ((ll_handler.func_code.co_argcount - 2) - len(oopspecdesc.argtuple)) @@ -470,17 +811,15 @@ [v_jitstate, c_oopspecdesc] + args_v, s_result) - def handle_green_call(self, hop): - # green-returning call, for now (XXX) we assume it's an - # all-green function that we can just call + def translate_op_green_call(self, hop): for r_arg in hop.args_r: assert isinstance(r_arg, GreenRepr) v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype) return v - def handle_red_call(self, hop): + def translate_op_red_call(self, hop): bk = self.annotator.bookkeeper - ts = self.timeshifter + ts = self v_jitstate = hop.llops.getjitstate() c_func = hop.args_v[0] fnobj = c_func.value._obj @@ -496,14 +835,16 @@ v_newjitstate = hop.genop('direct_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) + translate_op_yellow_call = translate_op_red_call + class HintLowLevelOpList(LowLevelOpList): """Warning: the HintLowLevelOpList's rtyper is the *original* rtyper, while the HighLevelOp's rtyper is actually our HintRTyper... """ - def __init__(self, timeshifter): - LowLevelOpList.__init__(self, timeshifter.rtyper) - self.timeshifter = timeshifter + def __init__(self, hrtyper): + LowLevelOpList.__init__(self, hrtyper.rtyper) + self.hrtyper = hrtyper def hasparentgraph(self): return False # for now @@ -524,23 +865,22 @@ args_v = [v_self] + args_v function = function.im_func - graph = self.timeshifter.annhelper.getgraph(function, args_s, s_result) + graph = self.hrtyper.annhelper.getgraph(function, args_s, s_result) self.record_extra_call(graph) # xxx - c = self.timeshifter.annhelper.graph2const(graph) + c = self.hrtyper.annhelper.graph2const(graph) # build the 'direct_call' operation - rtyper = self.timeshifter.rtyper try: RESULT = annmodel.annotation_to_lltype(s_result) except ValueError: - RESULT = rtyper.getrepr(s_result).lowleveltype + RESULT = self.rtyper.getrepr(s_result).lowleveltype return self.genop('direct_call', [c]+args_v, resulttype = RESULT) def getjitstate(self): return self.genop('getjitstate', [], - resulttype = self.timeshifter.r_JITState) + resulttype = self.hrtyper.r_JITState) def setjitstate(self, v_newjitstate): self.genop('setjitstate', [v_newjitstate]) @@ -550,14 +890,14 @@ class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractValue)): def rtyper_makerepr((ts, hs_c), hrtyper): - if hrtyper.gethscolor(hs_c) == 'green': + if hs_c.is_green(): return hrtyper.getgreenrepr(hs_c.concretetype) else: return hrtyper.getredrepr(hs_c.concretetype) def rtyper_makekey((ts, hs_c), hrtyper): - color = hrtyper.gethscolor(hs_c) - return hs_c.__class__, color, hs_c.concretetype + is_green = hs_c.is_green() + return hs_c.__class__, is_green, hs_c.concretetype class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractContainer)): @@ -568,7 +908,7 @@ # fall back to a red repr return hrtyper.getredrepr(hs_container.concretetype) return BlueStructRepr(hs_container.concretetype, vstructdef, - hrtyper.timeshifter) + hrtyper) def rtyper_makekey((ts, hs_container), hrtyper): vstructdef = hs_container.contentdef @@ -597,26 +937,26 @@ return hs_c.__class__, class RedRepr(Repr): - def __init__(self, original_concretetype, timeshifter): + def __init__(self, original_concretetype, hrtyper): assert original_concretetype is not lltype.Void, ( "cannot make red boxes for the lltype Void") self.original_concretetype = original_concretetype - self.lowleveltype = timeshifter.r_RedBox.lowleveltype - self.timeshifter = timeshifter + self.lowleveltype = hrtyper.r_RedBox.lowleveltype + self.hrtyper = hrtyper - def get_genop_var(self, v, llops): - ts = self.timeshifter - v_jitstate = hop.llops.getjitstate() - return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox, - [ts.s_JITState, llops.timeshifter.s_RedBox], - [v_jitstate, v], - ts.s_ConstOrVar) +## def get_genop_var(self, v, llops): +## ts = self.hrtyper +## v_jitstate = hop.llops.getjitstate() +## return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox, +## [ts.s_JITState, llops.hrtyper.s_RedBox], +## [v_jitstate, v], +## ts.s_ConstOrVar) def convert_const(self, ll_value): - RGenOp = self.timeshifter.RGenOp + RGenOp = self.hrtyper.RGenOp redbox = rvalue.redbox_from_prebuilt_value(RGenOp, ll_value) - timeshifter = self.timeshifter - return timeshifter.annhelper.delayedconst(timeshifter.r_RedBox, redbox) + hrtyper = self.hrtyper + return hrtyper.annhelper.delayedconst(hrtyper.r_RedBox, redbox) def residual_values(self, ll_value): return [ll_value] @@ -626,7 +966,7 @@ typedesc = None def create(self, hop): - ts = self.timeshifter + ts = self.hrtyper if self.typedesc is None: T = self.original_concretetype.TO self.typedesc = rcontainer.StructTypeDesc(ts.RGenOp, T) @@ -658,13 +998,13 @@ else: return annmodel.SomeInteger() - def get_genop_var(self, v, llops): - ts = self.timeshifter - v_jitstate = hop.llops.getjitstate() - return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant, - [ts.s_JITState, self.annotation()], - [v_jitstate, v], - ts.s_ConstOrVar) +## def get_genop_var(self, v, llops): +## ts = self.hrtyper +## v_jitstate = hop.llops.getjitstate() +## return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant, +## [ts.s_JITState, self.annotation()], +## [v_jitstate, v], +## ts.s_ConstOrVar) def convert_const(self, ll_value): return ll_value @@ -689,12 +1029,12 @@ def convert_from_to((r_from, r_to), v, llops): assert r_from.lowleveltype == r_to.original_concretetype - ts = llops.timeshifter + ts = llops.hrtyper v_jitstate = llops.getjitstate() return llops.genmixlevelhelpercall(rvalue.ll_fromvalue, [ts.s_JITState, r_from.annotation()], [v_jitstate, v], - llops.timeshifter.s_RedBox) + ts.s_RedBox) # ____________________________________________________________ Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Thu Sep 21 11:30:27 2006 @@ -90,10 +90,9 @@ def ll_fromvalue(jitstate, value): "Make a constant RedBox from a low-level value." - rgenop = jitstate.curbuilder.rgenop + gv = ll_gv_fromvalue(jitstate, value) T = lltype.typeOf(value) - kind = rgenop.kindToken(T) - gv = rgenop.genconst(value) + kind = jitstate.curbuilder.rgenop.kindToken(T) cls = ll_redboxcls(T) return cls(kind, gv) @@ -104,10 +103,19 @@ cls = ll_redboxcls(T) return cls(kind, gv) +def ll_gv_fromvalue(jitstate, value): + rgenop = jitstate.curbuilder.rgenop + gv = rgenop.genconst(value) + return gv + def ll_getvalue(box, T): "Return the content of a known-to-be-constant RedBox." return box.genvar.revealconst(T) +def ll_is_constant(box): + "Check if a red box is known to be constant." + return box.is_constant() + class IntRedBox(RedBox): "A red box that contains a constant integer-like value." Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 21 11:30:27 2006 @@ -3,7 +3,7 @@ from pypy.jit.hintannotator.annotator import HintAnnotator from pypy.jit.hintannotator.bookkeeper import HintBookkeeper from pypy.jit.hintannotator.model import * -from pypy.jit.timeshifter.timeshift import HintTimeshift +from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype from pypy.jit.timeshifter import rtimeshift, rvalue, rtyper as hintrtyper from pypy.objspace.flow.model import summary from pypy.rpython.lltypesystem import lltype, llmemory, rstr @@ -94,12 +94,13 @@ backendoptimize=backendoptimize) # make the timeshifted graphs - htshift = HintTimeshift(ha, rtyper, self.RGenOp) - fresh_jitstate = htshift.ll_fresh_jitstate - finish_jitstate = htshift.ll_finish_jitstate - RESTYPE = htshift.originalconcretetype( - ha.translator.graphs[0].getreturnvar()) - htshift.timeshift() + hrtyper = HintRTyper(ha, rtyper, self.RGenOp) + hrtyper.specialize(view = conftest.option.view) + + fresh_jitstate = hrtyper.ll_fresh_jitstate + finish_jitstate = hrtyper.ll_finish_jitstate + args_hs, hs_res = hrtyper.get_sig_hs(ha.translator.graphs[0]) + RESTYPE = originalconcretetype(hs_res) t = rtyper.annotator.translator for graph in ha.translator.graphs: checkgraph(graph) @@ -122,9 +123,9 @@ argcolors = [] generate_code_args_s = [] - for v, llvalue in zip(graph1varargs, values): + for v, hs_arg, llvalue in zip(graph1varargs, args_hs, values): s_var = annmodel.ll_to_annotation(llvalue) - r = htshift.hrtyper.bindingrepr(v) + r = hrtyper.bindingrepr(v) residual_v = r.residual_values(llvalue) if len(residual_v) == 0: color = "green" @@ -132,9 +133,9 @@ else: color = "red" assert residual_v == [llvalue], "XXX for now" - ARGTYPE = htshift.originalconcretetype(v) + ARGTYPE = originalconcretetype(hs_arg) residual_argtypes.append(ARGTYPE) - timeshifted_entrypoint_args_s.append(htshift.s_RedBox) + timeshifted_entrypoint_args_s.append(hrtyper.s_RedBox) generate_code_args_s.append(annmodel.SomeBool()) argcolors.append(color) generate_code_args_s.append(s_var) @@ -143,9 +144,9 @@ graph1) timeshifted_entrypoint = PseudoHighLevelCallable( timeshifted_entrypoint_fnptr, - [htshift.s_JITState] + [hrtyper.s_JITState] + timeshifted_entrypoint_args_s, - htshift.s_JITState) + hrtyper.s_JITState) FUNC = lltype.FuncType(residual_argtypes, RESTYPE) argcolors = unrolling_iterable(argcolors) self.argcolors = argcolors @@ -216,7 +217,7 @@ self.ml_generate_code = ml_generate_code ## self.ml_call_residual_graph = ml_call_residual_graph self.rtyper = rtyper - self.htshift = htshift + self.hrtyper = hrtyper self.annotate_interface_functions() if conftest.option.view: from pypy.translator.tool.graphpage import FlowGraphPage @@ -228,7 +229,7 @@ return values def annotate_interface_functions(self): - annhelper = self.htshift.annhelper + annhelper = self.hrtyper.annhelper RGenOp = self.RGenOp ml_generate_code = self.ml_generate_code ## ml_call_residual_graph = self.ml_call_residual_graph @@ -270,7 +271,7 @@ # now try to run the residual graph generated by the builder residual_graph = ll_generated._obj.graph - residual_graph.exceptiontransformed = self.htshift.exc_data_ptr + residual_graph.exceptiontransformed = self.hrtyper.exc_data_ptr if conftest.option.view: residual_graph.show() self.insns = summary(residual_graph) @@ -886,8 +887,19 @@ res = self.timeshift(ll_function, [3], [], policy=P_NOVIRTUAL) assert res == 3 + def test_green_call(self): + def ll_add_one(x): + return x+1 + def ll_function(y): + z = ll_add_one(y) + z = hint(z, concrete=True) + return hint(z, variable=True) + + res = self.timeshift(ll_function, [3], [0], policy=P_NOVIRTUAL) + assert res == 4 + self.check_insns({}) + def test_split_on_green_return(self): - py.test.skip("in-progress") def ll_two(x): if x > 0: return 17 @@ -895,7 +907,7 @@ return 22 def ll_function(x): n = ll_two(x) - return n+1 + return hint(n+1, variable=True) res = self.timeshift(ll_function, [-70], []) assert res == 23 self.check_insns({'int_gt': 1}) Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Thu Sep 21 11:30:27 2006 @@ -8,7 +8,7 @@ def __init__(self, hrtyper, LIST): RGenOp = hrtyper.RGenOp - rtyper = hrtyper.timeshifter.rtyper + rtyper = hrtyper.rtyper self.LIST = LIST self.LISTPTR = lltype.Ptr(LIST) self.ptrkind = RGenOp.kindToken(self.LISTPTR) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Sep 21 11:30:27 2006 @@ -375,7 +375,7 @@ self.insert_link_conversions(extrablock) def _convert_link(self, block, link): - if link.exitcase is not None: + if link.exitcase is not None and link.exitcase != 'default': if isinstance(block.exitswitch, Variable): r_case = self.bindingrepr(block.exitswitch) else: Modified: pypy/dist/pypy/translator/backendopt/ssa.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/ssa.py (original) +++ pypy/dist/pypy/translator/backendopt/ssa.py Thu Sep 21 11:30:27 2006 @@ -16,9 +16,7 @@ # [Block, blockvar, linkvar, linkvar, linkvar...] opportunities = [] opportunities_with_const = [] - for block, links in mkentrymap(graph).items(): - if block is graph.startblock: - continue + for block, links in mkinsideentrymap(graph).items(): assert links for n, inputvar in enumerate(block.inputargs): vars = [block, inputvar] @@ -124,3 +122,95 @@ vct = [getattr(v, 'concretetype', None) for v in vlist] assert vct == vct[:1] * len(vct), ( "variables called %s have mixed concretetypes: %r" % (vname, vct)) + +# ____________________________________________________________ + +def mkinsideentrymap(graph_or_blocks): + # graph_or_blocks can be a full FunctionGraph, or a mapping + # {block: reachable-from-outside-flag}. + if isinstance(graph_or_blocks, dict): + blocks = graph_or_blocks + entrymap = {} + for block in blocks: + for link in block.exits: + if link.target in blocks and not blocks[link.target]: + entrymap.setdefault(link.target, []).append(link) + return entrymap + else: + graph = graph_or_blocks + entrymap = mkentrymap(graph) + del entrymap[graph.startblock] + return entrymap + +def variables_created_in(block): + result = {} + for v in block.inputargs: + result[v] = True + for op in block.operations: + result[op.result] = True + return result + + +def SSA_to_SSI(graph_or_blocks, annotator=None): + """Turn a number of blocks belonging to a flow graph into valid (i.e. SSI) + form, assuming that they are only in SSA form (i.e. they can use each + other's variables directly, without having to pass and rename them along + links). + + 'graph_or_blocks' can be a graph, or just a dict that lists some blocks + from a graph, as follows: {block: reachable-from-outside-flag}. + """ + from pypy.translator.unsimplify import copyvar + + entrymap = mkinsideentrymap(graph_or_blocks) + builder = DataFlowFamilyBuilder(graph_or_blocks) + variable_families = builder.get_variable_families() + del builder + + pending = [] # list of (block, var-used-but-not-defined) + + for block in entrymap: + variables_created = variables_created_in(block) + variables_used = {} + for op in block.operations: + for v in op.args: + if isinstance(v, Variable): + variables_used[v] = True + if isinstance(block.exitswitch, Variable): + variables_used[v] = True + for link in block.exits: + for v in link.args: + if isinstance(v, Variable): + variables_used[v] = True + + for v in variables_used: + if v not in variables_created: + pending.append((block, v)) + + while pending: + block, v = pending.pop() + v_rep = variable_families.find_rep(v) + variables_created = variables_created_in(block) + if v in variables_created: + continue # already ok + for w in variables_created: + w_rep = variable_families.find_rep(w) + if v_rep is w_rep: + # 'w' is in the same family as 'v', so we can simply + # reuse its value for 'v' + block.renamevariables({v: w}) + break + else: + # didn't find it. Add it to all incoming links. + try: + links = entrymap[block] + except KeyError: + raise Exception("SSA_to_SSI failed: no way to give a value to" + " %r in %r" % (v, block)) + w = copyvar(annotator, v) + variable_families.union(v, w) + block.renamevariables({v: w}) + block.inputargs.append(w) + for link in links: + link.args.append(v) + pending.append((link.prevblock, v)) Modified: pypy/dist/pypy/translator/backendopt/test/test_ssa.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_ssa.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_ssa.py Thu Sep 21 11:30:27 2006 @@ -1,6 +1,7 @@ from pypy.translator.backendopt.ssa import * from pypy.translator.translator import TranslationContext -from pypy.objspace.flow.model import flatten, Block +from pypy.objspace.flow.model import flatten, Block, Link, Variable, Constant +from pypy.objspace.flow.model import SpaceOperation def test_data_flow_families(): @@ -49,3 +50,63 @@ allvars += [v.name for v in block.getvariables()] # see comments above for where the 8 remaining variables are expected to be assert len(dict.fromkeys(allvars)) == 8 + + +def test_SSA_to_SSI(): + c = Variable('c') + x = Variable('x') + y = Variable('y') + b1 = Block([c]) + b2 = Block([x]) + b3 = Block([]) + + b2.operations.append(SpaceOperation('add', [x, c], y)) + b2.exitswitch = y + + b1.closeblock(Link([Constant(0)], b2)) + b2.closeblock(Link([y], b2), Link([], b3)) + b3.closeblock(Link([y, c], None)) + + SSA_to_SSI({b1: True, # reachable from outside + b2: False, + b3: False}) + + assert len(b1.inputargs) == 1 + assert len(b2.inputargs) == 2 + assert len(b3.inputargs) == 2 + + assert b2.inputargs == b2.operations[0].args + assert len(b1.exits[0].args) == 2 + assert b1.exits[0].args[1] is c + assert len(b2.exits[0].args) == 2 + assert b2.exits[0].args == [y, b2.inputargs[1]] + assert len(b2.exits[1].args) == 2 + assert len(b3.exits[0].args) == 2 + + index = b3.inputargs.index(b3.exits[0].args[0]) + assert b2.exits[1].args[index] is b2.operations[0].result + + index = b3.inputargs.index(b3.exits[0].args[1]) + assert b2.exits[1].args[index] is b2.inputargs[1] + + +def test_SSA_to_SSI_2(): + x = Variable('x') + y = Variable('y') + z = Variable('z') + b1 = Block([x]) + b2 = Block([y]) + b3 = Block([]) + + b3.operations.append(SpaceOperation('hello', [y], z)) + b1.closeblock(Link([x], b2), Link([], b3)) + + SSA_to_SSI({b1: True, # reachable from outside + b2: False, + b3: False}) + + assert b1.inputargs == [x] + assert b2.inputargs == [y] + assert b3.inputargs == [b3.operations[0].args[0]] + assert b1.exits[0].args == [x] + assert b1.exits[1].args == [x] Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Thu Sep 21 11:30:27 2006 @@ -63,10 +63,10 @@ if (len(link.target.exits) != 1 and link.target.exitswitch != c_last_exception): break - assert link.target is not link.prevblock, ( - "the graph contains an empty infinite loop") block1 = link.target exit = block1.exits[0] + assert block1 is not exit.target, ( + "the graph contains an empty infinite loop") outputargs = [] for v in exit.args: if isinstance(v, Variable): From ac at codespeak.net Thu Sep 21 11:32:01 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 21 Sep 2006 11:32:01 +0200 (CEST) Subject: [pypy-svn] r32557 - pypy/branch/timeshift-refactoring Message-ID: <20060921093201.ED61D10075@code0.codespeak.net> Author: ac Date: Thu Sep 21 11:32:00 2006 New Revision: 32557 Removed: pypy/branch/timeshift-refactoring/ Log: (arigo, arre) Cut dead branch. From arigo at codespeak.net Thu Sep 21 11:34:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 11:34:50 +0200 (CEST) Subject: [pypy-svn] r32558 - pypy/dist/pypy/annotation Message-ID: <20060921093450.AB6FD10082@code0.codespeak.net> Author: arigo Date: Thu Sep 21 11:34:49 2006 New Revision: 32558 Modified: pypy/dist/pypy/annotation/pairtype.py Log: Added docstring. Modified: pypy/dist/pypy/annotation/pairtype.py ============================================================================== --- pypy/dist/pypy/annotation/pairtype.py (original) +++ pypy/dist/pypy/annotation/pairtype.py Thu Sep 21 11:34:49 2006 @@ -1,5 +1,30 @@ """ -XXX A docstring should go here. +Two magic tricks for classes: + + class X: + __metaclass__ = extendabletype + ... + + # in some other file... + class __extend__(X): + ... # and here you can add new methods and class attributes to X + +Mostly useful together with the second trick, which lets you build +methods whose 'self' is a pair of objects instead of just one: + + class __extend__(pairtype(X, Y)): + attribute = 42 + def method((x, y), other, arguments): + ... + + pair(x, y).attribute + pair(x, y).method(other, arguments) + +This finds methods and class attributes based on the actual +class of both objects that go into the pair(), with the usual +rules of method/attribute overriding in (pairs of) subclasses. + +For more information, see test_pairtype. """ class extendabletype(type): From ac at codespeak.net Thu Sep 21 12:01:48 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 21 Sep 2006 12:01:48 +0200 (CEST) Subject: [pypy-svn] r32559 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20060921100148.E84D21007F@code0.codespeak.net> Author: ac Date: Thu Sep 21 12:01:45 2006 New Revision: 32559 Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (arigo, arre) Add tests for recursive calls of which one doesn't work yet. Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 21 12:01:45 2006 @@ -911,3 +911,25 @@ res = self.timeshift(ll_function, [-70], []) assert res == 23 self.check_insns({'int_gt': 1}) + + + def test_recursive_call(self): + def ll_pseudo_factorial(n, fudge): + k = hint(n, concrete=True) + if n <= 0: + return 1 + return n * ll_pseudo_factorial(n - 1, fudge + n) - fudge + res = self.timeshift(ll_pseudo_factorial, [4, 2], [0]) + expected = ll_pseudo_factorial(4, 2) + assert res == expected + + def test_recursive_with_red_termination_condition(self): + py.test.skip('Does not terminate') + def ll_factorial(n): + if n <= 0: + return 1 + return n * ll_factorial(n - 1) + + res = self.timeshift(ll_factorial, [5], []) + assert res == 120 + From ac at codespeak.net Thu Sep 21 12:39:28 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 21 Sep 2006 12:39:28 +0200 (CEST) Subject: [pypy-svn] r32561 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060921103928.996B910084@code0.codespeak.net> Author: ac Date: Thu Sep 21 12:39:26 2006 New Revision: 32561 Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (arigo, arre) Intermediate checkin. Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 21 12:39:26 2006 @@ -166,7 +166,7 @@ def timeshift_graph(self, graph): # specialize all blocks of this graph - for block in graph.iterblocks(): + for block in list(graph.iterblocks()): self.annotator.annotated[block] = graph self.specialize_block(block) # "normalize" the graphs by putting an explicit v_jitstate variable @@ -245,6 +245,54 @@ _callable = graph.func) return fnptr, args_r + def get_timeshift_mapper(self, FUNC, specialization_key, graphs): + key = FUNC, specialization_key + try: + timeshift_mapper, values, keys = self.timeshift_mapping[key] + except KeyError: + values = [] + keys = [] + fnptrmap = {} + + def getter(fnptrmap, fnptr): + # indirection needed to defeat the flow object space + return fnptrmap[fnptr] + + def fill_dict(fnptrmap, values, keys): + for i in range(len(values)): + fnptrmap[values[i]] = keys[i] + + def timeshift_mapper(fnptrbox): + fnptr = rvalue.ll_getvalue(fnptrbox, FUNC) + try: + return getter(fnptrmap, fnptr) + except KeyError: + fill_dict(fnptrmap, values, keys) + return getter(fnptrmap, fnptr) # try again + + self.timeshift_mapping[key] = timeshift_mapper, values, keys + + bk = self.hannotator.bookkeeper + common_args_r = None + COMMON_TS_FUNC = None + tsgraphs = [] + for graph in graphs: + fnptr = self.rtyper.getcallable(graph) + ts_fnptr, args_r = self.get_timeshifted_fnptr(graph, + specialization_key) + tsgraphs.append(ts_fnptr._obj.graph) + TS_FUNC = lltype.typeOf(ts_fnptr) + if common_args_r is None: + common_args_r = args_r + COMMON_TS_FUNC = TS_FUNC + else: + # XXX for now + assert COMMON_TS_FUNC == TS_FUNC + assert common_args_r == args_r + keys.append(fnptr) + values.append(ts_fnptr) + return timeshift_mapper, COMMON_TS_FUNC, common_args_r, tsgraphs + def insert_v_jitstate_everywhere(self, graph): from pypy.translator.unsimplify import varoftype for block in graph.iterblocks(): Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 21 12:39:26 2006 @@ -933,3 +933,20 @@ res = self.timeshift(ll_factorial, [5], []) assert res == 120 + def test_simple_indirect_call(self): + py.test.skip('In-progress') + def g1(v): + return v * 2 + + def g2(v): + return v + 2 + + def f(flag, v): + if hint(flag, concrete=True): + g = g1 + else: + g = g2 + return g(v) + + res = self.timeshift(f, [False, 40], [0]) + assert res == 42 From arigo at codespeak.net Thu Sep 21 15:09:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 15:09:51 +0200 (CEST) Subject: [pypy-svn] r32563 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060921130951.86EAF10081@code0.codespeak.net> Author: arigo Date: Thu Sep 21 15:09:49 2006 New Revision: 32563 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py Log: Make Struct.__repr__ shorter. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Thu Sep 21 15:09:49 2006 @@ -257,8 +257,12 @@ _str_fields = saferecursive(_str_fields, '...') def __str__(self): - return "%s %s { %s }" % (self.__class__.__name__, - self._name, self._str_fields()) + # -- long version -- + #return "%s %s { %s }" % (self.__class__.__name__, + # self._name, self._str_fields()) + # -- short version -- + return "%s %s { %s }" % (self.__class__.__name__, self._name, + ', '.join(self._names)) def _short_name(self): return "%s %s" % (self.__class__.__name__, self._name) From arigo at codespeak.net Thu Sep 21 15:10:29 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 15:10:29 +0200 (CEST) Subject: [pypy-svn] r32564 - pypy/dist/pypy/annotation Message-ID: <20060921131029.0F45610081@code0.codespeak.net> Author: arigo Date: Thu Sep 21 15:10:27 2006 New Revision: 32564 Modified: pypy/dist/pypy/annotation/specialize.py Log: A specialization 'argvalue(2, 3, 4)' to specialize on multiple arguments. Not used yet. Modified: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- pypy/dist/pypy/annotation/specialize.py (original) +++ pypy/dist/pypy/annotation/specialize.py Thu Sep 21 15:10:27 2006 @@ -373,8 +373,8 @@ ## return funcdesc.cachedgraph(s1_type, alt_name='memo_%s' % funcdesc.name, ## builder=builder) -def specialize_argvalue(funcdesc, args_s, i): - key = args_s[i].const +def specialize_argvalue(funcdesc, args_s, *argindices): + key = tuple([args_s[i].const for i in argindices]) return funcdesc.cachedgraph(key) def specialize_argtype(funcdesc, args_s, i): From arigo at codespeak.net Thu Sep 21 15:11:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 15:11:00 +0200 (CEST) Subject: [pypy-svn] r32565 - in pypy/dist/pypy: jit/timeshifter jit/timeshifter/test rpython Message-ID: <20060921131100.C8E4B10081@code0.codespeak.net> Author: arigo Date: Thu Sep 21 15:10:58 2006 New Revision: 32565 Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/transform.py pypy/dist/pypy/rpython/annlowlevel.py Log: Indirect red calls now working. The function to call must be green so far. Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 21 15:10:58 2006 @@ -256,14 +256,13 @@ def getter(fnptrmap, fnptr): # indirection needed to defeat the flow object space - return fnptrmap[fnptr] + return fnptrmap[llmemory.cast_ptr_to_adr(fnptr)] def fill_dict(fnptrmap, values, keys): for i in range(len(values)): - fnptrmap[values[i]] = keys[i] + fnptrmap[llmemory.cast_ptr_to_adr(keys[i])] = values[i] - def timeshift_mapper(fnptrbox): - fnptr = rvalue.ll_getvalue(fnptrbox, FUNC) + def timeshift_mapper(fnptr): try: return getter(fnptrmap, fnptr) except KeyError: @@ -272,14 +271,14 @@ self.timeshift_mapping[key] = timeshift_mapper, values, keys - bk = self.hannotator.bookkeeper + bk = self.annotator.bookkeeper common_args_r = None COMMON_TS_FUNC = None tsgraphs = [] for graph in graphs: fnptr = self.rtyper.getcallable(graph) ts_fnptr, args_r = self.get_timeshifted_fnptr(graph, - specialization_key) + specialization_key) tsgraphs.append(ts_fnptr._obj.graph) TS_FUNC = lltype.typeOf(ts_fnptr) if common_args_r is None: @@ -568,34 +567,6 @@ return self.translate_op_ptr_nonzero(hop, reverse=True) - def translate_op_indirect_call(self, hop): - XXX - bk = self.annotator.bookkeeper - ts = self - v_jitstate = hop.llops.getjitstate() - v_funcbox = hop.args_v[0] - graph_list = hop.args_v[-1].value - hop.r_s_pop(0) - hop.r_s_pop() - args_hs = hop.args_s[:] - # fixed is always false here - specialization_key = bk.specialization_key(False, args_hs) - FUNC = ts.originalconcretetype(v_funcbox) - - mapper, TS_FUNC, args_r, tsgraphs = ts.get_timeshift_mapper( - FUNC, specialization_key, graph_list) - args_v = hop.inputargs(*args_r) - - v_tsfunc = hop.llops.genmixlevelhelpercall(mapper, - [ts.s_RedBox], - [v_funcbox], - annmodel.SomePtr(TS_FUNC)) - args_v[:0] = [v_tsfunc, v_jitstate] - RESULT = v_tsfunc.concretetype.TO.RESULT - args_v.append(hop.inputconst(lltype.Void, tsgraphs)) - v_newjitstate = hop.genop('indirect_call', args_v, RESULT) - hop.llops.setjitstate(v_newjitstate) - # special operations inserted by the HintGraphTransformer def translate_op_enter_graph(self, hop): @@ -867,7 +838,6 @@ def translate_op_red_call(self, hop): bk = self.annotator.bookkeeper - ts = self v_jitstate = hop.llops.getjitstate() c_func = hop.args_v[0] fnobj = c_func.value._obj @@ -875,8 +845,8 @@ args_hs = hop.args_s[:] # fixed is always false here specialization_key = bk.specialization_key(False, args_hs) - fnptr, args_r = ts.get_timeshifted_fnptr(fnobj.graph, - specialization_key) + fnptr, args_r = self.get_timeshifted_fnptr(fnobj.graph, + specialization_key) args_v = hop.inputargs(*args_r) args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate] RESULT = lltype.typeOf(fnptr).TO.RESULT @@ -885,6 +855,33 @@ translate_op_yellow_call = translate_op_red_call + def translate_op_red_indirect_call(self, hop): + bk = self.annotator.bookkeeper + v_jitstate = hop.llops.getjitstate() + + FUNC = originalconcretetype(hop.args_s[0]) + v_func = hop.inputarg(self.getgreenrepr(FUNC), arg=0) + graph_list = hop.args_v[-1].value + hop.r_s_pop(0) + hop.r_s_pop() + args_hs = hop.args_s[:] + # fixed is always false here + specialization_key = bk.specialization_key(False, args_hs) + + mapper, TS_FUNC, args_r, tsgraphs = self.get_timeshift_mapper( + FUNC, specialization_key, graph_list) + args_v = hop.inputargs(*args_r) + + v_tsfunc = hop.llops.genmixlevelhelpercall(mapper, + [annmodel.SomePtr(FUNC)], + [v_func ], + annmodel.SomePtr(TS_FUNC)) + args_v[:0] = [v_tsfunc, v_jitstate] + RESULT = v_tsfunc.concretetype.TO.RESULT + args_v.append(hop.inputconst(lltype.Void, tsgraphs)) + v_newjitstate = hop.genop('indirect_call', args_v, RESULT) + hop.llops.setjitstate(v_newjitstate) + class HintLowLevelOpList(LowLevelOpList): """Warning: the HintLowLevelOpList's rtyper is the *original* Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 21 15:10:58 2006 @@ -934,7 +934,6 @@ assert res == 120 def test_simple_indirect_call(self): - py.test.skip('In-progress') def g1(v): return v * 2 @@ -950,3 +949,4 @@ res = self.timeshift(f, [False, 40], [0]) assert res == 42 + self.check_insns({'int_add': 1}) Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Thu Sep 21 15:10:58 2006 @@ -331,9 +331,12 @@ uses_retval = False reds, greens = self.sort_by_color(varsalive) + newopname = {'direct_call' : 'red_call', + 'indirect_call': 'red_indirect_call'}[op.opname] + newops = [] self.genop(newops, 'save_locals', reds) - self.genop(newops, 'red_call', op.args) # Void result, + self.genop(newops, newopname, op.args) # Void result, # because the call doesn't return its redbox result, but only # has the hidden side-effect of putting it in the jitstate mapping = {} Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Thu Sep 21 15:10:58 2006 @@ -253,8 +253,10 @@ rtyper.type_system.perform_normalizations(rtyper) for r in self.delayedreprs: r.set_setup_delayed(False) + rtyper.call_all_setups() for p, repr, obj in self.delayedconsts: p._become(repr.convert_const(obj)) + rtyper.call_all_setups() for p, graph in self.delayedfuncs: real_p = rtyper.getcallable(graph) lltype.typeOf(p).TO.become(lltype.typeOf(real_p).TO) From arigo at codespeak.net Thu Sep 21 15:14:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 15:14:54 +0200 (CEST) Subject: [pypy-svn] r32566 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060921131454.DC4FB10086@code0.codespeak.net> Author: arigo Date: Thu Sep 21 15:14:52 2006 New Revision: 32566 Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: Wow, our untested normalization code worked out of the box. Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 21 15:14:52 2006 @@ -141,6 +141,7 @@ """ Driver for running the timeshifter. """ + self.type_system.perform_normalizations(self) graphs = self.annotator.translator.graphs if view: for graph in graphs: Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 21 15:14:52 2006 @@ -950,3 +950,25 @@ res = self.timeshift(f, [False, 40], [0]) assert res == 42 self.check_insns({'int_add': 1}) + + def test_normalize_indirect_call(self): + def g1(v): + return -17 + + def g2(v): + return v + 2 + + def f(flag, v): + if hint(flag, concrete=True): + g = g1 + else: + g = g2 + return g(v) + + res = self.timeshift(f, [False, 40], [0]) + assert res == 42 + self.check_insns({'int_add': 1}) + + res = self.timeshift(f, [True, 40], [0]) + assert res == -17 + self.check_insns() From arigo at codespeak.net Thu Sep 21 18:53:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Sep 2006 18:53:49 +0200 (CEST) Subject: [pypy-svn] r32567 - in pypy/dist/pypy/jit: hintannotator timeshifter timeshifter/test Message-ID: <20060921165349.1C0B910082@code0.codespeak.net> Author: arigo Date: Thu Sep 21 18:53:47 2006 New Revision: 32567 Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/transform.py Log: (arre, arigo) Small refactoring: moved the computation of the graph->tsgraph correspondance into transform.py. This is a further step towards making rtyper.py independent of the hannotator's results, but based only on the operations produced by transform. More advanced normalization test. Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Thu Sep 21 18:53:47 2006 @@ -110,8 +110,11 @@ return origin def compute_at_fixpoint(self): + pass + + def compute_after_normalization(self): # compute and cache the green-ness of OriginFlags objects - # while we can do so (i.e. before the graphs are modified) + # while we can do so (i.e. before the graphs are modified). for origin in self.originflags.values(): if origin.spaceop is not None: origin.greenargs_cached = origin.greenargs() Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Thu Sep 21 18:53:47 2006 @@ -485,7 +485,7 @@ jitstate.frame = myframe.backframe return jitstate -def leave_graph_void(jitstate): +def leave_graph_gray(jitstate): jitstate = merge_returning_jitstates(jitstate) myframe = jitstate.frame jitstate.frame = myframe.backframe Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 21 18:53:47 2006 @@ -142,20 +142,20 @@ Driver for running the timeshifter. """ self.type_system.perform_normalizations(self) - graphs = self.annotator.translator.graphs + self.annotator.bookkeeper.compute_after_normalization() + entrygraph = self.annotator.translator.graphs[0] + pending = [entrygraph] + seen = {entrygraph: True} + while pending: + graph = pending.pop() + for nextgraph in self.transform_graph(graph): + if nextgraph not in seen: + pending.append(nextgraph) + seen[nextgraph] = True if view: - for graph in graphs: - self.transform_graph(graph) self.annotator.translator.view() # in the middle - for graph in graphs: - self.timeshift_graph(graph) - - else: - # do the whole transformation graph-by-graph if there is no - # need to view the intermediate result - for graph in graphs: - self.transform_graph(graph) - self.timeshift_graph(graph) + for graph in seen: + self.timeshift_graph(graph) def transform_graph(self, graph): # prepare the graphs by inserting all bookkeeping/dispatching logic @@ -164,6 +164,7 @@ transformer = HintGraphTransformer(self.annotator, graph) transformer.transform() flowmodel.checkgraph(graph) # for now + return transformer.tsgraphs_seen def timeshift_graph(self, graph): # specialize all blocks of this graph @@ -232,66 +233,69 @@ self.dispatchsubclasses[mergepointfamily] = subclass return subclass - def get_timeshifted_fnptr(self, graph, specialization_key): - bk = self.annotator.bookkeeper - tsgraph = bk.get_graph_by_key(graph, specialization_key) + def get_args_r(self, tsgraph): args_hs, hs_res = self.get_sig_hs(tsgraph) - args_r = [self.getrepr(hs_arg) for hs_arg in args_hs] + return [self.getrepr(hs_arg) for hs_arg in args_hs] + + def gettscallable(self, tsgraph): + args_r = self.get_args_r(tsgraph) ARGS = [self.r_JITState.lowleveltype] ARGS += [r.lowleveltype for r in args_r] RESULT = self.r_JITState.lowleveltype - fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT), - tsgraph.name, - graph=tsgraph, - _callable = graph.func) - return fnptr, args_r - - def get_timeshift_mapper(self, FUNC, specialization_key, graphs): - key = FUNC, specialization_key + return lltype.functionptr(lltype.FuncType(ARGS, RESULT), + tsgraph.name, + graph=tsgraph) + + def get_timeshift_mapper(self, graph2ts): + # XXX try to share the results between "similar enough" graph2ts'es + key = graph2ts.items() + key.sort() + key = tuple(key) try: - timeshift_mapper, values, keys = self.timeshift_mapping[key] + return self.timeshift_mapping[key] except KeyError: - values = [] - keys = [] - fnptrmap = {} - - def getter(fnptrmap, fnptr): - # indirection needed to defeat the flow object space - return fnptrmap[llmemory.cast_ptr_to_adr(fnptr)] - - def fill_dict(fnptrmap, values, keys): - for i in range(len(values)): - fnptrmap[llmemory.cast_ptr_to_adr(keys[i])] = values[i] - - def timeshift_mapper(fnptr): - try: - return getter(fnptrmap, fnptr) - except KeyError: - fill_dict(fnptrmap, values, keys) - return getter(fnptrmap, fnptr) # try again - - self.timeshift_mapping[key] = timeshift_mapper, values, keys + pass bk = self.annotator.bookkeeper + keys = [] + values = [] common_args_r = None COMMON_TS_FUNC = None - tsgraphs = [] - for graph in graphs: - fnptr = self.rtyper.getcallable(graph) - ts_fnptr, args_r = self.get_timeshifted_fnptr(graph, - specialization_key) - tsgraphs.append(ts_fnptr._obj.graph) - TS_FUNC = lltype.typeOf(ts_fnptr) + for graph, tsgraph in graph2ts.items(): + fnptr = self.rtyper.getcallable(graph) + ts_fnptr = self.gettscallable(tsgraph) + args_r = self.get_args_r(tsgraph) + TS_FUNC = lltype.typeOf(ts_fnptr) if common_args_r is None: common_args_r = args_r COMMON_TS_FUNC = TS_FUNC else: - # XXX for now + # should be ensured by normalization assert COMMON_TS_FUNC == TS_FUNC assert common_args_r == args_r keys.append(fnptr) values.append(ts_fnptr) - return timeshift_mapper, COMMON_TS_FUNC, common_args_r, tsgraphs + + fnptrmap = {} + + def getter(fnptrmap, fnptr): + # indirection needed to defeat the flow object space + return fnptrmap[llmemory.cast_ptr_to_adr(fnptr)] + + def fill_dict(fnptrmap, values, keys): + for i in range(len(values)): + fnptrmap[llmemory.cast_ptr_to_adr(keys[i])] = values[i] + + def timeshift_mapper(fnptr): + try: + return getter(fnptrmap, fnptr) + except KeyError: + fill_dict(fnptrmap, values, keys) + return getter(fnptrmap, fnptr) # try again + + result = timeshift_mapper, COMMON_TS_FUNC, common_args_r + self.timeshift_mapping[key] = result + return result def insert_v_jitstate_everywhere(self, graph): from pypy.translator.unsimplify import varoftype @@ -589,9 +593,9 @@ self.s_JITState) hop.llops.setjitstate(v_newjs) - def translate_op_leave_graph_void(self, hop): + def translate_op_leave_graph_gray(self, hop): v_jitstate = hop.llops.getjitstate() - v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_void, + v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_gray, [self.s_JITState], [v_jitstate ], self.s_JITState) @@ -840,49 +844,40 @@ def translate_op_red_call(self, hop): bk = self.annotator.bookkeeper v_jitstate = hop.llops.getjitstate() - c_func = hop.args_v[0] - fnobj = c_func.value._obj + tsgraph = hop.args_v[0].value hop.r_s_popfirstarg() - args_hs = hop.args_s[:] - # fixed is always false here - specialization_key = bk.specialization_key(False, args_hs) - fnptr, args_r = self.get_timeshifted_fnptr(fnobj.graph, - specialization_key) - args_v = hop.inputargs(*args_r) + args_v = hop.inputargs(*self.get_args_r(tsgraph)) + fnptr = self.gettscallable(tsgraph) args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate] RESULT = lltype.typeOf(fnptr).TO.RESULT v_newjitstate = hop.genop('direct_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) - translate_op_yellow_call = translate_op_red_call - - def translate_op_red_indirect_call(self, hop): + def translate_op_indirect_red_call(self, hop): bk = self.annotator.bookkeeper v_jitstate = hop.llops.getjitstate() - FUNC = originalconcretetype(hop.args_s[0]) v_func = hop.inputarg(self.getgreenrepr(FUNC), arg=0) - graph_list = hop.args_v[-1].value + graph2ts = hop.args_v[-1].value hop.r_s_pop(0) hop.r_s_pop() - args_hs = hop.args_s[:] - # fixed is always false here - specialization_key = bk.specialization_key(False, args_hs) - - mapper, TS_FUNC, args_r, tsgraphs = self.get_timeshift_mapper( - FUNC, specialization_key, graph_list) - args_v = hop.inputargs(*args_r) - + mapper, TS_FUNC, args_r = self.get_timeshift_mapper(graph2ts) v_tsfunc = hop.llops.genmixlevelhelpercall(mapper, [annmodel.SomePtr(FUNC)], [v_func ], annmodel.SomePtr(TS_FUNC)) - args_v[:0] = [v_tsfunc, v_jitstate] + args_v = [v_tsfunc, v_jitstate] + hop.inputargs(*args_r) RESULT = v_tsfunc.concretetype.TO.RESULT - args_v.append(hop.inputconst(lltype.Void, tsgraphs)) + args_v.append(hop.inputconst(lltype.Void, graph2ts.values())) v_newjitstate = hop.genop('indirect_call', args_v, RESULT) hop.llops.setjitstate(v_newjitstate) + translate_op_gray_call = translate_op_red_call + translate_op_indirect_gray_call = translate_op_indirect_red_call + + translate_op_yellow_call = translate_op_red_call + translate_op_indirect_yellow_call = translate_op_indirect_red_call + class HintLowLevelOpList(LowLevelOpList): """Warning: the HintLowLevelOpList's rtyper is the *original* Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 21 18:53:47 2006 @@ -971,4 +971,38 @@ res = self.timeshift(f, [True, 40], [0]) assert res == -17 - self.check_insns() + self.check_insns({}) + + def test_normalize_indirect_call_more(self): + def g1(v): + if v >= 0: + return -17 + else: + return -155 + + def g2(v): + return v + 2 + + def f(flag, v): + w = g1(v) + if hint(flag, concrete=True): + g = g1 + else: + g = g2 + return g(v) + w + + res = self.timeshift(f, [False, 40], [0]) + assert res == 25 + self.check_insns({'int_add': 2, 'int_ge': 1}) + + res = self.timeshift(f, [True, 40], [0]) + assert res == -34 + self.check_insns({'int_ge': 2, 'int_add': 1}) + + res = self.timeshift(f, [False, -1000], [0]) + assert res == f(False, -1000) + self.check_insns({'int_add': 2, 'int_ge': 1}) + + res = self.timeshift(f, [True, -1000], [0]) + assert res == f(True, -1000) + self.check_insns({'int_ge': 2, 'int_add': 1}) Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Thu Sep 21 18:53:47 2006 @@ -28,9 +28,11 @@ def __init__(self, hannotator, graph): self.hannotator = hannotator self.graph = graph + self.graphcolor = self.graph_calling_color(graph) self.resumepoints = {} self.mergepointfamily = MergePointFamily() self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily) + self.tsgraphs_seen = [] def transform(self): mergepoints = list(self.enumerate_merge_points()) @@ -49,6 +51,24 @@ if len(links) > 1 and block is not self.graph.returnblock: yield block + def graph_calling_color(self, tsgraph): + args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph] + if originalconcretetype(hs_res) is lltype.Void: + return 'gray' + elif hs_res.is_green(): + return 'yellow' + else: + return 'red' + + def timeshifted_graph_of(self, graph, args_v): + bk = self.hannotator.bookkeeper + args_hs = [self.hannotator.binding(v) for v in args_v] + # fixed is always false here + specialization_key = bk.specialization_key(False, args_hs) + tsgraph = bk.get_graph_by_key(graph, specialization_key) + self.tsgraphs_seen.append(tsgraph) + return tsgraph + # __________ helpers __________ def genop(self, block, opname, args, result_type=None, result_like=None): @@ -114,11 +134,13 @@ used[v] = True return [v for v in used if v in created_before] - def sort_by_color(self, vars): + def sort_by_color(self, vars, by_color_of_vars=None): reds = [] greens = [] - for v in vars: - if self.hannotator.binding(v).is_green(): + if by_color_of_vars is None: + by_color_of_vars = vars + for v, bcv in zip(vars, by_color_of_vars): + if self.hannotator.binding(bcv).is_green(): greens.append(v) else: reds.append(v) @@ -169,7 +191,7 @@ constant_block.exitswitch = v_greenswitch constant_block.closeblock(link_f, link_t) - reds, greens = self.sort_by_color(link_f.args) + reds, greens = self.sort_by_color(link_f.args, link_f.target.inputargs) self.genop(nonconstant_block, 'save_locals', reds) resumepoint = self.get_resume_point(link_f.target) c_resumepoint = inputconst(lltype.Signed, resumepoint) @@ -262,16 +284,15 @@ def insert_save_return(self): block = self.before_return_block() [v_retbox] = block.inputargs - hs_retbox = self.hannotator.binding(v_retbox) - if originalconcretetype(hs_retbox) is lltype.Void: - self.leave_graph_opname = 'leave_graph_void' + if self.graphcolor == 'gray': self.genop(block, 'save_locals', []) - elif hs_retbox.is_green(): - self.leave_graph_opname = 'leave_graph_yellow' + elif self.graphcolor == 'yellow': self.genop(block, 'save_greens', [v_retbox]) - else: + elif self.graphcolor == 'red': self.leave_graph_opname = 'leave_graph_red' self.genop(block, 'save_locals', [v_retbox]) + else: + raise AssertionError(self.graph, self.graphcolor) self.genop(block, 'save_return', []) def insert_enter_graph(self): @@ -284,28 +305,47 @@ def insert_leave_graph(self): block = self.before_return_block() - self.genop(block, self.leave_graph_opname, []) + self.genop(block, 'leave_graph_%s' % (self.graphcolor,), []) # __________ handling of the various kinds of calls __________ + def graphs_from(self, spaceop): + if spaceop.opname == 'direct_call': + c_func = spaceop.args[0] + fnobj = c_func.value._obj + graphs = [fnobj.graph] + args_v = spaceop.args[1:] + elif spaceop.opname == 'indirect_call': + graphs = spaceop.args[-1].value + args_v = spaceop.args[1:-1] + else: + raise AssertionError(spaceop.opname) + for graph in graphs: + tsgraph = self.timeshifted_graph_of(graph, args_v) + yield graph, tsgraph + def guess_call_kind(self, spaceop): - if spaceop.opname == 'indirect_call': - return 'red' # for now - assert spaceop.opname == 'direct_call' - c_func = spaceop.args[0] - fnobj = c_func.value._obj - s_result = self.hannotator.binding(spaceop.result) - if hasattr(fnobj._callable, 'oopspec'): - return 'oopspec' - elif (originalconcretetype(s_result) is not lltype.Void and - s_result.is_green()): - for v in spaceop.args: - s_arg = self.hannotator.binding(v) - if not s_arg.is_green(): - return 'yellow' - return 'green' + if spaceop.opname == 'direct_call': + c_func = spaceop.args[0] + fnobj = c_func.value._obj + if hasattr(fnobj._callable, 'oopspec'): + return 'oopspec' + + for v in spaceop.args: + hs_arg = self.hannotator.binding(v) + if not hs_arg.is_green(): + break else: - return 'red' + hs_res = self.hannotator.binding(spaceop.result) + if hs_res.is_green(): + # all-green arguments and result + return 'green' + colors = {} + for graph, tsgraph in self.graphs_from(spaceop): + color = self.graph_calling_color(tsgraph) + colors[color] = tsgraph + assert len(colors) == 1, colors # buggy normalization? + return color def split_after_calls(self): for block in list(self.graph.iterblocks()): @@ -316,7 +356,21 @@ handler = getattr(self, 'handle_%s_call' % (call_kind,)) handler(block, i) - def handle_red_call(self, block, pos): + def make_call(self, block, op, save_locals_vars, color='red'): + self.genop(block, 'save_locals', save_locals_vars) + targets = dict(self.graphs_from(op)) + if len(targets) == 1: + [tsgraph] = targets.values() + c_tsgraph = inputconst(lltype.Void, tsgraph) + self.genop(block, '%s_call' % (color,), [c_tsgraph] + op.args[1:]) + # Void result, because the call doesn't return its redbox result, + # but only has the hidden side-effect of putting it in the jitstate + else: + c_targets = inputconst(lltype.Void, targets) + self.genop(block, 'indirect_%s_call' % (color,), + op.args[:-1] + [c_targets]) + + def handle_red_call(self, block, pos, color='red'): # the 'save_locals' pseudo-operation is used to save all # alive local variables into the current JITState beforeops = block.operations[:pos] @@ -331,14 +385,9 @@ uses_retval = False reds, greens = self.sort_by_color(varsalive) - newopname = {'direct_call' : 'red_call', - 'indirect_call': 'red_indirect_call'}[op.opname] - newops = [] - self.genop(newops, 'save_locals', reds) - self.genop(newops, newopname, op.args) # Void result, - # because the call doesn't return its redbox result, but only - # has the hidden side-effect of putting it in the jitstate + self.make_call(newops, op, reds, color) + mapping = {} for i, var in enumerate(reds): c_index = Constant(i, concretetype=lltype.Signed) @@ -346,7 +395,8 @@ result_like = var) mapping[var] = newvar - if uses_retval and not self.hannotator.binding(op.result).is_green(): + if uses_retval: + assert not self.hannotator.binding(op.result).is_green() var = op.result newvar = self.genop(newops, 'fetch_return', [], result_like = var) @@ -359,6 +409,9 @@ block.inputargs = saved block.operations[:0] = beforeops + newops + def handle_gray_call(self, block, pos): + self.handle_red_call(block, pos, color='gray') + def handle_oopspec_call(self, block, pos): op = block.operations[pos] assert op.opname == 'direct_call' @@ -388,8 +441,7 @@ nextblock.inputargs.insert(0, v_result) reds, greens = self.sort_by_color(varsalive) - self.genop(block, 'save_locals', reds) - self.genop(block, 'yellow_call', op.args) # Void result, like red_call + self.make_call(block, op, reds, 'yellow') resumepoint = self.get_resume_point(nextblock) c_resumepoint = inputconst(lltype.Signed, resumepoint) From pedronis at codespeak.net Thu Sep 21 20:43:21 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Sep 2006 20:43:21 +0200 (CEST) Subject: [pypy-svn] r32569 - pypy/dist/pypy/interpreter Message-ID: <20060921184321.B049710082@code0.codespeak.net> Author: pedronis Date: Thu Sep 21 20:43:19 2006 New Revision: 32569 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: no attrs expected on Wrappable either Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Sep 21 20:43:19 2006 @@ -87,6 +87,8 @@ class Wrappable(W_Root): """A subclass of Wrappable is an internal, interpreter-level class that can nevertheless be exposed at application-level by space.wrap().""" + __slots__ = () + def __spacebind__(self, space): return self From pedronis at codespeak.net Thu Sep 21 20:44:44 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Sep 2006 20:44:44 +0200 (CEST) Subject: [pypy-svn] r32570 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20060921184444.9D58610082@code0.codespeak.net> Author: pedronis Date: Thu Sep 21 20:44:42 2006 New Revision: 32570 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: the optiomisation trying to use singletons for exception without attributes was not checking for attrs in parents in the hierarchy. Fix and test. Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Thu Sep 21 20:44:42 2006 @@ -208,6 +208,12 @@ def __repr__(self): return "" % (self.name,) + def has_no_attrs(self): + for clsdef in self.getmro(): + if clsdef.attrs: + return False + return True + def commonbase(self, other): other1 = other while other is not None and not self.issubclass(other): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Sep 21 20:44:42 2006 @@ -670,7 +670,7 @@ if (isinstance(s_init, annmodel.SomeImpossibleValue) and classdef.classdesc.is_exception_class() and - not classdef.attrs): + classdef.has_no_attrs()): # special case for instanciating simple built-in # exceptions: always return the same prebuilt instance, # and ignore any arguments passed to the contructor. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Thu Sep 21 20:44:42 2006 @@ -1379,6 +1379,28 @@ res = self.interpret(f, []) assert res == 12 + def test_exception_with_non_empty_baseclass(self): + class BE(Exception): + pass + class E1(BE): + pass + class E2(BE): + pass + def f(x): + if x: + e = E1() + else: + e = E2() + witness = E1() + witness.x = 42 + e.x = 3 + return witness.x + + res = self.interpret(f, [0]) + assert res == 42 + res = self.interpret(f, [1]) + assert res == 42 + # We don't care about the following test_hlinvoke tests working on # ootype. Maybe later. This kind of thing is only used in rdict From pedronis at codespeak.net Thu Sep 21 21:12:05 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Sep 2006 21:12:05 +0200 (CEST) Subject: [pypy-svn] r32571 - in pypy/dist/pypy: interpreter interpreter/test objspace/cpy Message-ID: <20060921191205.2448310082@code0.codespeak.net> Author: pedronis Date: Thu Sep 21 21:12:01 2006 New Revision: 32571 Modified: pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/interpreter/test/test_gateway.py pypy/dist/pypy/objspace/cpy/function.py Log: another round of cleanups for gateway and unwrap_spec recipes. I will stop here for now. Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Thu Sep 21 21:12:01 2006 @@ -38,21 +38,13 @@ self.varargname = varargname self.kwargname = kwargname - def next_arg(self): - return self._argiter.next() - def append(self, argname): self.argnames.append(argname) def signature(self): return self.argnames, self.varargname, self.kwargname - def apply_unwrap_spec(self, unwrap_spec, recipe, dest_sig): - self._argiter = iter(self.argnames) - dispatch = recipe.dispatch - for el in unwrap_spec: - dispatch(el, self, dest_sig) - +#________________________________________________________________ class UnwrapSpecRecipe: "NOT_RPYTHON" @@ -74,250 +66,161 @@ raise Exception("%s: no match for unwrap_spec element %s" % ( self.__class__.__name__, el)) + def apply_over(self, unwrap_spec, *extra): + dispatch = self.dispatch + for el in unwrap_spec: + dispatch(el, *extra) + +class UnwrapSpecEmit(UnwrapSpecRecipe): + + def __init__(self): + self.n = 0 + self.miniglobals = {} + + def succ(self): + n = self.n + self.n += 1 + return n + + def use(self, obj): + name = obj.__name__ + self.miniglobals[name] = obj + return name + +#________________________________________________________________ class UnwrapSpec_Check(UnwrapSpecRecipe): # checks for checking interp2app func argument names wrt unwrap_spec # and synthetizing an app-level signature - def visit_function(self, (func, cls), orig_sig, app_sig): - self.dispatch(cls, orig_sig, app_sig) + def __init__(self, original_sig): + self.func = original_sig.func + self.orig_arg = iter(original_sig.argnames).next + self._varargname = original_sig.varargname # XXX + + def visit_function(self, (func, cls), app_sig): + self.dispatch(cls, app_sig) - def visit__Wrappable(self, el, orig_sig, app_sig): + def visit__Wrappable(self, el, app_sig): name = el.__name__ - argname = orig_sig.next_arg() + argname = self.orig_arg() assert not argname.startswith('w_'), ( "unwrapped %s argument %s of built-in function %r should " - "not start with 'w_'" % (name, argname, orig_sig.func)) + "not start with 'w_'" % (name, argname, self.func)) app_sig.append(argname) - def visit__ObjSpace(self, el, orig_sig, app_sig): - orig_sig.next_arg() + def visit__ObjSpace(self, el, app_sig): + self.orig_arg() - def visit__W_Root(self, el, orig_sig, app_sig): + def visit__W_Root(self, el, app_sig): assert el is W_Root, "oops" - argname = orig_sig.next_arg() + argname = self.orig_arg() assert argname.startswith('w_'), ( "argument %s of built-in function %r should " - "start with 'w_'" % (argname, orig_sig.func)) + "start with 'w_'" % (argname, self.func)) app_sig.append(argname[2:]) - def visit__Arguments(self, el, orig_sig, app_sig): - argname = orig_sig.next_arg() + def visit__Arguments(self, el, app_sig): + argname = self.orig_arg() assert app_sig.varargname is None,( - "built-in function %r has conflicting rest args specs" % orig_sig.func) + "built-in function %r has conflicting rest args specs" % self.func) app_sig.varargname = 'args' app_sig.kwargname = 'keywords' - def visit_starargs(self, el, orig_sig, app_sig): - varargname = orig_sig.varargname - assert varargname.endswith('_w'), ( - "argument *%s of built-in function %r should end in '_w'" % - (varargname, orig_sig.func)) - assert app_sig.varargname is None,( - "built-in function %r has conflicting rest args specs" % orig_sig.func) - app_sig.varargname = varargname[:-2] - - def visit_args_w(self, el, orig_sig, app_sig): - argname = orig_sig.next_arg() + def visit_args_w(self, el, app_sig): + argname = self.orig_arg() assert argname.endswith('_w'), ( "rest arguments arg %s of built-in function %r should end in '_w'" % - (argname, orig_sig.func)) + (argname, self.func)) assert app_sig.varargname is None,( - "built-in function %r has conflicting rest args specs" % orig_sig.func) + "built-in function %r has conflicting rest args specs" % self.func) app_sig.varargname = argname[:-2] - def visit_w_args(self, el, orig_sig, app_sig): - argname = orig_sig.next_arg() + def visit_w_args(self, el, app_sig): + argname = self.orig_arg() assert argname.startswith('w_'), ( "rest arguments arg %s of built-in function %r should start 'w_'" % - (argname, orig_sig.func)) + (argname, self.func)) assert app_sig.varargname is None,( - "built-in function %r has conflicting rest args specs" % orig_sig.func) + "built-in function %r has conflicting rest args specs" % self.func) app_sig.varargname = argname[2:] - def visit__object(self, el, orig_sig, app_sig): - if el not in (int, str, float): + def visit__object(self, typ, app_sig): + if typ not in (int, str, float): assert False, "unsupported basic type in unwrap_spec" - name = el.__name__ - argname = orig_sig.next_arg() + argname = self.orig_arg() assert not argname.startswith('w_'), ( "unwrapped %s argument %s of built-in function %r should " - "not start with 'w_'" % (name, argname, orig_sig.func)) + "not start with 'w_'" % (typ.__name__, argname, self.func)) app_sig.append(argname) -class UnwrapSpec_Emit(UnwrapSpecRecipe): +class UnwrapSpec_EmitRun(UnwrapSpecEmit): # collect code to emit for interp2app builtin frames based on unwrap_spec - def visit_function(self, (func, cls), orig_sig, emit_sig): - name = func.__name__ - cur = emit_sig.through_scope_w - emit_sig.setfastscope.append( - "obj = %s(scope_w[%d])" % (name, cur)) - emit_sig.miniglobals[name] = func - emit_sig.setfastscope.append( - "%s_arg%d = obj" % (name,cur)) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("%s_arg%d" % (name,cur)) - - def visit__Wrappable(self, el, orig_sig, emit_sig): - name = el.__name__ - cur = emit_sig.through_scope_w - emit_sig.setfastscope.append( - "obj = space.interp_w(%s, scope_w[%d])" % (name, cur)) - emit_sig.miniglobals[name] = el - emit_sig.setfastscope.append( - "%s_arg%d = obj" % (name,cur)) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("%s_arg%d" % (name,cur)) - - def visit__ObjSpace(self, el, orig_sig, emit_sig): - emit_sig.run_args.append('space') - - def visit__W_Root(self, el, orig_sig, emit_sig): - cur = emit_sig.through_scope_w - emit_sig.setfastscope.append( - "w_arg%d = scope_w[%d]" % (cur,cur)) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("w_arg%d" % cur) - - def visit__Arguments(self, el, orig_sig, emit_sig): - cur = emit_sig.through_scope_w - emit_sig.through_scope_w += 2 - emit_sig.miniglobals['Arguments'] = Arguments - emit_sig.setfastscope.append( - "arguments_arg = " - "Arguments.frompacked(space,scope_w[%d],scope_w[%d])" - % (cur, cur+1)) - emit_sig.run_args.append("arguments_arg") - - def visit_starargs(self, el, orig_sig, emit_sig): - emit_sig.setfastscope.append( - "starargs_arg_w = space.unpacktuple(scope_w[%d])" % - (emit_sig.through_scope_w)) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("*starargs_arg_w") - - def visit_args_w(self, el, orig_sig, emit_sig): - emit_sig.setfastscope.append( - "args_w = space.unpacktuple(scope_w[%d])" % - (emit_sig.through_scope_w)) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("args_w") - - def visit_w_args(self, el, orig_sig, emit_sig): - cur = emit_sig.through_scope_w - emit_sig.setfastscope.append( - "w_args = scope_w[%d]" % cur) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("w_args") - - def visit__object(self, el, orig_sig, emit_sig): - if el not in (int, str, float): - assert False, "unsupported basic type in uwnrap_spec" - name = el.__name__ - cur = emit_sig.through_scope_w - emit_sig.setfastscope.append( - "%s_arg%d = space.%s_w(scope_w[%d])" % - (name,cur,name,cur)) - emit_sig.through_scope_w += 1 - emit_sig.run_args.append("%s_arg%d" % (name,cur)) - - -class UnwrapSpec_FastFunc_Unwrap(UnwrapSpecRecipe): + def __init__(self): + UnwrapSpecEmit.__init__(self) + self.run_args = [] - def visit_function(self, (func, cls), info): - raise FastFuncNotSupported + def scopenext(self): + return "scope_w[%d]" % self.succ() + + def visit_function(self, (func, cls)): + self.run_args.append("%s(%s)" % (self.use(func), + self.scopenext())) - def visit__Wrappable(self, el, info): - name = el.__name__ - cur = info.narg - info.unwrap.append("space.interp_w(%s, w%d)" % (name, cur)) - info.miniglobals[name] = el - info.narg += 1 + def visit__Wrappable(self, typ): + self.run_args.append("space.interp_w(%s, %s)" % (self.use(typ), + self.scopenext())) - def visit__ObjSpace(self, el, info): - if info.index != 0: - raise FastFuncNotSupported - info.unwrap.append("space") - - def visit__W_Root(self, el, info): - cur = info.narg - info.unwrap.append("w%d" % cur) - info.narg += 1 + def visit__ObjSpace(self, el): + self.run_args.append('space') - def visit__Arguments(self, el, info): - raise FastFuncNotSupported + def visit__W_Root(self, el): + self.run_args.append(self.scopenext()) - def visit_starargs(self, el, info): - raise FastFuncNotSupported + def visit__Arguments(self, el): + self.miniglobals['Arguments'] = Arguments + self.run_args.append("Arguments.frompacked(space, %s, %s)" + % (self.scopenext(), self.scopenext())) - def visit_args_w(self, el, info): - raise FastFuncNotSupported + def visit_args_w(self, el): + self.run_args.append("space.unpacktuple(%s)" % self.scopenext()) - def visit_w_args(self, el, info): - raise FastFuncNotSupported + def visit_w_args(self, el): + self.run_args.append(self.scopenext()) - def visit__object(self, el, info): - if el not in (int, str, float): + def visit__object(self, typ): + if typ not in (int, str, float): assert False, "unsupported basic type in uwnrap_spec" - name = el.__name__ - cur = info.narg - info.unwrap.append("space.%s_w(w%d)" % (name,cur)) - info.narg +=1 - - -class BuiltinActivation(object): - - def __init__(self, behavior): - """NOT_RPYTHON""" - self.behavior = behavior - - def _run(self, space, scope_w): - """Subclasses with behavior specific for an unwrap spec are generated""" - raise TypeError, "abstract" - -class BuiltinCodeSignature(Signature): - "NOT_RPYTHON" - - def __init__(self,*args,**kwds): - self.unwrap_spec = kwds.get('unwrap_spec') - del kwds['unwrap_spec'] - Signature.__init__(self,*args,**kwds) - self.setfastscope = [] - self.run_args = [] - self.through_scope_w = 0 - self.miniglobals = {} + self.run_args.append("space.%s_w(%s)" % + (typ.__name__, self.scopenext())) - def _make_unwrap_activation_class(self, cache={}): + def _make_unwrap_activation_class(self, unwrap_spec, cache={}): try: - key = tuple(self.unwrap_spec) + key = tuple(unwrap_spec) activation_factory_cls, run_args = cache[key] - assert run_args == self.run_args,"unexpected: same spec, different run_args" + assert run_args == self.run_args, ( + "unexpected: same spec, different run_args") return activation_factory_cls except KeyError: parts = [] - for el in self.unwrap_spec: + for el in unwrap_spec: if isinstance(el, tuple): - parts.append(''.join([getattr(subel, '__name__', subel) for subel in el])) + parts.append(''.join([getattr(subel, '__name__', subel) + for subel in el])) else: parts.append(getattr(el, '__name__', el)) label = '_'.join(parts) #print label - setfastscope = self.setfastscope - if not setfastscope: - setfastscope = ["pass"] - setfastscope = '\n '.join(setfastscope) # xxx indentation below - d = {} source = """if 1: def _run_UWS_%s(self, space, scope_w): - %s return self.behavior(%s) - \n""" % (label, setfastscope, ','.join(self.run_args)) + \n""" % (label, ', '.join(self.run_args)) exec compile2(source) in self.miniglobals, d d['_run'] = d['_run_UWS_%s' % label] del d['_run_UWS_%s' % label] @@ -328,57 +231,106 @@ cache[key] = activation_cls, self.run_args return activation_cls - def make_activation(self, func): - activation_uw_cls = self._make_unwrap_activation_class() + @staticmethod + def make_activation(unwrap_spec, func): + emit = UnwrapSpec_EmitRun() + emit.apply_over(unwrap_spec) + activation_uw_cls = emit._make_unwrap_activation_class(unwrap_spec) return activation_uw_cls(func) - -def make_builtin_activation(func, orig_sig, unwrap_spec): - "NOT_RPYTHON" - name = (getattr(func, '__module__', None) or '')+'_'+func.__name__ - emit_sig = BuiltinCodeSignature(name=name, unwrap_spec=unwrap_spec) - orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Emit(), - dest_sig = emit_sig) - return emit_sig.make_activation(func) + + +class BuiltinActivation(object): + + def __init__(self, behavior): + """NOT_RPYTHON""" + self.behavior = behavior + + def _run(self, space, scope_w): + """Subclasses with behavior specific for an unwrap spec are generated""" + raise TypeError, "abstract" + +#________________________________________________________________ class FastFuncNotSupported(Exception): pass -class FastFuncInfo(object): +class UnwrapSpec_FastFunc_Unwrap(UnwrapSpecEmit): + def __init__(self): - self.index = 0 - self.narg = 0 + UnwrapSpecEmit.__init__(self) + self.args = [] self.unwrap = [] - self.miniglobals = {} + self.finger = 0 -def make_fastfunc(func, unwrap_spec): - info = FastFuncInfo() - recipe = UnwrapSpec_FastFunc_Unwrap().dispatch - for el in unwrap_spec: - recipe(el, info) - info.index += 1 - if info.narg > 4: + def dispatch(self, el, *args): + UnwrapSpecEmit.dispatch(self, el, *args) + self.finger += 1 + if self.n > 4: raise FastFuncNotSupported - args = ['space'] + ['w%d' % n for n in range(info.narg)] - if args == info.unwrap: - fastfunc = func - else: - # try to avoid excessive bloat - if func.__module__ == 'pypy.interpreter.astcompiler.ast': + + def nextarg(self): + arg = "w%d" % self.succ() + self.args.append(arg) + return arg + + def visit_function(self, (func, cls)): + raise FastFuncNotSupported + + def visit__Wrappable(self, typ): + self.unwrap.append("space.interp_w(%s, %s)" % (self.use(typ), + self.nextarg())) + + def visit__ObjSpace(self, el): + if self.finger != 0: raise FastFuncNotSupported - if (not func.__module__.startswith('pypy.module.__builtin__') and - not func.__module__.startswith('pypy.module.sys') and - not func.__module__.startswith('pypy.module.math')): - if not func.__name__.startswith('descr'): + self.unwrap.append("space") + + def visit__W_Root(self, el): + self.unwrap.append(self.nextarg()) + + def visit__Arguments(self, el): + raise FastFuncNotSupported + + def visit_args_w(self, el): + raise FastFuncNotSupported + + def visit_w_args(self, el): + raise FastFuncNotSupported + + def visit__object(self, typ): + if typ not in (int, str, float): + assert False, "unsupported basic type in uwnrap_spec" + self.unwrap.append("space.%s_w(%s)" % (typ.__name__, + self.nextarg())) + + @staticmethod + def make_fastfunc(unwrap_spec, func): + unwrap_info = UnwrapSpec_FastFunc_Unwrap() + unwrap_info.apply_over(unwrap_spec) + narg = unwrap_info.n + args = ['space'] + unwrap_info.args + if args == unwrap_info.unwrap: + fastfunc = func + else: + # try to avoid excessive bloat + if func.__module__ == 'pypy.interpreter.astcompiler.ast': raise FastFuncNotSupported - d = {} - info.miniglobals['func'] = func - source = """if 1: - def fastfunc_%s_%d(%s): - return func(%s) - \n""" % (func.__name__, info.narg, ', '.join(args), ', '.join(info.unwrap)) - exec compile2(source) in info.miniglobals, d - fastfunc = d['fastfunc_%s_%d' % (func.__name__, info.narg)] - return info.narg, fastfunc + if (not func.__module__.startswith('pypy.module.__builtin__') and + not func.__module__.startswith('pypy.module.sys') and + not func.__module__.startswith('pypy.module.math')): + if not func.__name__.startswith('descr'): + raise FastFuncNotSupported + d = {} + unwrap_info.miniglobals['func'] = func + source = """if 1: + def fastfunc_%s_%d(%s): + return func(%s) + \n""" % (func.__name__, narg, + ', '.join(args), + ', '.join(unwrap_info.unwrap)) + exec compile2(source) in unwrap_info.miniglobals, d + fastfunc = d['fastfunc_%s_%d' % (func.__name__, narg)] + return narg, fastfunc class BuiltinCode(eval.Code): "The code object implementing a built-in (interpreter-level) hook." @@ -427,11 +379,11 @@ unwrap_spec[0] = self_type orig_sig = Signature(func, argnames, varargname, kwargname) - app_sig = Signature(func) - orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpec_Check(), - dest_sig = app_sig) + UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, + app_sig #to populate + ) self.sig = argnames, varargname, kwargname = app_sig.signature() self.minargs = len(argnames) @@ -440,14 +392,15 @@ else: self.maxargs = self.minargs - self.activation = make_builtin_activation(func, orig_sig, unwrap_spec) + self.activation = UnwrapSpec_EmitRun.make_activation(unwrap_spec, func) self._bltin = func self._unwrap_spec = unwrap_spec # speed hack if 0 <= len(unwrap_spec) <= 5: try: - arity, fastfunc = make_fastfunc(func, unwrap_spec) + arity, fastfunc = UnwrapSpec_FastFunc_Unwrap.make_fastfunc( + unwrap_spec, func) except FastFuncNotSupported: if unwrap_spec == [ObjSpace, Arguments]: self.__class__ = BuiltinCodePassThroughArguments0 Modified: pypy/dist/pypy/interpreter/test/test_gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_gateway.py (original) +++ pypy/dist/pypy/interpreter/test/test_gateway.py Thu Sep 21 21:12:01 2006 @@ -14,12 +14,12 @@ class TestBuiltinCode: def test_signature(self): - def c(space, w_x, w_y, *hello_w): + def c(space, w_x, w_y, hello_w): pass code = gateway.BuiltinCode(c, unwrap_spec=[gateway.ObjSpace, gateway.W_Root, gateway.W_Root, - 'starargs']) + 'args_w']) assert code.signature() == (['x', 'y'], 'hello', None) def d(self, w_boo): pass @@ -35,7 +35,7 @@ assert code.signature() == (['x', 'y'], 'args', 'keywords') def test_call(self): - def c(space, w_x, w_y, *hello_w): + def c(space, w_x, w_y, hello_w): u = space.unwrap w = space.wrap assert len(hello_w) == 2 @@ -45,7 +45,7 @@ code = gateway.BuiltinCode(c, unwrap_spec=[gateway.ObjSpace, gateway.W_Root, gateway.W_Root, - 'starargs']) + 'args_w']) w = self.space.wrap args = argument.Arguments(self.space, [w(123), w(23), w(0), w(True)]) w_result = code.funcrun(FakeFunc(self.space, "c"), args) Modified: pypy/dist/pypy/objspace/cpy/function.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/function.py (original) +++ pypy/dist/pypy/objspace/cpy/function.py Thu Sep 21 21:12:01 2006 @@ -16,66 +16,63 @@ class UnwrapSpec_Trampoline(UnwrapSpecRecipe): - def visit__ObjSpace(self, el, orig_sig, tramp): - argname = orig_sig.next_arg() + def __init__(self, original_sig): + self.orig_arg = iter(original_sig.argnames).next + self.inputargs = [] + self.wrappings = [] + self.passedargs = [] + self.miniglobals = {} + self.star_arg = False + + def visit__ObjSpace(self, el): + argname = self.orig_arg() assert argname == 'space' - tramp.passedargs.append('___space') + self.passedargs.append('___space') - def visit__W_Root(self, el, orig_sig, tramp): - argname = orig_sig.next_arg() + def visit__W_Root(self, el): + argname = self.orig_arg() assert argname.startswith('w_') basename = argname[2:] - tramp.inputargs.append(basename) - tramp.wrappings.append('%s = ___W_Object(%s)' % (argname, basename)) - tramp.passedargs.append(argname) + self.inputargs.append(basename) + self.wrappings.append('%s = ___W_Object(%s)' % (argname, basename)) + self.passedargs.append(argname) - def visit__Wrappable(self, el, orig_sig, tramp): + def visit__Wrappable(self, el): clsname = el.__name__ # XXX name clashes, but in gateway.py too - tramp.miniglobals[clsname] = el - argname = orig_sig.next_arg() + self.miniglobals[clsname] = el + argname = self.orig_arg() assert not argname.startswith('w_') - tramp.inputargs.append(argname) - tramp.wrappings.append('%s = ___space.interp_w(%s, ___W_Object(%s))' + self.inputargs.append(argname) + self.wrappings.append('%s = ___space.interp_w(%s, ___W_Object(%s))' % (argname, clsname, argname)) - tramp.passedargs.append(argname) + self.passedargs.append(argname) - def visit__object(self, el, orig_sig, tramp): + def visit__object(self, el): convertermap = {int: 'int_w', str: 'str_w', float: 'float_w'} - argname = orig_sig.next_arg() + argname = self.orig_arg() assert not argname.startswith('w_') - tramp.inputargs.append(argname) - tramp.wrappings.append('%s = ___space.%s(___W_Object(%s))' % + self.inputargs.append(argname) + self.wrappings.append('%s = ___space.%s(___W_Object(%s))' % (argname, convertermap[el], argname)) - tramp.passedargs.append(argname) + self.passedargs.append(argname) - def visit_args_w(self, el, orig_sig, tramp): - argname = orig_sig.next_arg() + def visit_args_w(self, el): + argname = self.orig_arg() assert argname.endswith('_w') basename = argname[:-2] - tramp.inputargs.append('*' + basename) - tramp.wrappings.append('%s = []' % (argname,)) - tramp.wrappings.append('for ___i in range(len(%s)):' % (basename,)) - tramp.wrappings.append(' %s.append(___W_Object(%s[___i]))' % ( + self.inputargs.append('*' + basename) + self.wrappings.append('%s = []' % (argname,)) + self.wrappings.append('for ___i in range(len(%s)):' % (basename,)) + self.wrappings.append(' %s.append(___W_Object(%s[___i]))' % ( argname, basename)) - tramp.passedargs.append(argname) - tramp.star_arg = True - - -class TrampolineSignature(object): - - def __init__(self): - self.inputargs = [] - self.wrappings = [] - self.passedargs = [] - self.miniglobals = {} - self.star_arg = False - + self.passedargs.append(argname) + self.star_arg = True def reraise(e): w_type = e.w_type @@ -102,7 +99,7 @@ bltin.func_code) orig_sig = Signature(bltin, argnames, varargname, kwargname) - tramp = TrampolineSignature() + tramp = UnwrapSpec_Trampoline(orig_sig) tramp.miniglobals = { '___space': space, '___W_Object': CPyObjSpace.W_Object, @@ -110,9 +107,7 @@ '___OperationError': OperationError, '___reraise': reraise, } - orig_sig.apply_unwrap_spec(unwrap_spec, - UnwrapSpec_Trampoline(), - dest_sig = tramp) + tramp.apply_over(unwrap_spec) sourcelines = ['def trampoline(%s):' % (', '.join(tramp.inputargs),)] # this description is to aid viewing in graphviewer From pedronis at codespeak.net Thu Sep 21 21:16:15 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Sep 2006 21:16:15 +0200 (CEST) Subject: [pypy-svn] r32572 - pypy/dist/pypy/interpreter Message-ID: <20060921191615.5AAB710082@code0.codespeak.net> Author: pedronis Date: Thu Sep 21 21:16:14 2006 New Revision: 32572 Modified: pypy/dist/pypy/interpreter/gateway.py Log: this line is no longer necessary Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Thu Sep 21 21:16:14 2006 @@ -97,7 +97,6 @@ def __init__(self, original_sig): self.func = original_sig.func self.orig_arg = iter(original_sig.argnames).next - self._varargname = original_sig.varargname # XXX def visit_function(self, (func, cls), app_sig): self.dispatch(cls, app_sig) From arigo at codespeak.net Fri Sep 22 13:00:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 13:00:19 +0200 (CEST) Subject: [pypy-svn] r32573 - in pypy/dist/pypy: jit/hintannotator/test jit/timeshifter jit/timeshifter/test rpython/lltypesystem translator Message-ID: <20060922110019.E331810063@code0.codespeak.net> Author: arigo Date: Fri Sep 22 13:00:15 2006 New Revision: 32573 Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/transform.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/translator/simplify.py Log: (arre, arigo) * added the immutable hint to the 'typeptr' part of all instance objects. * jit green calls: check for side-effects. * made test_simple_method pass, for now by assuming that in all indirect calls the red box containing the function pointer is actually a compile-time constant. Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Fri Sep 22 13:00:15 2006 @@ -556,14 +556,14 @@ def test_simple_meth(): class Base(object): - def m(self): raise NotImplementedError + pass # for inspect.getsource() bugs class Concrete(Base): - def m(self): return 42 + pass # for inspect.getsource() bugs def f(flag): if flag: Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Fri Sep 22 13:00:15 2006 @@ -912,6 +912,18 @@ assert res == 23 self.check_insns({'int_gt': 1}) + def test_green_with_side_effects(self): + S = lltype.GcStruct('S', ('flag', lltype.Bool)) + s = lltype.malloc(S) + def ll_set_flag(s): + s.flag = True + def ll_function(): + s.flag = False + ll_set_flag(s) + return s.flag + res = self.timeshift(ll_function, [], []) + assert res is True + self.check_insns({'setfield': 2, 'getfield': 1}) def test_recursive_call(self): def ll_pseudo_factorial(n, fudge): @@ -1006,3 +1018,25 @@ res = self.timeshift(f, [True, -1000], [0]) assert res == f(True, -1000) self.check_insns({'int_ge': 2, 'int_add': 1}) + + def test_simple_meth(self): + class Base(object): + def m(self): + raise NotImplementedError + pass # for inspect.getsource() bugs + + class Concrete(Base): + def m(self): + return 42 + pass # for inspect.getsource() bugs + + def f(flag): + if flag: + o = Base() + else: + o = Concrete() + return o.m() + + res = self.timeshift(f, [False], [0], policy=P_NOVIRTUAL) + assert res == 42 + self.check_insns({}) Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Fri Sep 22 13:00:15 2006 @@ -7,6 +7,7 @@ from pypy.rpython.rmodel import inputconst from pypy.translator.unsimplify import varoftype, copyvar from pypy.translator.unsimplify import split_block, split_block_at_start +from pypy.translator.simplify import rec_op_has_side_effects from pypy.translator.backendopt.ssa import SSA_to_SSI from pypy.translator.backendopt import support @@ -338,8 +339,11 @@ else: hs_res = self.hannotator.binding(spaceop.result) if hs_res.is_green(): - # all-green arguments and result - return 'green' + # all-green arguments and result. + # Does the function have side-effects? + t = self.hannotator.base_translator + if not rec_op_has_side_effects(t, spaceop): + return 'green' colors = {} for graph, tsgraph in self.graphs_from(spaceop): color = self.graph_calling_color(tsgraph) @@ -367,8 +371,14 @@ # but only has the hidden side-effect of putting it in the jitstate else: c_targets = inputconst(lltype.Void, targets) - self.genop(block, 'indirect_%s_call' % (color,), - op.args[:-1] + [c_targets]) + args_v = op.args[:-1] + [c_targets] + hs_func = self.hannotator.binding(args_v[0]) + if not hs_func.is_green(): + # XXX for now, assume that it will be a constant red box + v_greenfunc = self.genop(block, 'revealconst', [args_v[0]], + result_type = originalconcretetype(hs_func)) + args_v[0] = v_greenfunc + self.genop(block, 'indirect_%s_call' % (color,), args_v) def handle_red_call(self, block, pos, color='red'): # the 'save_locals' pseudo-operation is used to save all @@ -425,9 +435,25 @@ op.opname = 'green_call' def handle_yellow_call(self, block, pos): + op = block.operations[pos] + hs_result = self.hannotator.binding(op.result) + if not hs_result.is_green(): + # yellow calls are supposed to return greens, + # add an indirection if it's not the case + # XXX a bit strange + RESULT = originalconcretetype(hs_result) + v_tmp = varoftype(RESULT) + hs = hintmodel.SomeLLAbstractConstant(RESULT, {}) + self.hannotator.setbinding(v_tmp, hs) + v_real_result = op.result + op.result = v_tmp + newop = SpaceOperation('same_as', [v_tmp], v_real_result) + block.operations.insert(pos+1, newop) + link = support.split_block_with_keepalive(block, pos+1, annotator=self.hannotator) - op = block.operations.pop(pos) + op1 = block.operations.pop(pos) + assert op1 is op assert len(block.operations) == pos nextblock = link.target varsalive = link.args Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri Sep 22 13:00:15 2006 @@ -57,7 +57,8 @@ OBJECT_VTABLE = lltype.ForwardReference() CLASSTYPE = Ptr(OBJECT_VTABLE) -OBJECT = GcStruct('object', ('typeptr', CLASSTYPE)) +OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), + hints = {'immutable': True}) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', CLASSTYPE), Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Fri Sep 22 13:00:15 2006 @@ -406,23 +406,27 @@ if block is graph.exceptblock: return False # graphs explicitly raising have side-effects for op in block.operations: - if op.opname == "direct_call": - g = get_graph(op.args[0], translator) - if g is None: - return False - if not has_no_side_effects(translator, g, newseen): - return False - elif op.opname == "indirect_call": - graphs = op.args[-1].value - if graphs is None: - return False - for g in graphs: - if not has_no_side_effects(translator, g, newseen): - return False - elif op_has_side_effects(op): + if rec_op_has_side_effects(translator, op, newseen): return False return True +def rec_op_has_side_effects(translator, op, seen=None): + if op.opname == "direct_call": + g = get_graph(op.args[0], translator) + if g is None: + return True + if not has_no_side_effects(translator, g, seen): + return True + elif op.opname == "indirect_call": + graphs = op.args[-1].value + if graphs is None: + return True + for g in graphs: + if not has_no_side_effects(translator, g, seen): + return True + else: + return op_has_side_effects(op) + # ___________________________________________________________________________ # remove operations if their result is not used and they have no side effects From arigo at codespeak.net Fri Sep 22 13:49:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 13:49:55 +0200 (CEST) Subject: [pypy-svn] r32576 - in pypy/dist/pypy: annotation annotation/test translator/test Message-ID: <20060922114955.C3F0810070@code0.codespeak.net> Author: arigo Date: Fri Sep 22 13:49:53 2006 New Revision: 32576 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/translator/test/snippet.py Log: (arre, arigo) Annotator fix for prebuilt instances of classes with __slots__. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Sep 22 13:49:53 2006 @@ -614,7 +614,7 @@ self.seen_mutable[x] = True self.event('mutable', x) source = InstanceSource(self, x) - for attr in x.__dict__: + for attr in source.all_instance_attributes(): clsdef.add_source_for_attribute(attr, source) # can trigger reflowing def valueoftype(self, t): Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Fri Sep 22 13:49:53 2006 @@ -413,10 +413,22 @@ self.obj = obj def s_get_value(self, classdef, name): - s_value = self.bookkeeper.immutablevalue( - self.obj.__dict__[name]) + s_value = self.bookkeeper.immutablevalue(getattr(self.obj, name)) return s_value + def all_instance_attributes(self): + result = getattr(self.obj, '__dict__', {}).keys() + tp = self.obj.__class__ + if isinstance(tp, type): + for basetype in tp.__mro__: + slots = basetype.__dict__.get('__slots__') + if slots: + if isinstance(slots, str): + result.append(slots) + else: + result.extend(slots) + return result + class NoSuchSlotError(Exception): "Raised when an attribute is found on a class where __slots__ forbits it." Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Fri Sep 22 13:49:53 2006 @@ -373,6 +373,12 @@ assert s == annmodel.SomeInteger(nonneg=True) #self.assertEquals(s.__class__, annmodel.SomeInteger) + def test_pbc_attr_preserved_on_instance_with_slots(self): + a = self.RPythonAnnotator() + s = a.build_types(snippet.preserve_pbc_attr_on_instance_with_slots, + [bool]) + assert s == annmodel.SomeInteger(nonneg=True) + def test_is_and_knowntype_data(self): a = self.RPythonAnnotator() s = a.build_types(snippet.is_and_knowntype, [str]) Modified: pypy/dist/pypy/translator/test/snippet.py ============================================================================== --- pypy/dist/pypy/translator/test/snippet.py (original) +++ pypy/dist/pypy/translator/test/snippet.py Fri Sep 22 13:49:53 2006 @@ -715,6 +715,22 @@ return x.answer +class APBCS(object): + __slots__ = ['answer'] + def __init__(self): + self.answer = 42 + +apbcs = APBCS() +apbcs.answer = 7 + +def preserve_pbc_attr_on_instance_with_slots(cond): + if cond: + x = APBCS() + else: + x = apbcs + return x.answer + + def is_and_knowntype(x): if x is None: return x From mwh at codespeak.net Fri Sep 22 15:00:30 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Sep 2006 15:00:30 +0200 (CEST) Subject: [pypy-svn] r32577 - in pypy/branch/kill-keepalives/pypy: objspace/flow rpython rpython/lltypesystem rpython/memory translator/backendopt translator/c Message-ID: <20060922130030.D18F01006E@code0.codespeak.net> Author: mwh Date: Fri Sep 22 15:00:25 2006 New Revision: 32577 Modified: pypy/branch/kill-keepalives/pypy/objspace/flow/model.py pypy/branch/kill-keepalives/pypy/rpython/llinterp.py pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Log: yet another and apparently working go at malloc removal of things with autofree_fields. this took an obscenely long time to get right. Modified: pypy/branch/kill-keepalives/pypy/objspace/flow/model.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/objspace/flow/model.py (original) +++ pypy/branch/kill-keepalives/pypy/objspace/flow/model.py Fri Sep 22 15:00:25 2006 @@ -42,7 +42,7 @@ class FunctionGraph(object): - __slots__ = ['startblock', 'returnblock', 'exceptblock', '__dict__'] + __slots__ = ['startblock', 'returnblock', 'exceptblock', '__dict__', 'needs_more_malloc_removal'] def __init__(self, name, startblock, return_var=None): self.name = name # function name (possibly mangled already) @@ -57,6 +57,7 @@ Variable('evalue')]) # exception value self.exceptblock.operations = () self.exceptblock.exits = () + self.needs_more_malloc_removal = False def getargs(self): return self.startblock.inputargs Modified: pypy/branch/kill-keepalives/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/llinterp.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/llinterp.py Fri Sep 22 15:00:25 2006 @@ -171,7 +171,6 @@ self.curr_block = None self.curr_operation_index = 0 self.alloca_objects = [] - self.local_mallocs = [] # _______________________________________________________ # variable setters/getters helpers @@ -245,8 +244,6 @@ for obj in self.alloca_objects: #XXX slighly unclean obj._setobj(None) - for adr in self.local_mallocs: - self.heap.raw_free(adr) return args finally: if tracer: @@ -511,6 +508,7 @@ setattr(obj, finalfield, fieldvalue) else: obj[finalfield] = fieldvalue + op_bare_setinteriorfield = op_setinteriorfield def op_getarrayitem(self, array, index): return array[index] @@ -526,7 +524,7 @@ args = gc.get_arg_write_barrier(array, index, item) write_barrier = gc.get_funcptr_write_barrier() self.op_direct_call(write_barrier, *args) - + op_bare_setarrayitem = op_setarrayitem def perform_call(self, f, ARGS, args): fobj = self.llinterpreter.typer.type_system.deref(f) @@ -751,11 +749,6 @@ assert lltype.typeOf(value) == typ getattr(addr, str(typ).lower())[offset] = value - def op_local_raw_malloc(self, size): - r = self.heap.raw_malloc(size) - self.local_mallocs.append(r) - return r - # ____________________________________________________________ # Overflow-detecting variants Modified: pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/lltypesystem/lloperation.py Fri Sep 22 15:00:25 2006 @@ -329,7 +329,6 @@ # __________ address operations __________ 'raw_malloc': LLOp(canraise=(MemoryError,)), - 'local_raw_malloc': LLOp(canraise=(MemoryError,)), 'raw_malloc_usage': LLOp(sideeffects=False), 'raw_free': LLOp(), 'raw_memclear': LLOp(), Modified: pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py (original) +++ pypy/branch/kill-keepalives/pypy/rpython/memory/gctransform.py Fri Sep 22 15:00:25 2006 @@ -81,7 +81,6 @@ return self.seen_graphs[graph] = True self.links_to_split = {} # link -> vars to pop_alive across the link - self.seen_local_raw_malloc = False # for sanity, we need an empty block at the start of the graph if not starts_with_empty_block(graph): @@ -108,68 +107,12 @@ if starts_with_empty_block(graph): remove_empty_startblock(graph) - if self.seen_local_raw_malloc: - self.remove_local_mallocs(graph) - self.links_to_split = None v = Variable('vanishing_exc_value') v.concretetype = self.get_lltype_of_exception_value() graph.exc_cleanup = (v, self.pop_alive(v)) return is_borrowed # xxx for tests only - def remove_local_mallocs(self, graph): - from pypy.translator.backendopt.malloc import compute_lifetimes - lifetimes = compute_lifetimes(graph) - for info in lifetimes: - cand = True - # XXX do checking - for cp in info.creationpoints: - if cp[0] != "op": - cand = False - break - op = cp[2] - if op.opname != 'local_raw_malloc': - cand = False - break - op.opname = 'raw_malloc' - if cand: - for cp in info.creationpoints: - cp[2].opname = 'raw_malloc' - - variables_by_block = {} - for block, var in info.variables: - vars = variables_by_block.setdefault(block, set()) - vars.add(var) - for block, vars in variables_by_block.iteritems(): - links_with_a_var = [] - links_without_a_var = [] - for link in block.exits: - if vars & set(link.args): - links_with_a_var.append(link) - else: - links_without_a_var.append(link) - #if not links_without_a_var: - # continue - for link in links_without_a_var: - vv = iter(vars).next() - for v in vars: - assert v not in link.args - if v.concretetype == llmemory.Address: - vv = v - newblock = insert_empty_block(None, link) - link.args.append(vv) - newblock.inputargs.append(copyvar(None, vv)) - if vv.concretetype != llmemory.Address: - newv = varoftype(llmemory.Address) - newblock.operations.append(SpaceOperation( - "cast_ptr_to_adr", [newblock.inputargs[-1]], newv)) - vv = newv - else: - vv = newblock.inputargs[-1] - newblock.operations.append(SpaceOperation( - "raw_free", [vv], varoftype(lltype.Void))) - checkgraph(graph) - def compute_borrowed_vars(self, graph): # the input args are borrowed, and stay borrowed for as long as they # are not merged with other values. @@ -328,10 +271,6 @@ replace_setinteriorfield = replace_setfield replace_setarrayitem = replace_setfield - def replace_local_raw_malloc(self, op, livevars, block): - self.seen_local_raw_malloc = True - return [op] - def replace_safe_call(self, op, livevars, block): return [SpaceOperation("direct_call", op.args, op.result)] Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Fri Sep 22 15:00:25 2006 @@ -1,9 +1,9 @@ from pypy.objspace.flow.model import Variable, Constant, Block, Link -from pypy.objspace.flow.model import SpaceOperation, traverse +from pypy.objspace.flow.model import SpaceOperation, traverse, checkgraph from pypy.tool.algo.unionfind import UnionFind from pypy.rpython.lltypesystem import lltype -from pypy.translator.simplify import remove_identical_vars -from pypy.translator.unsimplify import varoftype +from pypy.translator.simplify import remove_identical_vars, join_blocks +from pypy.translator.unsimplify import varoftype, insert_empty_block, copyvar from pypy.translator.backendopt.support import log from pypy.translator.backendopt.constfold import constant_fold_graph @@ -87,7 +87,7 @@ def visit(node): if isinstance(node, Block): for op in node.operations: - if op.opname in ("same_as", "cast_pointer", "cast_adr_to_ptr"): + if op.opname in ("same_as", "cast_pointer"): # special-case these operations to identify their input # and output variables union(node, op.args[0], node, op.result) @@ -128,7 +128,7 @@ traverse(visit, graph) return lifetimes.infos() -def _try_inline_malloc(info): +def _try_inline_malloc(graph, info, links_to_split, remove_autofrees=False): """Try to inline the mallocs creation and manipulation of the Variables in the given LifeTime.""" # the values must be only ever created by a "malloc" @@ -220,18 +220,29 @@ try: destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr - if destr_ptr and 'autofree_fields' not in STRUCT._hints: - return False - fields_to_raw_free = STRUCT._hints['autofree_fields'] + if destr_ptr: + if 'autofree_fields' in STRUCT._hints: + if remove_autofrees: + fields_to_raw_free = STRUCT._hints['autofree_fields'] + assert len(info.creationpoints) == 1 + else: + graph.needs_more_malloc_removal = True + return False + else: + return False except (ValueError, AttributeError), e: pass + assert not fields_to_raw_free or remove_autofrees + # must not remove unions inlined as the only field of a GcStruct if union_wrapper(STRUCT): return False # success: replace each variable with a family of variables (one per field) + # print 'removing malloc of', STRUCT, fields_to_raw_free + # 'flatnames' is a list of (STRUCTTYPE, fieldname_in_that_struct) that # describes the list of variables that should replace the single # malloc'ed pointer variable that we are about to remove. For primitive @@ -306,6 +317,16 @@ for block, vars in variables_by_block.items(): + links_without_vars = [] + + if fields_to_raw_free: + for link in block.exits: + if not set(link.args) & set(vars): + links_without_vars.append(link) +## print "link hasn't var", link, 'args:', link.args, 'vars', vars +## print [(c, c.concretetype) for c in link.args] +## print [(c, c.concretetype) for c in vars] + def flowin(var, newvarsmap, insert_keepalive=False): # in this 'block', follow where the 'var' goes to and replace # it by a flattened-out family of variables. This family is given @@ -341,15 +362,6 @@ S = op.args[0].concretetype.TO fldnames = [a.value for a in op.args[1:-1]] key = key_for_field_access(S, *fldnames) - if len(fldnames) == 1 and fldnames[0] in fields_to_raw_free and not isinstance(op.args[2], Constant): - # find the raw malloc and replace it with a local_raw_malloc - # XXX delicate in the extreme! - i = -1 - while newops[i].opname != 'raw_malloc': - i -= 1 - newops[i] = SpaceOperation("local_raw_malloc", - newops[i].args, - newops[i].result) assert key in newvarsmap if key in accessed_substructs: c_name = Constant('data', lltype.Void) @@ -423,28 +435,22 @@ count[0] += progress else: newops.append(op) +## if newops[-1:] != [op] and remove_autofrees: +## newops.append(SpaceOperation("debug_print", [Constant(str(op), lltype.Void)], varoftype(lltype.Void))) assert block.exitswitch not in vars - var_exits = False for link in block.exits: newargs = [] + oldargs = link.args[:] for arg in link.args: if arg in vars: newargs += list_newvars() insert_keepalive = False # kept alive by the link - var_exits = True else: newargs.append(arg) link.args[:] = newargs -## if not var_exits: -## for field in fields_to_raw_free: -## newops.append(SpaceOperation("flavored_free", -## [Constant("raw", lltype.Void), -## newvarsmap[key_for_field_access(STRUCT, field)]], -## varoftype(lltype.Void))) - if insert_keepalive and last_removed_access is not None: keepalives = [] for v in list_newvars(): @@ -458,6 +464,10 @@ block.operations[:] = newops + return newvarsmap + + for_field_freeing_varmap = None + # look for variables arriving from outside the block for var in vars: if var in block.inputargs: @@ -465,14 +475,14 @@ newinputargs = block.inputargs[:i] newvarsmap = {} for key in flatnames: - newvar = Variable() + newvar = Variable(key[0]._name + ''.join(map(str, key[1:]))) newvar.concretetype = newvarstype[key] newvarsmap[key] = newvar newinputargs.append(newvar) newinputargs += block.inputargs[i+1:] block.inputargs[:] = newinputargs assert var not in block.inputargs - flowin(var, newvarsmap, insert_keepalive=True) + for_field_freeing_varmap = flowin(var, newvarsmap, insert_keepalive=True) # look for variables created inside the block by a malloc vars_created_here = [] @@ -480,24 +490,50 @@ if op.opname in ("malloc", "zero_malloc") and op.result in vars: vars_created_here.append(op.result) for var in vars_created_here: - flowin(var, newvarsmap=None) + newmap = flowin(var, newvarsmap=None) + if for_field_freeing_varmap is None: + for_field_freeing_varmap = newmap + + if fields_to_raw_free and links: + for link in links_without_vars: + varstofree = [for_field_freeing_varmap[key_for_field_access(STRUCT, field)] for field in fields_to_raw_free] + varstofree = [v for v in varstofree if isinstance(v, Variable)] + if varstofree: + links_to_split.setdefault(link, []).extend(varstofree) return count[0] -def remove_mallocs_once(graph): +def remove_mallocs_once(graph, remove_autofrees=False): """Perform one iteration of malloc removal.""" remove_identical_vars(graph) lifetimes = compute_lifetimes(graph) progress = 0 + links_to_split = {} for info in lifetimes: - progress += _try_inline_malloc(info) + progress += _try_inline_malloc(graph, info, links_to_split, remove_autofrees) + checkgraph(graph) + join_blocks(graph) + for link, vars_to_free in links_to_split.iteritems(): + newblock = None + for v in vars_to_free: + if isinstance(v, Variable): + if not newblock: + newblock = insert_empty_block(None, link) + link.args.append(v) + newblock.inputargs.append(copyvar(None, v)) + newblock.operations.append(SpaceOperation("flavored_free", + [Constant("raw", lltype.Void), + newblock.inputargs[-1]], + varoftype(lltype.Void))) +## if graph.name == "func" and remove_autofrees and progress: +## graph.show() return progress -def remove_simple_mallocs(graph, callback=None): +def remove_simple_mallocs(graph, callback=None, remove_autofrees=False): """Iteratively remove (inline) the mallocs that can be simplified away.""" tot = 0 while True: - count = remove_mallocs_once(graph) + count = remove_mallocs_once(graph, remove_autofrees) if count: log.malloc('%d simple mallocs removed in %r' % (count, graph.name)) constant_fold_graph(graph) Modified: pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/c/funcgen.py Fri Sep 22 15:00:25 2006 @@ -48,6 +48,9 @@ # apply the exception transformation if self.db.exctransformer: self.db.exctransformer.create_exception_handling(self.graph) + if graph.needs_more_malloc_removal: + from pypy.translator.backendopt.malloc import remove_simple_mallocs + remove_simple_mallocs(graph, remove_autofrees=True) # apply the gc transformation if self.db.gctransformer: self.db.gctransformer.transform_graph(self.graph) @@ -753,6 +756,9 @@ format.append(arg.value.replace('%', '%%')) continue format.append('%c') + elif T == Void and isinstance(arg, Constant) and isinstance(arg.value, str): + format.append(arg.value.replace('%', '%%')) + continue else: raise Exception("don't know how to debug_print %r" % (T,)) argv.append(self.expr(arg)) From mwh at codespeak.net Fri Sep 22 15:04:07 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Sep 2006 15:04:07 +0200 (CEST) Subject: [pypy-svn] r32578 - pypy/branch/kill-keepalives/pypy/translator/backendopt Message-ID: <20060922130407.274EB1006E@code0.codespeak.net> Author: mwh Date: Fri Sep 22 15:04:06 2006 New Revision: 32578 Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Log: oops Modified: pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/kill-keepalives/pypy/translator/backendopt/malloc.py Fri Sep 22 15:04:06 2006 @@ -494,7 +494,7 @@ if for_field_freeing_varmap is None: for_field_freeing_varmap = newmap - if fields_to_raw_free and links: + if fields_to_raw_free and links_without_vars: for link in links_without_vars: varstofree = [for_field_freeing_varmap[key_for_field_access(STRUCT, field)] for field in fields_to_raw_free] varstofree = [v for v in varstofree if isinstance(v, Variable)] From arigo at codespeak.net Fri Sep 22 15:14:30 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 15:14:30 +0200 (CEST) Subject: [pypy-svn] r32579 - pypy/dist/pypy/jit/timeshifter Message-ID: <20060922131430.3FF821006E@code0.codespeak.net> Author: arigo Date: Fri Sep 22 15:14:28 2006 New Revision: 32579 Modified: pypy/dist/pypy/jit/timeshifter/oop.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/transform.py pypy/dist/pypy/jit/timeshifter/vlist.py Log: (arre, arigo) Type-safety, with __slots__ to check that attributes are not moved up unexpectedly. Lots of isinstance() fixes... Modified: pypy/dist/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/oop.py (original) +++ pypy/dist/pypy/jit/timeshifter/oop.py Fri Sep 22 15:14:28 2006 @@ -52,15 +52,19 @@ self.sigtoken = RGenOp.sigToken(FUNCTYPE) if operation_name == 'newlist': - from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist - self.typedesc = ListTypeDesc(hrtyper, FUNCTYPE.RESULT.TO) - self.ll_handler = oop_newlist + typename, method = 'list', 'oop_newlist' + SELFTYPE = FUNCTYPE.RESULT.TO + self.is_method = False else: typename, method = operation_name.split('.') method = 'oop_%s_%s' % (typename, method) - vmodule = __import__('pypy.jit.timeshifter.v%s' % (typename,), - None, None, [method]) - self.ll_handler = getattr(vmodule, method) + SELFTYPE = FUNCTYPE.ARGS[self.argpositions[0]].TO + self.is_method = True + + vmodule = __import__('pypy.jit.timeshifter.v%s' % (typename,), + None, None, [method]) + self.typedesc = vmodule.TypeDesc(hrtyper, SELFTYPE) + self.ll_handler = getattr(vmodule, method) # exception handling graph = fnobj.graph Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Fri Sep 22 15:14:28 2006 @@ -3,6 +3,7 @@ from pypy.jit.timeshifter import rvalue class AbstractContainer(object): + __slots__ = [] def op_getfield(self, jitstate, fielddesc): raise NotImplementedError Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Fri Sep 22 15:14:28 2006 @@ -61,6 +61,8 @@ self.r_JITState) = self.s_r_instanceof(rtimeshift.JITState) (self.s_RedBox, self.r_RedBox) = self.s_r_instanceof(rvalue.RedBox) + (self.s_PtrRedBox, + self.r_PtrRedBox) = self.s_r_instanceof(rvalue.PtrRedBox) (self.s_OopSpecDesc, self.r_OopSpecDesc) = self.s_r_instanceof(oop.OopSpecDesc) (self.s_ConstOrVar, @@ -819,6 +821,10 @@ args_v.extend([hop.llops.genconst(ll_None)] * missing_args) args_s = [ts.s_RedBox] * len(args_v) + if oopspecdesc.is_method: + args_s[0] = ts.s_PtrRedBox # for more precise annotations + args_v[0] = hop.llops.genop('cast_pointer', [args_v[0]], + resulttype = ts.r_PtrRedBox.lowleveltype) RESULT = originalconcretetype(hop.s_result) if RESULT is lltype.Void: s_result = annmodel.s_None Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Fri Sep 22 15:14:28 2006 @@ -21,6 +21,7 @@ class RedBox(object): + __slots__ = ['kind', 'genvar'] def __init__(self, kind, genvar=None): self.kind = kind @@ -177,23 +178,26 @@ def copy(self, memo): boxmemo = memo.boxes try: - return boxmemo[self] + result = boxmemo[self] except KeyError: result = PtrRedBox(self.kind, self.genvar) boxmemo[self] = result if self.content: result.content = self.content.copy(memo) - return result + assert isinstance(result, PtrRedBox) + return result def replace(self, memo): boxmemo = memo.boxes try: - return boxmemo[self] + result = boxmemo[self] except KeyError: boxmemo[self] = self if self.content: self.content.replace(memo) - return self + result = self + assert isinstance(result, PtrRedBox) + return result def freeze(self, memo): boxmemo = memo.boxes Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Fri Sep 22 15:14:28 2006 @@ -72,12 +72,12 @@ # __________ helpers __________ - def genop(self, block, opname, args, result_type=None, result_like=None): - # 'result_type' can be a LowLevelType (for green returns) - # or a template variable whose hintannotation is copied - if result_type is not None: - v_res = varoftype(result_type) - hs = hintmodel.SomeLLAbstractConstant(result_type, {}) + def genop(self, block, opname, args, resulttype=None, result_like=None): + # 'result_like' can be a template variable whose hintannotation is + # copied + if resulttype is not None: + v_res = varoftype(resulttype) + hs = hintmodel.SomeLLAbstractConstant(resulttype, {}) self.hannotator.setbinding(v_res, hs) elif result_like is not None: v_res = copyvar(self.hannotator, result_like) @@ -182,13 +182,13 @@ nonconstant_block = Block([]) v_flag = self.genop(block, 'is_constant', [v_redswitch], - result_type = lltype.Bool) + resulttype = lltype.Bool) self.genswitch(block, v_flag, true = constant_block, false = nonconstant_block) v_greenswitch = self.genop(constant_block, 'revealconst', [v_redswitch], - result_type = lltype.Bool) + resulttype = lltype.Bool) constant_block.exitswitch = v_greenswitch constant_block.closeblock(link_f, link_t) @@ -248,7 +248,7 @@ c_mp = inputconst(lltype.Void, mp) v_finished_flag = self.genop(block, 'merge_point', [self.c_mpfamily, c_mp] + greens, - result_type = lltype.Bool) + resulttype = lltype.Bool) block.exitswitch = v_finished_flag [link_f] = block.exits link_t = Link([self.c_dummy], self.graph.returnblock) @@ -273,7 +273,7 @@ if self.resumepoints: block = self.before_return_block() v_switchcase = self.genop(block, 'dispatch_next', [], - result_type = lltype.Signed) + resulttype = lltype.Signed) block.exitswitch = v_switchcase defaultlink = block.exits[0] defaultlink.exitcase = 'default' @@ -376,7 +376,7 @@ if not hs_func.is_green(): # XXX for now, assume that it will be a constant red box v_greenfunc = self.genop(block, 'revealconst', [args_v[0]], - result_type = originalconcretetype(hs_func)) + resulttype = originalconcretetype(hs_func)) args_v[0] = v_greenfunc self.genop(block, 'indirect_%s_call' % (color,), args_v) Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Fri Sep 22 15:14:28 2006 @@ -33,6 +33,8 @@ vlist.ownbox = box return box +TypeDesc = ListTypeDesc + class FrozenVirtualList(AbstractContainer): @@ -137,101 +139,116 @@ return oopspecdesc.residual_call(jitstate, [lengthbox, itembox]) def oop_list_copy(jitstate, oopspecdesc, selfbox): - if isinstance(selfbox.content, VirtualList): + content = selfbox.content + if isinstance(content, VirtualList): copybox = oopspecdesc.typedesc.factory(0, None) - copybox.content.item_boxes.extend(selfbox.content.item_boxes) + copycontent = copybox.content + assert isinstance(copycontent, VirtualList) + copycontent.item_boxes.extend(content.item_boxes) return copybox else: return oopspecdesc.residual_call(jitstate, [selfbox]) def oop_list_len(jitstate, oopspecdesc, selfbox): - if isinstance(selfbox.content, VirtualList): - return rvalue.ll_fromvalue(jitstate, len(selfbox.content.item_boxes)) + content = selfbox.content + if isinstance(content, VirtualList): + return rvalue.ll_fromvalue(jitstate, len(content.item_boxes)) else: return oopspecdesc.residual_call(jitstate, [selfbox]) def oop_list_nonzero(jitstate, oopspecdesc, selfbox): - if isinstance(selfbox.content, VirtualList): - return rvalue.ll_fromvalue(jitstate, bool(selfbox.content.item_boxes)) + content = selfbox.content + if isinstance(content, VirtualList): + return rvalue.ll_fromvalue(jitstate, bool(content.item_boxes)) else: return oopspecdesc.residual_call(jitstate, [selfbox]) def oop_list_append(jitstate, oopspecdesc, selfbox, itembox): - if isinstance(selfbox.content, VirtualList): - selfbox.content.item_boxes.append(itembox) + content = selfbox.content + if isinstance(content, VirtualList): + content.item_boxes.append(itembox) else: oopspecdesc.residual_call(jitstate, [selfbox, itembox]) def oop_list_insert(jitstate, oopspecdesc, selfbox, indexbox, itembox): - if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): + content = selfbox.content + if isinstance(content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) # XXX what if the assert fails? - assert 0 <= index <= len(selfbox.content.item_boxes) - selfbox.content.item_boxes.insert(index, itembox) + assert 0 <= index <= len(content.item_boxes) + content.item_boxes.insert(index, itembox) else: oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) def oop_list_concat(jitstate, oopspecdesc, selfbox, otherbox): - if isinstance(selfbox.content, VirtualList): + content = selfbox.content + if isinstance(content, VirtualList): assert isinstance(otherbox, rvalue.PtrRedBox) - if (otherbox.content is not None and - isinstance(otherbox.content, VirtualList)): + othercontent = otherbox.content + if othercontent is not None and isinstance(othercontent, VirtualList): newbox = oopspecdesc.typedesc.factory(0, None) - newbox.content.item_boxes.extend(selfbox.content.item_boxes) - newbox.content.item_boxes.extend(otherbox.content.item_boxes) + newcontent = newbox.content + assert isinstance(newcontent, VirtualList) + newcontent.item_boxes.extend(content.item_boxes) + newcontent.item_boxes.extend(othercontent.item_boxes) return newbox return oopspecdesc.residual_call(jitstate, [selfbox, otherbox]) def oop_list_pop(jitstate, oopspecdesc, selfbox, indexbox=None): + content = selfbox.content if indexbox is None: - if isinstance(selfbox.content, VirtualList): + if isinstance(content, VirtualList): try: - return selfbox.content.item_boxes.pop() + return content.item_boxes.pop() except IndexError: return oopspecdesc.residual_exception(jitstate, IndexError) else: return oopspecdesc.residual_call(jitstate, [selfbox]) - if (isinstance(selfbox.content, VirtualList) and + if (isinstance(content, VirtualList) and indexbox.is_constant()): index = rvalue.ll_getvalue(indexbox, lltype.Signed) try: - return selfbox.content.item_boxes.pop(index) + return content.item_boxes.pop(index) except IndexError: return oopspecdesc.residual_exception(jitstate, IndexError) return oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) def oop_list_reverse(jitstate, oopspecdesc, selfbox): - if isinstance(selfbox.content, VirtualList): - selfbox.content.item_boxes.reverse() + content = selfbox.content + if isinstance(content, VirtualList): + content.item_boxes.reverse() else: oopspecdesc.residual_call(jitstate, [selfbox]) def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox): - if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): + content = selfbox.content + if isinstance(content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) try: - return selfbox.content.item_boxes[index] + return content.item_boxes[index] except IndexError: return oopspecdesc.residual_exception(jitstate, IndexError) else: return oopspecdesc.residual_call(jitstate, [selfbox, indexbox]) def oop_list_setitem(jitstate, oopspecdesc, selfbox, indexbox, itembox): - if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): + content = selfbox.content + if isinstance(content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) try: - selfbox.content.item_boxes[index] = itembox + content.item_boxes[index] = itembox except IndexError: oopspecdesc.residual_exception(jitstate, IndexError) else: oopspecdesc.residual_call(jitstate, [selfbox, indexbox, itembox]) def oop_list_delitem(jitstate, oopspecdesc, selfbox, indexbox): - if isinstance(selfbox.content, VirtualList) and indexbox.is_constant(): + content = selfbox.content + if isinstance(content, VirtualList) and indexbox.is_constant(): index = rvalue.ll_getvalue(indexbox, lltype.Signed) try: - del selfbox.content.item_boxes[index] + del content.item_boxes[index] except IndexError: oopspecdesc.residual_exception(jitstate, IndexError) else: From arigo at codespeak.net Fri Sep 22 18:21:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 18:21:57 +0200 (CEST) Subject: [pypy-svn] r32583 - in pypy/dist/pypy: bin translator/tool/pygame Message-ID: <20060922162157.9A5431006E@code0.codespeak.net> Author: arigo Date: Fri Sep 22 18:21:55 2006 New Revision: 32583 Modified: pypy/dist/pypy/bin/dotviewer.py pypy/dist/pypy/translator/tool/pygame/graphclient.py Log: Can pass directly .plain files to bin/dotviewer.py. Modified: pypy/dist/pypy/bin/dotviewer.py ============================================================================== --- pypy/dist/pypy/bin/dotviewer.py (original) +++ pypy/dist/pypy/bin/dotviewer.py Fri Sep 22 18:21:55 2006 @@ -12,13 +12,15 @@ usage = ''' %s filename.dot + %s filename.plain %s hostname:port %s :port In the first form, show the graph contained in a .dot file. +In the second form, the graph was already compiled to a .plain file. In the other forms, connect to a graph server like goal/translate.py. -''' % (sys.argv[0], sys.argv[0], sys.argv[0]) +''' % (sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0]) parser = optparse.OptionParser(usage=usage) parser.add_option("--reload", action="store_true", dest="reload", Modified: pypy/dist/pypy/translator/tool/pygame/graphclient.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/graphclient.py (original) +++ pypy/dist/pypy/translator/tool/pygame/graphclient.py Fri Sep 22 18:21:55 2006 @@ -18,7 +18,11 @@ PLAIN_FILE = udir.join('graph.plain') def dot2plain(dotfile, plainfile, use_codespeak=False): - if not use_codespeak: + if str(dotfile).lower().endswith('.plain'): + # already a .plain file + plainfile = py.path.local(plainfile) + plainfile.write(py.path.local(dotfile).read()) + elif not use_codespeak: py.process.cmdexec('dot -Tplain %s>%s' % (dotfile, plainfile)) elif 0: gw = py.execnet.SshGateway('codespeak.net') From arigo at codespeak.net Fri Sep 22 18:22:31 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 18:22:31 +0200 (CEST) Subject: [pypy-svn] r32584 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060922162231.2A8441006E@code0.codespeak.net> Author: arigo Date: Fri Sep 22 18:22:30 2006 New Revision: 32584 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py Log: (arre, arigo) Try to build a meaningful 'id' for _func objects. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Fri Sep 22 18:22:30 2006 @@ -1132,7 +1132,7 @@ if isinstance(obj, int): return obj # special case for cast_int_to_ptr() results obj = normalizeptr(self)._obj - result = intmask(id(obj)) + result = intmask(obj._getid()) # assume that id() returns an addressish value which is # not zero and aligned to at least a multiple of 4 assert result != 0 and (result & 3) == 0 @@ -1170,6 +1170,8 @@ return self def _normalizedcontainer(self): return self + def _getid(self): + return id(self) class _parentable(_container): _kind = "?" @@ -1467,6 +1469,9 @@ return _ptr(Ptr(subarray._TYPE), subarray, solid) _makeptr = staticmethod(_makeptr) + def _getid(self): + raise NotImplementedError('_subarray._getid()') + class _func(_container): def __init__(self, TYPE, **attrs): @@ -1491,6 +1496,14 @@ def __hash__(self): return hash(frozendict(self.__dict__)) + def _getid(self): + if hasattr(self, 'graph'): + return id(self.graph) + elif self._callable: + return id(self._callable) + else: + return id(self) + def __getstate__(self): import pickle, types __dict__ = self.__dict__.copy() @@ -1558,6 +1571,9 @@ def __str__(self): return "pyobject %s" % (Hashable.__str__(self),) + def _getid(self): + return id(self.value) + class _pyobjheader(_parentable): def __init__(self, parent=None, parentindex=None): _parentable.__init__(self, PyObject) From arigo at codespeak.net Fri Sep 22 18:23:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 18:23:03 +0200 (CEST) Subject: [pypy-svn] r32585 - pypy/dist/pypy/jit/tl Message-ID: <20060922162303.0CC0F1006E@code0.codespeak.net> Author: arigo Date: Fri Sep 22 18:23:02 2006 New Revision: 32585 Modified: pypy/dist/pypy/jit/tl/tlc.py Log: Express a loop as a recursion again, which is necessary for now to avoid merging. Modified: pypy/dist/pypy/jit/tl/tlc.py ============================================================================== --- pypy/dist/pypy/jit/tl/tlc.py (original) +++ pypy/dist/pypy/jit/tl/tlc.py Fri Sep 22 18:23:02 2006 @@ -49,10 +49,9 @@ def div(self, n): n = n.int_o() - cur = self - for i in range(n): - cur = cur.cdr() - return cur.car() + if n < 0: + raise IndexError + return self._nth(n) def add(self, other): if not isinstance(other, LispObj): @@ -67,12 +66,12 @@ def eq(self, other): return self is other - def car(self): raise IndexError - def cdr(self): raise IndexError - def _concat(self, other): return other + def _nth(self, n): + raise IndexError + nil = NilObj() class ConsObj(LispObj): @@ -96,6 +95,12 @@ def _concat(self, other): return ConsObj(self._car, self._cdr._concat(other)) + def _nth(self, n): + if n == 0: + return self._car + else: + return self._cdr._nth(n-1) + def char2int(c): t = ord(c) if t & 128: From arigo at codespeak.net Fri Sep 22 18:23:38 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 18:23:38 +0200 (CEST) Subject: [pypy-svn] r32586 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060922162338.870001006E@code0.codespeak.net> Author: arigo Date: Fri Sep 22 18:23:36 2006 New Revision: 32586 Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/test/test_tlc.py pypy/dist/pypy/jit/timeshifter/vlist.py Log: (arre, arigo) The first TLC test passes! Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Fri Sep 22 18:23:36 2006 @@ -153,6 +153,7 @@ #self.fz_content_boxes initialized later def exactmatch(self, vstruct, outgoingvarboxes, memo): + assert isinstance(vstruct, VirtualStruct) contmemo = memo.containers if self in contmemo: ok = vstruct is contmemo[self] Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Fri Sep 22 18:23:36 2006 @@ -915,6 +915,7 @@ def test_green_with_side_effects(self): S = lltype.GcStruct('S', ('flag', lltype.Bool)) s = lltype.malloc(S) + s.flag = False def ll_set_flag(s): s.flag = True def ll_function(): @@ -922,7 +923,7 @@ ll_set_flag(s) return s.flag res = self.timeshift(ll_function, [], []) - assert res is True + assert res == True self.check_insns({'setfield': 2, 'getfield': 1}) def test_recursive_call(self): @@ -959,7 +960,7 @@ g = g2 return g(v) - res = self.timeshift(f, [False, 40], [0]) + res = self.timeshift(f, [0, 40], [0]) assert res == 42 self.check_insns({'int_add': 1}) @@ -977,11 +978,11 @@ g = g2 return g(v) - res = self.timeshift(f, [False, 40], [0]) + res = self.timeshift(f, [0, 40], [0]) assert res == 42 self.check_insns({'int_add': 1}) - res = self.timeshift(f, [True, 40], [0]) + res = self.timeshift(f, [1, 40], [0]) assert res == -17 self.check_insns({}) @@ -1003,19 +1004,19 @@ g = g2 return g(v) + w - res = self.timeshift(f, [False, 40], [0]) + res = self.timeshift(f, [0, 40], [0]) assert res == 25 self.check_insns({'int_add': 2, 'int_ge': 1}) - res = self.timeshift(f, [True, 40], [0]) + res = self.timeshift(f, [1, 40], [0]) assert res == -34 self.check_insns({'int_ge': 2, 'int_add': 1}) - res = self.timeshift(f, [False, -1000], [0]) + res = self.timeshift(f, [0, -1000], [0]) assert res == f(False, -1000) self.check_insns({'int_add': 2, 'int_ge': 1}) - res = self.timeshift(f, [True, -1000], [0]) + res = self.timeshift(f, [1, -1000], [0]) assert res == f(True, -1000) self.check_insns({'int_ge': 2, 'int_add': 1}) @@ -1037,6 +1038,6 @@ o = Concrete() return o.m() - res = self.timeshift(f, [False], [0], policy=P_NOVIRTUAL) + res = self.timeshift(f, [0], [0], policy=P_NOVIRTUAL) assert res == 42 self.check_insns({}) Modified: pypy/dist/pypy/jit/timeshifter/test/test_tlc.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_tlc.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_tlc.py Fri Sep 22 18:23:36 2006 @@ -9,20 +9,20 @@ from pypy.jit.tl.test.test_tl import FACTORIAL_SOURCE +tlc_interp_without_call = func_with_new_name( + tlc.interp_without_call, "tlc_interp_without_call") +# to stick attributes on the new function object, not on tlc.interp_wi* +def build_bytecode(s): + result = ''.join([chr(int(t)) for t in s.split(',')]) + return LLSupport.to_rstr(result) +tlc_interp_without_call.convert_arguments = [build_bytecode, int, int] + + class TestTLC(TimeshiftingTests): - def test_tlc(self): - py.test.skip("in-progress") + def test_factorial(self): code = tlc.compile(FACTORIAL_SOURCE) bytecode = ','.join([str(ord(c)) for c in code]) - tlc_interp_without_call = func_with_new_name( - tlc.interp_without_call, "tlc_interp_without_call") - # to stick attributes on the new function object, not on tlc.interp_wi* - def build_bytecode(s): - result = ''.join([chr(int(t)) for t in s.split(',')]) - return LLSupport.to_rstr(result) - tlc_interp_without_call.convert_arguments = [build_bytecode, int, int] - if Benchmark.ENABLED: n = 2500 expected = 0 # far too many powers of 2 to be anything else @@ -30,5 +30,24 @@ n = 5 expected = 120 res = self.timeshift(tlc_interp_without_call, [bytecode, 0, n], - [0, 1], policy=P_OOPSPEC, backendoptimize=True) + [0, 1], policy=P_OOPSPEC)#, backendoptimize=True) assert res == expected + + def test_nth_item(self): + py.test.skip("in-progress") + # get the nth item of a chained list + code = tlc.compile(""" + NIL + PUSH 40 + CONS + PUSH 20 + CONS + PUSH 10 + CONS + PUSHARG + DIV + """) + bytecode = ','.join([str(ord(c)) for c in code]) + res = self.timeshift(tlc_interp_without_call, [bytecode, 0, 1], + [0, 1], policy=P_OOPSPEC)#, backendoptimize=True) + assert res == 20 Modified: pypy/dist/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/vlist.py (original) +++ pypy/dist/pypy/jit/timeshifter/vlist.py Fri Sep 22 18:23:36 2006 @@ -43,6 +43,7 @@ #self.fz_item_boxes initialized later def exactmatch(self, vlist, outgoingvarboxes, memo): + assert isinstance(vlist, VirtualList) contmemo = memo.containers if self in contmemo: ok = vlist is contmemo[self] From arigo at codespeak.net Fri Sep 22 19:20:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 19:20:13 +0200 (CEST) Subject: [pypy-svn] r32596 - in pypy/dist/pypy/rpython/rctypes: . test tool tool/test Message-ID: <20060922172013.6DC831006C@code0.codespeak.net> Author: arigo Date: Fri Sep 22 19:20:11 2006 New Revision: 32596 Modified: pypy/dist/pypy/rpython/rctypes/astruct.py pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py pypy/dist/pypy/rpython/rctypes/tool/test/test_ctypes_platform.py Log: Two rctypes extensions: offsetof(Struct, fieldname), and ctypes_platform support for guessing the length of a 'char[]' array field in a struct. Modified: pypy/dist/pypy/rpython/rctypes/astruct.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/astruct.py (original) +++ pypy/dist/pypy/rpython/rctypes/astruct.py Fri Sep 22 19:20:11 2006 @@ -1,5 +1,6 @@ from ctypes import Structure, Union -from pypy.annotation.model import SomeCTypesObject +from pypy.annotation.model import SomeCTypesObject, SomeInteger +from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry from pypy.rpython.lltypesystem import lltype @@ -10,6 +11,30 @@ # by the llinterpreter. They work in the generated C code, though. +def offsetof(Struct, fieldname): + "Utility function that returns the offset of a field in a structure." + return getattr(Struct, fieldname).offset + + +class OffsetOfFnEntry(ExtRegistryEntry): + "Annotation and rtyping of calls to offsetof()" + _about_ = offsetof + + def compute_result_annotation(self, s_Struct, s_fieldname): + assert s_Struct.is_constant() + assert s_fieldname.is_constant() + ofs = offsetof(s_Struct.const, s_fieldname.const) + assert ofs >= 0 + s_result = SomeInteger(nonneg=True) + s_result.const = ofs + return s_result + + def specialize_call(self, hop): + ofs = hop.s_result.const + return hop.inputconst(lltype.Signed, ofs) + +# ____________________________________________________________ + class CallEntry(CTypesCallEntry): "Annotation and rtyping of calls to structure types." _type_ = StructType, UnionType Modified: pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py Fri Sep 22 19:20:11 2006 @@ -4,6 +4,7 @@ import py.test import pypy.rpython.rctypes.implementation +from pypy.rpython.rctypes.astruct import offsetof from pypy.rpython.error import TyperError from pypy.annotation.annrpython import RPythonAnnotator from pypy.translator.translator import TranslationContext @@ -235,6 +236,12 @@ S(x, x=5) py.test.raises(TyperError, "interpret(f2, [4])") + def test_specialize_offsetof(self): + def f1(): + return offsetof(tagpoint, 'y') + res = interpret(f1, []) + assert res == tagpoint.y.offset + class Test_compilation: def test_compile_struct_access(self): def access_struct(n): Modified: pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py (original) +++ pypy/dist/pypy/rpython/rctypes/tool/ctypes_platform.py Fri Sep 22 19:20:11 2006 @@ -391,6 +391,12 @@ for ctype in typeclass: if size_and_sign(ctype) == expected_size_and_sign: return ctype + if (hasattr(fieldtype, '_length_') + and getattr(fieldtype, '_type_', None) == ctypes.c_char): + # for now, assume it is an array of chars; otherwise we'd also + # have to check the exact integer type of the elements of the array + size, sign = expected_size_and_sign + return ctypes.c_char * size raise TypeError("conflicting field type %r for %r" % (fieldtype, fieldname)) Modified: pypy/dist/pypy/rpython/rctypes/tool/test/test_ctypes_platform.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/tool/test/test_ctypes_platform.py (original) +++ pypy/dist/pypy/rpython/rctypes/tool/test/test_ctypes_platform.py Fri Sep 22 19:20:11 2006 @@ -147,3 +147,17 @@ assert issubclass(c_x , ctypes.Structure) assert issubclass(c_y, ctypes.Structure) assert c_y_fields["x"] is c_x + +def test_array(): + dirent = ctypes_platform.getstruct("struct dirent", + """ + struct dirent /* for this example only, not the exact dirent */ + { + long d_ino; + int d_off; + unsigned short d_reclen; + char d_name[32]; + }; + """, + [("d_name", ctypes.c_char * 0)]) + assert dirent.d_name.size == 32 From arigo at codespeak.net Fri Sep 22 19:50:27 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 19:50:27 +0200 (CEST) Subject: [pypy-svn] r32597 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060922175027.F2DBF10074@code0.codespeak.net> Author: arigo Date: Fri Sep 22 19:50:26 2006 New Revision: 32597 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/lltypesystem/rrange.py pypy/dist/pypy/rpython/lltypesystem/rslice.py Log: Some more {'hints': 'immutable'}. Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Fri Sep 22 19:50:26 2006 @@ -44,7 +44,8 @@ def _setup_repr(self): llfields = self._setup_repr_fields() - self.pbc_type.become(Struct('pbc', *llfields)) + kwds = {'hints': {'immutable': True}} + self.pbc_type.become(Struct('pbc', *llfields, **kwds)) def create_instance(self): return malloc(self.pbc_type, immortal=True) @@ -64,7 +65,7 @@ with no common access set.""" lowleveltype = llmemory.Address - EMPTY = Struct('pbc') + EMPTY = Struct('pbc', hints={'immutable': True}) def convert_pbc(self, pbcptr): return llmemory.fakeaddress(pbcptr) @@ -103,7 +104,8 @@ fields = [] for row in self.uniquerows: fields.append((row.attrname, row.fntype)) - return Ptr(Struct('specfunc', *fields)) + kwds = {'hints': {'immutable': True}} + return Ptr(Struct('specfunc', *fields, **kwds)) def create_specfunc(self): return malloc(self.lowleveltype.TO, immortal=True) Modified: pypy/dist/pypy/rpython/lltypesystem/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rrange.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rrange.py Fri Sep 22 19:50:26 2006 @@ -35,7 +35,8 @@ adtmeths = { "ll_length":ll_length, "ll_getitem_fast":ll_getitem_fast, - }) + }, + hints = {'immutable': True}) RANGESTITER = GcStruct("range", ("next", Signed), ("stop", Signed), ("step", Signed)) class RangeRepr(AbstractRangeRepr): @@ -51,7 +52,8 @@ "ll_length":ll_length, "ll_getitem_fast":ll_getitem_fast, "step":step, - })) + }, + hints = {'immutable': True})) self.RANGEITER = Ptr(GcStruct("range", ("next", Signed), ("stop", Signed))) AbstractRangeRepr.__init__(self, step, *args) self.ll_newrange = ll_newrange Modified: pypy/dist/pypy/rpython/lltypesystem/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rslice.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rslice.py Fri Sep 22 19:50:26 2006 @@ -18,8 +18,8 @@ # // step is always 1 # } -SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed)) - +SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed), + hints = {'immutable': True}) class SliceRepr(AbstractSliceRepr): pass From arigo at codespeak.net Fri Sep 22 21:51:31 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 21:51:31 +0200 (CEST) Subject: [pypy-svn] r32598 - pypy/dist/pypy/module/_socket Message-ID: <20060922195131.DB0461006E@code0.codespeak.net> Author: arigo Date: Fri Sep 22 21:51:30 2006 New Revision: 32598 Added: pypy/dist/pypy/module/_socket/rsocket.py (contents, props changed) Log: Another (better?) start at the socket module. This one is meant to be usable from pure RPython programs (methods with a 'space' arguments are only to ease the implementation of the future PyPy mixed module). In particular it should work well on top of CPython too. The address-manipulation parts of the interface are not like CPython's; instead, to be RPythonic, we have various subclasses of a base Address class, with various constructors and inspection methods. At least this allows some roughly clean separation of the manipulation of the various address families. Implementation-wise, this tries to stick as close to CPython's socketmodule.c as possible. Added: pypy/dist/pypy/module/_socket/rsocket.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_socket/rsocket.py Fri Sep 22 21:51:30 2006 @@ -0,0 +1,407 @@ +""" +An RPython implementation of sockets based on ctypes. +Note that the interface has to be slightly different - this is not +a drop-in replacement for the 'socket' module. +""" + +# ------------ IN - PROGRESS ----------- + +from pypy.rpython.objectmodel import instantiate + + +class Address(object): + """The base class for RPython-level objects representing addresses. + Fields: addr - a _c.sockaddr structure + addrlen - size used within 'addr' + """ + def __init__(self, addr, addrlen): + self.addr = addr + self.addrlen = addrlen + + def raw_to_addr(self, ptr, size): + paddr = copy_buffer(ptr, size) + self.addr = cast(paddr, POINTER(_c.sockaddr)).contents + self.addrlen = size + + def as_object(self, space): + """Convert the address to an app-level object.""" + # If we don't know the address family, don't raise an + # exception -- return it as a tuple. + family = self.addr.sa_family + buf = copy_buffer(cast(pointer(self.addr.sa_data), POINTER(char)), + self.addrlen - offsetof(_c.sockaddr_un, 'sa_data')) + return space.newtuple([space.wrap(family), + space.wrap(buf.raw)]) + + def from_object(space, w_address): + """Convert an app-level object to an Address.""" + # It's a static method but it's overridden and must be called + # on the correct subclass. + raise SocketError("unknown address family") + from_object = staticmethod(from_object) + + def from_null(): + raise SocketError("unknown address family") + from_null = staticmethod(from_null) + +# ____________________________________________________________ + +class IPAddress(Address): + """AF_INET and AF_INET6 addresses""" + + def makeipaddr(self, name): + # Convert a string specifying a host name or one of a few symbolic + # names to a numeric IP address. This usually calls gethostbyname() + # to do the work; the names "" and "" are special. + if len(name) == 0: + hints = _c.addrinfo(ai_family = self.family, + ai_socktype = _c.SOCK_DGRAM, # dummy + ai_flags = _c.AI_PASSIVE) + res = _c.addrinfo_ptr() + error = _c.getaddrinfo(None, "0", byref(hints), byref(res)) + if error: + raise GAIError(error) + try: + info = res.contents + if info.ai_next: + raise SocketError("wildcard resolved to " + "multiple addresses") + self.raw_to_addr(cast(info.ai_addr, POINTER(char)), + info.ai_addrlen) + finally: + _c.freeaddrinfo(res) + return + + # IPv4 also supports the special name "". + if name == '': + self.makeipv4addr(_c.INADDR_BROADCAST) + return + + # "dd.dd.dd.dd" format. + digits = name.split('.') + if len(digits) == 4: + try: + d0 = int(digits[0]) + d1 = int(digits[1]) + d2 = int(digits[2]) + d3 = int(digits[3]) + except ValueError: + pass + else: + if (0 <= d0 <= 255 and + 0 <= d1 <= 255 and + 0 <= d2 <= 255 and + 0 <= d3 <= 255): + self.makeipv4addr(_c.htonl( + (d0 << 24) | (d1 << 16) | (d2 << 8) | (d3 << 0))) + return + + # generic host name to IP conversion + hints = _c.addrinfo(ai_family = self.family) + res = _c.addrinfo_ptr() + error = _c.getaddrinfo(name, None, byref(hints), byref(res)) + # PLAT EAI_NONAME + if error: + raise GAIError(error) + try: + info = res.contents + self.raw_to_addr(cast(info.ai_addr, POINTER(char)), + info.ai_addrlen) + finally: + _c.freeaddrinfo(res) + + def get_host(self): + # Create a string object representing an IP address. + # For IPv4 this is always a string of the form 'dd.dd.dd.dd' + # (with variable size numbers). + buf = create_string_buffer(_c.NI_MAXHOST) + error = _c.getnameinfo(byref(self.addr), self.addrlen, + byref(buf), _c.NI_MAXHOST, + None, 0, _c.NI_NUMERICHOST) + if error: + raise GAIError(error) + return buf.value + + def makeipv4addr(self, s_addr): + raise SocketError("address family mismatched") + +# ____________________________________________________________ + +class INETAddress(IPAddress): + family = _c.AF_INET + struct = _c.sockaddr_in + + def __init__(self, host, port): + self.makeipaddr(host) + a = self.as_sockaddr_in() + a.sin_port = _c.htons(port) + + def makeipv4addr(self, s_addr): + sin = _c.sockaddr_in(sin_family = _c.AF_INET) # PLAT sin_len + sin.sin_addr.s_addr = s_addr + paddr = cast(pointer(sin), POINTER(_c.sockaddr)) + self.addr = paddr.contents + self.addrlen = sizeof(_c.sockaddr_in) + + def as_sockaddr_in(self): + return cast(pointer(self.addr), POINTER(_c.sockaddr_in)).contents + + def get_port(self): + a = self.as_sockaddr_in() + return _c.ntohs(a.sin_port) + + def as_object(self, space): + return space.newtuple([space.wrap(self.get_host()), + space.wrap(self.get_port())]) + + def from_object(space, w_address): + # Parse an app-level object representing an AF_INET address + w_host, w_port = space.unpackiterable(w_address, 2) + host = space.str_w(w_host) + port = space.int_w(w_port) + return INETAddress(host, port) + from_object = staticmethod(from_object) + + def from_null(): + return make_null_address(INETAddress) + from_null = staticmethod(from_null) + +# ____________________________________________________________ + +class INET6Address(IPAddress): + family = _c.AF_INET6 + struct = _c.sockaddr_in6 + + def __init__(self, host, port, flowinfo=0, scope_id=0): + self.makeipaddr(host) + a = self.as_sockaddr_in6() + a.sin6_port = _c.htons(port) + a.sin6_flowinfo = flowinfo + a.sin6_scope_id = scope_id + + def as_sockaddr_in6(self): + return cast(pointer(self.addr), POINTER(_c.sockaddr_in6)).contents + + def get_port(self): + a = self.as_sockaddr_in6() + return _c.ntohs(a.sin6_port) + + def get_flowinfo(self): + a = self.as_sockaddr_in6() + return a.sin6_flowinfo + + def get_scope_id(self): + a = self.as_sockaddr_in6() + return a.sin6_scope_id + + def as_object(self, space): + return space.newtuple([space.wrap(self.get_host()), + space.wrap(self.get_port()), + space.wrap(self.get_flowinfo()), + space.wrap(self.get_scope_id())]) + + def from_object(space, w_address): + pieces_w = space.unpackiterable(w_address) + if not (2 <= len(pieces_w) <= 4): + raise SocketError("AF_INET6 address must be a tuple of length 2 " + "to 4, not %d" % len(pieces)) + host = space.str_w(pieces_w[0]) + port = space.int_w(pieces_w[1]) + if len(pieces_w) > 2: flowinfo = space.int_w(pieces_w[2]) + else: flowinfo = 0 + if len(pieces_w) > 3: scope_id = space.int_w(pieces_w[3]) + else: scope_id = 0 + return INET6Address(host, port, flowinfo, scope_id) + from_object = staticmethod(from_object) + + def from_null(): + return make_null_address(INET6Address) + from_null = staticmethod(from_null) + +# ____________________________________________________________ + +class UNIXAddress(Address): + family = _c.AF_UNIX + struct = _c.sockaddr_un + + def __init__(self, path): + addr = _c.sockaddr_un(sun_family = _c.AF_UNIX) + if _c.linux and path.startswith('\x00'): + # Linux abstract namespace extension + if len(path) > sizeof(addr.sun_path): + raise SocketError("AF_UNIX path too long") + else: + # regular NULL-terminated string + if len(path) >= sizeof(addr.sun_path): + raise SocketError("AF_UNIX path too long") + addr.sun_path[len(path)] = '\x00' + for i in range(len(path)): + addr.sun_path[i] = path[i] + self.addr = cast(pointer(addr), POINTER(sockaddr)).contents + self.addrlen = offsetof(sockaddr_un, 'sun_path') + len(path) + + def as_sockaddr_un(self): + return cast(pointer(self.addr), POINTER(_c.sockaddr_un)).contents + + def get_path(self): + a = self.as_sockaddr_un() + if _c.linux and a.sun_path[0] == '\x00': + # Linux abstract namespace + buf = copy_buffer(cast(pointer(a.sun_path), POINTER(char)), + self.addrlen - offsetof(_c.sockaddr_un, 'sun_path')) + return buf.raw + else: + # regular NULL-terminated string + return cast(pointer(a.sun_path), c_char_p).value + + def as_object(self, space): + return space.wrap(self.get_path()) + + def from_object(space, w_address): + return UNIXAddress(space.str_w(w_address)) + from_object = staticmethod(from_object) + + def from_null(): + return make_null_address(UNIXAddress) + from_null = staticmethod(from_null) + +# ____________________________________________________________ + +_FAMILIES = {} +for klass in [INETAddress, + INET6Address, + UNIXAddress]: + if klass.family is not None: + _FAMILIES[klass.family] = klass + +def familyclass(family): + return _FAMILIES.get(addr.sa_family, Address) + +def make_address(addr, addrlen): + result = instantiate(familyclass(addr.sa_family)) + result.addr = addr + result.addrlen = addrlen + return result + +def make_null_address(klass): + result = instantiate(klass) + result.addr = cast(pointer(klass.struct()), POINTER(_c.sockaddr)).contents + result.addrlen = 0 + return result +make_null_address._annspecialcase_ = 'specialize:arg(0)' + +def copy_buffer(ptr, size): + buf = create_string_buffer(size) + for i in range(size): + buf[i] = ptr.contents[i] + return buf + +# ____________________________________________________________ + +class RSocket(object): + """RPython-level socket object. + """ + + def __init__(self, family=_c.AF_INET, type=_c.SOCK_STREAM, proto=0): + """Create a new socket.""" + fd = _c.socket(family, type, proto) + if _c.invalid_socket(fd): + raise last_error() + # PLAT RISCOS + self.fd = fd + self.family = family + self.type = type + self.proto = proto + + # convert an Address into an app-level object + def addr_as_object(self, space, address): + return address.as_object(space) + + # convert an app-level object into an Address + # based on the current socket's family + def addr_from_object(self, space, w_address): + return af_get(self.family).from_object(space, w_address) + + def null_addr(self): + return familyclass(self.family).from_null() + + def accept(self): + """Wait for an incoming connection. + Return (new socket object, client address).""" + address = self.null_addr() + addrlen = _c.socklen_t() + newfd = _c.socketaccept(self.fd, byref(address.addr), byref(addrlen)) + if _c.invalid_socket(newfd): + raise self.error_handler() + address.addrlen = addrlen.value + sock = make_socket(newfd, self.family, self.type, self.proto) + return (sock, address) + + def bind(self, address): + """Bind the socket to a local address.""" + res = _c.socketbind(self.fd, byref(address.addr), address.addrlen) + if res < 0: + raise self.error_handler() + + def close(self): + """Close the socket. It cannot be used after this call.""" + fd = self.fd + if fd != _c.INVALID_SOCKET: + self.fd = _c.INVALID_SOCKET + _c.socketclose(fd) + + def connect(self, address): + """Connect the socket to a remote address.""" + res = _c.socketconnect(self.fd, byref(address.addr), address.addrlen) + if res < 0: + raise self.error_handler() + + def getsockname(self): + """Return the address of the local endpoint.""" + address = self.null_addr() + addrlen = _c.socklen_t() + res = _c.socketgetsockname(self.fd, byref(address.addr), + byref(addrlen)) + if res < 0: + raise self.error_handler() + address.addrlen = addrlen.value + return address + + def getpeername(self): + """Return the address of the remote endpoint.""" + address = self.null_addr() + addrlen = _c.socklen_t() + res = _c.socketgetpeername(self.fd, byref(address.addr), + byref(addrlen)) + if res < 0: + raise self.error_handler() + address.addrlen = addrlen.value + return address + + def listen(self, backlog): + """Enable a server to accept connections. The backlog argument + must be at least 1; it specifies the number of unaccepted connections + that the system will allow before refusing new connections.""" + if backlog < 1: + backlog = 1 + res = _c.socketlisten(self.fd, backlog) + if res < 0: + raise self.error_handler() + + def recv(self, nbytes, flags=0): + """Receive up to buffersize bytes from the socket. For the optional + flags argument, see the Unix manual. When no data is available, block + until at least one byte is available or until the remote end is closed. + When the remote end is closed and all data is read, return the empty + string.""" + IN-PROGRESS + +# ____________________________________________________________ + +def make_socket(fd, family, type, proto): + result = instantiate(RSocket) + result.fd = fd + result.family = family + result.type = type + result.proto = proto + return result From arigo at codespeak.net Fri Sep 22 23:20:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Sep 2006 23:20:00 +0200 (CEST) Subject: [pypy-svn] r32599 - in pypy/dist/pypy: module/_socket module/_socket/test rpython/rctypes/socketmodule Message-ID: <20060922212000.2AAA810063@code0.codespeak.net> Author: arigo Date: Fri Sep 22 23:19:57 2006 New Revision: 32599 Added: pypy/dist/pypy/module/_socket/test/test_rsocket.py (contents, props changed) Modified: pypy/dist/pypy/module/_socket/rsocket.py pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Log: More on rsocket. Time to switch to test-driven development... Modified: pypy/dist/pypy/module/_socket/rsocket.py ============================================================================== --- pypy/dist/pypy/module/_socket/rsocket.py (original) +++ pypy/dist/pypy/module/_socket/rsocket.py Fri Sep 22 23:19:57 2006 @@ -7,6 +7,9 @@ # ------------ IN - PROGRESS ----------- from pypy.rpython.objectmodel import instantiate +from pypy.rpython.rctypes.socketmodule import ctypes_socket as _c # MOVE ME +from ctypes import cast, POINTER, c_char, c_char_p, pointer, byref +from ctypes import create_string_buffer, sizeof class Address(object): @@ -28,7 +31,7 @@ # If we don't know the address family, don't raise an # exception -- return it as a tuple. family = self.addr.sa_family - buf = copy_buffer(cast(pointer(self.addr.sa_data), POINTER(char)), + buf = copy_buffer(cast(pointer(self.addr.sa_data), POINTER(c_char)), self.addrlen - offsetof(_c.sockaddr_un, 'sa_data')) return space.newtuple([space.wrap(family), space.wrap(buf.raw)]) @@ -66,7 +69,7 @@ if info.ai_next: raise SocketError("wildcard resolved to " "multiple addresses") - self.raw_to_addr(cast(info.ai_addr, POINTER(char)), + self.raw_to_addr(cast(info.ai_addr, POINTER(c_char)), info.ai_addrlen) finally: _c.freeaddrinfo(res) @@ -105,7 +108,7 @@ raise GAIError(error) try: info = res.contents - self.raw_to_addr(cast(info.ai_addr, POINTER(char)), + self.raw_to_addr(cast(info.ai_addr, POINTER(c_char)), info.ai_addrlen) finally: _c.freeaddrinfo(res) @@ -116,7 +119,7 @@ # (with variable size numbers). buf = create_string_buffer(_c.NI_MAXHOST) error = _c.getnameinfo(byref(self.addr), self.addrlen, - byref(buf), _c.NI_MAXHOST, + buf, _c.NI_MAXHOST, None, 0, _c.NI_NUMERICHOST) if error: raise GAIError(error) @@ -247,7 +250,7 @@ a = self.as_sockaddr_un() if _c.linux and a.sun_path[0] == '\x00': # Linux abstract namespace - buf = copy_buffer(cast(pointer(a.sun_path), POINTER(char)), + buf = copy_buffer(cast(pointer(a.sun_path), POINTER(c_char)), self.addrlen - offsetof(_c.sockaddr_un, 'sun_path')) return buf.raw else: @@ -293,7 +296,7 @@ def copy_buffer(ptr, size): buf = create_string_buffer(size) for i in range(size): - buf[i] = ptr.contents[i] + buf[i] = ptr[i] return buf # ____________________________________________________________ @@ -306,13 +309,16 @@ """Create a new socket.""" fd = _c.socket(family, type, proto) if _c.invalid_socket(fd): - raise last_error() + raise self.error_handler() # PLAT RISCOS self.fd = fd self.family = family self.type = type self.proto = proto + def error_handler(self): + return CSocketError(_c.errno()) + # convert an Address into an app-level object def addr_as_object(self, space, address): return address.as_object(space) @@ -353,9 +359,17 @@ def connect(self, address): """Connect the socket to a remote address.""" res = _c.socketconnect(self.fd, byref(address.addr), address.addrlen) - if res < 0: + if res != 0: raise self.error_handler() + def connect_ex(self, address): + """This is like connect(address), but returns an error code (the errno + value) instead of raising an exception when an error occurs.""" + return _c.socketconnect(self.fd, byref(address.addr), address.addrlen) + + def fileno(self): + return self.fd + def getsockname(self): """Return the address of the local endpoint.""" address = self.null_addr() @@ -388,13 +402,65 @@ if res < 0: raise self.error_handler() - def recv(self, nbytes, flags=0): + def recv(self, buffersize, flags=0): """Receive up to buffersize bytes from the socket. For the optional flags argument, see the Unix manual. When no data is available, block until at least one byte is available or until the remote end is closed. When the remote end is closed and all data is read, return the empty string.""" - IN-PROGRESS + buf = create_string_buffer(buffersize) + read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags) + if read_bytes < 0: + raise self.error_handler() + return buf[:read_bytes] + + def recvfrom(self, buffersize, flags=0): + """Like recv(buffersize, flags) but also return the sender's + address.""" + buf = create_string_buffer(buffersize) + address = self.null_addr() + addrlen = _c.socklen_t() + read_bytes = _c.socketrecvfrom(self.fd, buf, buffersize, flags, + byref(address.addr), byref(addrlen)) + if read_bytes < 0: + raise self.error_handler() + address.addrlen = addrlen.value + return (buf[:read_bytes], address) + + def send(self, data, flags=0): + """Send a data string to the socket. For the optional flags + argument, see the Unix manual. Return the number of bytes + sent; this may be less than len(data) if the network is busy.""" + res = _c.socketsend(self.fd, data, len(data), flags) + if res < 0: + raise self.error_handler() + return res + + def sendall(self, data, flags=0): + """Send a data string to the socket. For the optional flags + argument, see the Unix manual. This calls send() repeatedly + until all data is sent. If an error occurs, it's impossible + to tell how much data has been sent.""" + while data: + res = self.send(data, flags) + data = data[res:] + + def sendto(self, data, flags, address): + """Like send(data, flags) but allows specifying the destination + address. (Note that 'flags' is mandatory here.)""" + res = _c.socketsendto(self.fd, data, len(data), flags, + byref(address.addr), address.addrlen) + if res < 0: + raise self.error_handler() + return res + + def shutdown(self, how): + """Shut down the reading side of the socket (flag == SHUT_RD), the + writing side of the socket (flag == SHUT_WR), or both ends + (flag == SHUT_RDWR).""" + res = _c.socketshutdown(self.fd, how) + if res < 0: + raise self.error_handler() # ____________________________________________________________ @@ -405,3 +471,24 @@ result.type = type result.proto = proto return result + +class BaseSocketError(Exception): + pass + +class SocketError(BaseSocketError): + def __init__(self, message): + self.message = message + def __str__(self): + return self.message + +class CSocketError(BaseSocketError): + def __init__(self, errno): + self.errno = errno + def __str__(self): + return _c.socket_strerror(self.errno) + +class GAIError(BaseSocketError): + def __init__(self, errno): + self.errno = errno + def __str__(self): + return _c.gai_strerror(self.errno) Added: pypy/dist/pypy/module/_socket/test/test_rsocket.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_socket/test/test_rsocket.py Fri Sep 22 23:19:57 2006 @@ -0,0 +1,14 @@ +import py +from pypy.module._socket.rsocket import * + +def test_ipv4_addr(): + a = INETAddress("localhost", 4000) + assert a.get_host() == "127.0.0.1" + assert a.get_port() == 4000 + a = INETAddress("", 4001) + assert a.get_host() == "0.0.0.0" + assert a.get_port() == 4001 + a = INETAddress("", 47002) + assert a.get_host() == "255.255.255.255" + assert a.get_port() == 47002 + py.test.raises(GAIError, INETAddress, "no such host exists", 47003) Modified: pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py (original) +++ pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Fri Sep 22 23:19:57 2006 @@ -6,7 +6,7 @@ # Not used here, but exported for other code. from pypy.rpython.rctypes.aerrno import geterrno -from ctypes import c_ushort, c_int, c_uint, c_char_p, c_void_p +from ctypes import c_ushort, c_int, c_uint, c_char_p, c_void_p, c_char from ctypes import POINTER, ARRAY, cdll, sizeof, SetPointerType # Also not used here, but exported for other code. @@ -14,6 +14,7 @@ includes = ('sys/types.h', 'sys/socket.h', + 'sys/un.h', 'netinet/in.h', 'netinet/tcp.h', 'unistd.h', @@ -32,7 +33,11 @@ O_NONBLOCK = ctypes_platform.ConstantInteger('O_NONBLOCK') F_GETFL = ctypes_platform.ConstantInteger('F_GETFL') F_SETFL = ctypes_platform.ConstantInteger('F_SETFL') - + + linux = ctypes_platform.Defined('linux') + MS_WINDOWS = ctypes_platform.Defined('MS_WINDOWS') + INVALID_SOCKET = ctypes_platform.DefinedConstantInteger('INVALID_SOCKET') + constant_names = ['AF_APPLETALK', 'AF_ASH', 'AF_ATMPVC', 'AF_ATMSVC', 'AF_AX25', 'AF_BLUETOOTH', 'AF_BRIDGE', 'AF_ECONET', 'AF_INET', 'AF_INET6', 'AF_IPX', 'AF_IRDA', 'AF_KEY', 'AF_NETBEUI', 'AF_NETLINK', @@ -107,7 +112,7 @@ # struct types CConfig.sockaddr = ctypes_platform.Struct('struct sockaddr', [('sa_family', c_int), - ]) + ('sa_data', c_char * 0)]) sockaddr_ptr = POINTER('sockaddr') CConfig.in_addr = ctypes_platform.Struct('struct in_addr', [('s_addr', c_uint)]) @@ -116,10 +121,15 @@ ('sin_port', c_ushort), ('sin_addr', CConfig.in_addr)]) -CConfig.sockaddr_in6 = ctypes_platform.Struct('struct sockaddr_in6', - [('sin6_flowinfo', c_int), - ('sin6_scope_id', c_int), - ]) +CConfig.sockaddr_in6 = ctypes_platform.Struct('struct sockaddr_in6', + [('sin6_family', c_int), + ('sin6_flowinfo', c_int), + ('sin6_scope_id', c_int)]) + +CConfig.sockaddr_un = ctypes_platform.Struct('struct sockaddr_un', + [('sun_family', c_int), + ('sun_path', c_char * 0)]) + addrinfo_ptr = POINTER("addrinfo") CConfig.addrinfo = ctypes_platform.Struct('struct addrinfo', [('ai_flags', c_int), @@ -171,6 +181,17 @@ F_GETFL = cConfig.F_GETFL F_SETFL = cConfig.F_SETFL +linux = cConfig.linux +MS_WINDOWS = cConfig.MS_WINDOWS +if MS_WINDOWS: + def invalid_socket(fd): + return fd == INVALID_SOCKET + INVALID_SOCKET = cConfig.INVALID_SOCKET +else: + def invalid_socket(fd): + return fd < 0 + INVALID_SOCKET = -1 + uint16_t = cConfig.uint16_t uint32_t = cConfig.uint32_t size_t = cConfig.size_t @@ -180,6 +201,7 @@ sockaddr_size = sizeof(sockaddr) sockaddr_in = cConfig.sockaddr_in sockaddr_in6 = cConfig.sockaddr_in6 +sockaddr_un = cConfig.sockaddr_un in_addr = cConfig.in_addr in_addr_size = sizeof(in_addr) addrinfo = cConfig.addrinfo @@ -217,7 +239,12 @@ socket.argtypes = [c_int, c_int, c_int] socket.restype = c_int -socketclose = os.close +if MS_WINDOWS: + socketclose = socketdll.closesocket + socketclose.argtypes = [c_int] + socketclose.restype = c_int +else: + socketclose = os.close socketconnect = socketdll.connect socketconnect.argtypes = [c_int, sockaddr_ptr, socklen_t] @@ -262,10 +289,6 @@ inet_ntoa.argtypes = [in_addr] inet_ntoa.restype = c_char_p -close = socketdll.close -close.argtypes = [c_int] -close.restype = c_int - socketaccept = socketdll.accept socketaccept.argtypes = [c_int, sockaddr_ptr, POINTER(socklen_t)] socketaccept.restype = c_int @@ -367,3 +390,70 @@ shutdown = socketdll.shutdown shutdown.argtypes = [c_int, c_int] shutdown.restype = c_int + + +if MS_WINDOWS: + WIN32_ERROR_MESSAGES = { + errno.WSAEINTR: "Interrupted system call", + errno.WSAEBADF: "Bad file descriptor", + errno.WSAEACCES: "Permission denied", + errno.WSAEFAULT: "Bad address", + errno.WSAEINVAL: "Invalid argument", + errno.WSAEMFILE: "Too many open files", + errno.WSAEWOULDBLOCK: + "The socket operation could not complete without blocking", + errno.WSAEINPROGRESS: "Operation now in progress", + errno.WSAEALREADY: "Operation already in progress", + errno.WSAENOTSOCK: "Socket operation on non-socket", + errno.WSAEDESTADDRREQ: "Destination address required", + errno.WSAEMSGSIZE: "Message too long", + errno.WSAEPROTOTYPE: "Protocol wrong type for socket", + errno.WSAENOPROTOOPT: "Protocol not available", + errno.WSAEPROTONOSUPPORT: "Protocol not supported", + errno.WSAESOCKTNOSUPPORT: "Socket type not supported", + errno.WSAEOPNOTSUPP: "Operation not supported", + errno.WSAEPFNOSUPPORT: "Protocol family not supported", + errno.WSAEAFNOSUPPORT: "Address family not supported", + errno.WSAEADDRINUSE: "Address already in use", + errno.WSAEADDRNOTAVAIL: "Can't assign requested address", + errno.WSAENETDOWN: "Network is down", + errno.WSAENETUNREACH: "Network is unreachable", + errno.WSAENETRESET: "Network dropped connection on reset", + errno.WSAECONNABORTED: "Software caused connection abort", + errno.WSAECONNRESET: "Connection reset by peer", + errno.WSAENOBUFS: "No buffer space available", + errno.WSAEISCONN: "Socket is already connected", + errno.WSAENOTCONN: "Socket is not connected", + errno.WSAESHUTDOWN: "Can't send after socket shutdown", + errno.WSAETOOMANYREFS: "Too many references: can't splice", + errno.WSAETIMEDOUT: "Operation timed out", + errno.WSAECONNREFUSED: "Connection refused", + errno.WSAELOOP: "Too many levels of symbolic links", + errno.WSAENAMETOOLONG: "File name too long", + errno.WSAEHOSTDOWN: "Host is down", + errno.WSAEHOSTUNREACH: "No route to host", + errno.WSAENOTEMPTY: "Directory not empty", + errno.WSAEPROCLIM: "Too many processes", + errno.WSAEUSERS: "Too many users", + errno.WSAEDQUOT: "Disc quota exceeded", + errno.WSAESTALE: "Stale NFS file handle", + errno.WSAEREMOTE: "Too many levels of remote in path", + errno.WSASYSNOTREADY: "Network subsystem is unvailable", + errno.WSAVERNOTSUPPORTED: "WinSock version is not supported", + errno.WSANOTINITIALISED: "Successful WSAStartup() not yet performed", + errno.WSAEDISCON: "Graceful shutdown in progress", + + # Resolver errors + # XXX Not exported by errno. Replace by the values in winsock.h + # errno.WSAHOST_NOT_FOUND: "No such host is known", + # errno.WSATRY_AGAIN: "Host not found, or server failed", + # errno.WSANO_RECOVERY: "Unexpected server error encountered", + # errno.WSANO_DATA: "Valid name without requested data", + # errno.WSANO_ADDRESS: "No address, look for MX record", + } + + def socket_strerror(errno): + return WIN32_ERROR_MESSAGES.get(errno, "winsock error") +else: + def socket_strerror(errno): + return strerror(errno) From arigo at codespeak.net Sat Sep 23 15:02:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 23 Sep 2006 15:02:02 +0200 (CEST) Subject: [pypy-svn] r32606 - pypy/branch/method-cache Message-ID: <20060923130202.15A361006E@code0.codespeak.net> Author: arigo Date: Sat Sep 23 15:02:01 2006 New Revision: 32606 Added: pypy/branch/method-cache/ - copied from r32605, pypy/dist/ Log: A branch to experiment with method resolution caches in the bytecode. From arigo at codespeak.net Sat Sep 23 15:05:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 23 Sep 2006 15:05:04 +0200 (CEST) Subject: [pypy-svn] r32607 - in pypy/branch/method-cache/pypy: interpreter interpreter/astcompiler objspace/std tool Message-ID: <20060923130504.B022A1006E@code0.codespeak.net> Author: arigo Date: Sat Sep 23 15:05:01 2006 New Revision: 32607 Added: pypy/branch/method-cache/pypy/interpreter/methodcache.py (contents, props changed) Modified: pypy/branch/method-cache/pypy/interpreter/astcompiler/pyassem.py pypy/branch/method-cache/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/method-cache/pypy/interpreter/pyopcode.py pypy/branch/method-cache/pypy/objspace/std/objspace.py pypy/branch/method-cache/pypy/objspace/std/typeobject.py pypy/branch/method-cache/pypy/objspace/std/typetype.py pypy/branch/method-cache/pypy/tool/stdlib_opcode.py Log: First version. Still to do: - think about interaction with other objspaces than the std - marshal the MethodCache constants - in pyassem, get the value stack depth right Modified: pypy/branch/method-cache/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/method-cache/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/method-cache/pypy/interpreter/astcompiler/pyassem.py Sat Sep 23 15:05:01 2006 @@ -705,7 +705,6 @@ def _lookupConst(self, w_obj, list_w): space = self.space - w_obj_type = space.type(w_obj) for i in range(len(list_w)): if self._cmpConsts(w_obj, list_w[i]): return i @@ -776,7 +775,18 @@ arg = inst.name index = self._cmp.index(arg) return InstrInt(inst.op, index) - + + def _convert_CALL_METHOD(self, inst): + assert isinstance(inst, InstrObj) + w_cache = inst.obj + index = self._lookupConst(w_cache, self.consts) + return InstrInt(inst.op, index) + + _convert_CALL_METHOD_KW = _convert_CALL_METHOD + _convert_CALL_METHOD_VAR = _convert_CALL_METHOD + _convert_CALL_METHOD_VAR_KW = _convert_CALL_METHOD + _convert_CALL_METHOD_FAST = _convert_CALL_METHOD + # similarly for other opcodes... @@ -980,6 +990,7 @@ # XXX 1. need to keep track of stack depth on jumps # XXX 2. at least partly as a result, this code is broken # XXX 3. Don't need a class here! + # XXX CALL_METHOD_* NOT TRACKED YET, we get a bad but safe upper bound def findDepth(self, insts, debug=0): depth = 0 Modified: pypy/branch/method-cache/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/method-cache/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/method-cache/pypy/interpreter/astcompiler/pycodegen.py Sat Sep 23 15:05:01 2006 @@ -13,6 +13,7 @@ CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, \ CO_FUTURE_DIVISION, CO_FUTURE_WITH_STATEMENT from pypy.interpreter.pyparser.error import SyntaxError +from pypy.interpreter.methodcache import MethodCache # drop VERSION dependency since it the ast transformer for 2.4 doesn't work with 2.3 anyway VERSION = 2 @@ -24,6 +25,13 @@ "CALL_FUNCTION_VAR", "CALL_FUNCTION_VAR_KW", ] +callmeth_opcode_info = [ + # (Have *args, Have **args) : opcode + "CALL_METHOD", + "CALL_METHOD_KW", + "CALL_METHOD_VAR", + "CALL_METHOD_VAR_KW", +] LOOP = 1 EXCEPT = 2 @@ -1032,7 +1040,12 @@ pos = 0 kw = 0 self.set_lineno(node) - node.node.accept( self ) + is_method = isinstance(node.node, ast.Getattr) + if is_method: + # special case for calls that "look like" method calls + node.node.expr.accept( self ) + else: + node.node.accept( self ) for arg in node.args: arg.accept( self ) if isinstance(arg, ast.Keyword): @@ -1045,8 +1058,17 @@ node.dstar_args.accept( self ) have_star = node.star_args is not None have_dstar = node.dstar_args is not None - opcode = callfunc_opcode_info[ have_star*2 + have_dstar] - self.emitop_int(opcode, kw << 8 | pos) + argkwcount = kw << 8 | pos + if is_method: + if not have_star and not have_dstar and not kw: + opcode = 'CALL_METHOD_FAST' + else: + opcode = callmeth_opcode_info[ have_star*2 + have_dstar] + cache = MethodCache(node.node.attrname, argkwcount) + self.emitop_obj(opcode, self.space.wrap(cache)) + else: + opcode = callfunc_opcode_info[ have_star*2 + have_dstar] + self.emitop_int(opcode, argkwcount) def visitPrint(self, node): self.set_lineno(node) Added: pypy/branch/method-cache/pypy/interpreter/methodcache.py ============================================================================== --- (empty file) +++ pypy/branch/method-cache/pypy/interpreter/methodcache.py Sat Sep 23 15:05:01 2006 @@ -0,0 +1,70 @@ +""" +""" + +from pypy.interpreter import baseobjspace, typedef +from pypy.interpreter.function import Function + + +class MethodCache(baseobjspace.Wrappable): + + cached_tag = None + w_cached_function = None + + def __init__(self, attrname, argkwcount): + self.attrname = attrname + self.argkwcount = argkwcount + + def load_cache(self, space, w_type, version_tag): + w_class, w_value = space.lookup_in_type_where(w_type, + '__getattribute__') + if w_class is not None and space.is_w(w_class, space.w_object): + # no special __getattribute__, so we can perform the + # lookup of the attrname in the usual way + w_class, w_value = space.lookup_in_type_where(w_type, + self.attrname) + if type(w_value) is Function: + # cache the Function object + self.cached_tag = version_tag + self.w_cached_function = w_value + return True + # not the common case - no caching + self.cached_tag = None + self.w_cached_function = None + return False + + def call_args(self, space, w_obj, args): + w_type = space.type(w_obj) + version_tag = space.gettypeversion(w_type) + if version_tag is self.cached_tag or self.load_cache(space, w_type, + version_tag): + w_value = w_obj.getdictvalue_w(space, self.attrname) + if w_value is None: + # no method shadowing (this is the common situation that we + # are trying to make as fast as possible) + args = args.prepend(w_obj) + return space.call_args(self.w_cached_function, args) + else: + # fallback + w_value = space.getattr(w_obj, space.wrap(self.attrname)) + return space.call_args(w_value, args) + + def call_valuestack(self, space, valuestack): + nargs = self.argkwcount + w_obj = valuestack.top(nargs) + w_type = space.type(w_obj) + version_tag = space.gettypeversion(w_type) + if version_tag is self.cached_tag or self.load_cache(space, w_type, + version_tag): + w_value = w_obj.getdictvalue_w(space, self.attrname) + if w_value is None: + # no method shadowing (this is the common situation that we + # are trying to make as fast as possible) + return self.w_cached_function.funccall_valuestack(nargs + 1, + valuestack) + else: + # fallback + w_value = space.getattr(w_obj, space.wrap(self.attrname)) + return space.call_valuestack(w_value, nargs, valuestack) + + +MethodCache.typedef = typedef.TypeDef("method_cache") Modified: pypy/branch/method-cache/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/method-cache/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/method-cache/pypy/interpreter/pyopcode.py Sat Sep 23 15:05:01 2006 @@ -684,9 +684,9 @@ def CALL_FUNCTION(f, oparg): # XXX start of hack for performance - if (oparg >> 8) & 0xff == 0: + if oparg <= 0xff: # Only positional arguments - nargs = oparg & 0xff + nargs = oparg w_function = f.valuestack.top(nargs) try: w_result = f.space.call_valuestack(w_function, nargs, f.valuestack) @@ -712,6 +712,57 @@ w_varargs = f.valuestack.pop() f.call_function(oparg, w_varargs, w_varkw) + def CALL_METHOD(f, constindex, w_star=None, w_starstar=None): + from pypy.interpreter.methodcache import MethodCache + w_methodcache = f.getconstant_w(constindex) + methodcache = f.space.interp_w(MethodCache, w_methodcache) + oparg = methodcache.argkwcount + n_arguments = oparg & 0xff + n_keywords = (oparg>>8) & 0xff + keywords = None + if n_keywords: + keywords = {} + for i in range(n_keywords): + w_value = f.valuestack.pop() + w_key = f.valuestack.pop() + key = f.space.str_w(w_key) + keywords[key] = w_value + arguments = [None] * n_arguments + for i in range(n_arguments - 1, -1, -1): + arguments[i] = f.valuestack.pop() + args = Arguments(f.space, arguments, keywords, w_star, w_starstar) + w_self = f.valuestack.pop() + w_result = methodcache.call_args(f.space, w_self, args) + #rstack.resume_point("call_function", f, returns=w_result) XXX + f.valuestack.push(w_result) + + def CALL_METHOD_VAR(f, oparg): + w_varargs = f.valuestack.pop() + f.CALL_METHOD(oparg, w_varargs, None) + + def CALL_METHOD_KW(f, oparg): + w_varkw = f.valuestack.pop() + f.CALL_METHOD(oparg, None, w_varkw) + + def CALL_METHOD_VAR_KW(f, oparg): + w_varkw = f.valuestack.pop() + w_varargs = f.valuestack.pop() + f.CALL_METHOD(oparg, w_varargs, w_varkw) + + def CALL_METHOD_FAST(f, constindex): + # Only positional arguments + from pypy.interpreter.methodcache import MethodCache + w_methodcache = f.getconstant_w(constindex) + methodcache = f.space.interp_w(MethodCache, w_methodcache) + nargs = methodcache.argkwcount + try: + w_result = methodcache.call_valuestack(f.space, f.valuestack) + #rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result) + # XXX + finally: + f.valuestack.drop(nargs + 1) + f.valuestack.push(w_result) + def MAKE_FUNCTION(f, numdefaults): w_codeobj = f.valuestack.pop() codeobj = f.space.interp_w(PyCode, w_codeobj) @@ -735,6 +786,7 @@ def LIST_APPEND(f): w = f.valuestack.pop() v = f.valuestack.pop() + # XXX could use a MethodCache here too, or even something more direct f.space.call_method(v, 'append', w) def SET_LINENO(f, lineno): Modified: pypy/branch/method-cache/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/method-cache/pypy/objspace/std/objspace.py (original) +++ pypy/branch/method-cache/pypy/objspace/std/objspace.py Sat Sep 23 15:05:01 2006 @@ -259,6 +259,10 @@ # unique-for-this-space W_TypeObject instance return self.fromcache(stdtypedef.TypeCache).getorbuild(typedef) + def gettypeversion(self, w_type): + assert isinstance(w_type, W_TypeObject) + return w_type.version_tag + def wrap(self, x): "Wraps the Python value 'x' into one of the wrapper classes." # You might notice that this function is rather conspicuously Modified: pypy/branch/method-cache/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/branch/method-cache/pypy/objspace/std/typeobject.py (original) +++ pypy/branch/method-cache/pypy/objspace/std/typeobject.py Sat Sep 23 15:05:01 2006 @@ -38,6 +38,11 @@ return "_%s%s" % (klass, name) + +class VersionTag(object): + pass + + class W_TypeObject(W_Object): from pypy.objspace.std.typetype import type_typedef as typedef @@ -207,6 +212,7 @@ w_self.mro_w = space.unpackiterable(w_mro) return w_self.mro_w = w_self.compute_mro() + w_self.mutated() def ready(w_self): for w_base in w_self.bases_w: @@ -214,6 +220,11 @@ continue w_base.add_subclass(w_self) + def mutated(w_self): + """Relevant changes are only the ones that change the result + of a lookup(), i.e. changes to dict_w or mro_w.""" + w_self.version_tag = VersionTag() + # compute the most parent class with the same layout as us def get_layout(w_self): w_bestbase = w_self.w_bestbase @@ -407,6 +418,7 @@ space.set(w_descr, w_type, w_value) return w_type.dict_w[name] = w_value + w_type.mutated() def delattr__Type_ANY(space, w_type, w_name): if w_type.lazyloaders: @@ -419,9 +431,10 @@ return try: del w_type.dict_w[name] - return except KeyError: raise OperationError(space.w_AttributeError, w_name) + else: + w_type.mutated() # ____________________________________________________________ Modified: pypy/branch/method-cache/pypy/objspace/std/typetype.py ============================================================================== --- pypy/branch/method-cache/pypy/objspace/std/typetype.py (original) +++ pypy/branch/method-cache/pypy/objspace/std/typetype.py Sat Sep 23 15:05:01 2006 @@ -139,6 +139,7 @@ space.wrap("can't set %s.__module__" % w_type.name)) w_type.dict_w['__module__'] = w_value + w_type.mutated() def descr___subclasses__(space, w_type): """Return the list of immediate subclasses.""" Modified: pypy/branch/method-cache/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/branch/method-cache/pypy/tool/stdlib_opcode.py (original) +++ pypy/branch/method-cache/pypy/tool/stdlib_opcode.py Sat Sep 23 15:05:01 2006 @@ -5,5 +5,18 @@ opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.4.1/opcode.py') execfile(str(opcode_path), globals()) + # __________ extra opcodes __________ + + def def_op(name, op): + opname[op] = name + opmap[name] = op + + def_op('CALL_METHOD', 192) + def_op('CALL_METHOD_VAR', 193) + def_op('CALL_METHOD_KW', 194) + def_op('CALL_METHOD_VAR_KW', 195) + def_op('CALL_METHOD_FAST', 196) + + load_opcode() del load_opcode From mwh at codespeak.net Sat Sep 23 18:40:15 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 23 Sep 2006 18:40:15 +0200 (CEST) Subject: [pypy-svn] r32611 - in pypy/dist/pypy/translator/c: . test Message-ID: <20060923164015.DB4D410060@code0.codespeak.net> Author: mwh Date: Sat Sep 23 18:40:14 2006 New Revision: 32611 Modified: pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/test/test_lltyped.py Log: make constant sizeof(something containing an array of Void)s compile and give likely sounding results. Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Sat Sep 23 18:40:14 2006 @@ -21,14 +21,19 @@ cdecl(db.gettype(value.TYPE), ''), structnode.c_struct_field_name(value.fldname)) elif isinstance(value, ItemOffset): - return '(sizeof(%s) * %s)'%( - cdecl(db.gettype(value.TYPE), ''), value.repeat) + if value.TYPE != Void: + return '(sizeof(%s) * %s)'%( + cdecl(db.gettype(value.TYPE), ''), value.repeat) + else: + return '0' elif isinstance(value, ArrayItemsOffset): if isinstance(value.TYPE, FixedSizeArray): return '0' - else: + elif value.TYPE.OF != Void: return 'offsetof(%s, items)'%( cdecl(db.gettype(value.TYPE), '')) + else: + return 'sizeof(%s)'%(cdecl(db.gettype(value.TYPE), ''),) elif isinstance(value, ArrayLengthOffset): return 'offsetof(%s, length)'%( cdecl(db.gettype(value.TYPE), '')) Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Sat Sep 23 18:40:14 2006 @@ -251,3 +251,18 @@ fn = self.getcompiled(llf) res = fn(0x33) assert res in [0x1033, 0x3320] + + def test_sizeof_void_array(self): + from pypy.rpython.lltypesystem import llmemory + A = Array(Void) + size1 = llmemory.sizeof(A, 1) + size2 = llmemory.sizeof(A, 14) + def f(x=int): + if x: + return size1 + else: + return size2 + fn = self.getcompiled(f) + res1 = fn(1) + res2 = fn(0) + assert res1 == res2 From mwh at codespeak.net Sun Sep 24 01:06:36 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 24 Sep 2006 01:06:36 +0200 (CEST) Subject: [pypy-svn] r32613 - in pypy/dist/pypy/rpython: . lltypesystem memory memory/test Message-ID: <20060923230636.2D06C1006E@code0.codespeak.net> Author: mwh Date: Sun Sep 24 01:06:32 2006 New Revision: 32613 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/test/test_gctransform.py Log: so this started out with an attempt to make it possible to llinterp the output of the refcountinggctransformer. along the way i: * implemented raw_memclear for llinterped objects far more thoroughly * changed the refcountinggctransformer to only rely on an implementation of raw_malloc from the backend * found out once again that refcounting builds take ages and produce slow binaries. it would be nice if someone could read op_gc_call_rtti_destructor and check it for sanity Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun Sep 24 01:06:32 2006 @@ -632,7 +632,9 @@ gc.collect() def op_gc_free(self, addr): - raise NotImplementedError("gc_free") + # what can you do? + pass + #raise NotImplementedError("gc_free") def op_gc_fetch_exception(self): raise NotImplementedError("gc_fetch_exception") @@ -641,7 +643,10 @@ raise NotImplementedError("gc_restore_exception") def op_gc_call_rtti_destructor(self, rtti, addr): - raise NotImplementedError("gc_call_rtti_destructor") + if hasattr(rtti._obj, 'destructor_funcptr'): + d = rtti._obj.destructor_funcptr + ob = addr.get() + return self.op_direct_call(d, ob) def op_gc_deallocate(self, TYPE, addr): raise NotImplementedError("gc_deallocate") Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sun Sep 24 01:06:32 2006 @@ -24,6 +24,8 @@ def raw_malloc(self, rest): raise NotImplementedError("raw_malloc(%r, %r)" % (self, rest)) + def raw_memclear(self, adr): + raise NotImplementedError("raw_memclear(%r, %r)" % (self, adr)) class ItemOffset(AddressOffset): @@ -64,6 +66,25 @@ array_adr = cast_ptr_to_adr(p) return array_adr + ArrayItemsOffset(T) + def raw_memclear(self, adr): + if (isinstance(self.TYPE, lltype.ContainerType) and self.repeat == 1): + from pypy.rpython.rctypes.rmodel import reccopy + fresh = lltype.malloc(self.TYPE, flavor='raw', zero=True) + reccopy(fresh, adr.get()) + else: + assert adr.offset is not None + if isinstance(adr.offset, ArrayItemsOffset): + array = adr.ob + elif isinstance(adr.offset, CompositeOffset): + array = (adr + -adr.offset.offsets[-1]).get() + if isinstance(self.TYPE, lltype.ContainerType): + fresh = lltype.malloc(self.TYPE, flavor='raw', zero=True) + for i in range(self.repeat): + reccopy(fresh, array[i]) + else: + for i in range(self.repeat): + array[i] = self.TYPE._defl() + class FieldOffset(AddressOffset): @@ -86,6 +107,22 @@ assert rest return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE) + def raw_memclear(self, adr): + if self.fldname != self.TYPE._arrayfld: + return AddressOffset.raw_memclear(adr) # for the error msg + structptr = adr.get() + for name in self.TYPE._names[:-1]: + FIELDTYPE = getattr(self.TYPE, name) + if isinstance(FIELDTYPE, lltype.ContainerType): + fresh = lltype.malloc(FIELDTYPE, raw=True, zero=True) + from pypy.rpython.rctypes.rmodel import reccopy + fresh = lltype.malloc(self.TYPE, flavor='raw', zero=True) + reccopy(fresh, getattr(structptr, name)._obj) + else: + setattr(structptr, name, FIELDTYPE._defl()) + + + class CompositeOffset(AddressOffset): @@ -125,6 +162,12 @@ def raw_malloc(self, rest): return self.offsets[0].raw_malloc(self.offsets[1:] + rest) + def raw_memclear(self, adr): + for o in self.offsets[:-1]: + o.raw_memclear(adr) + adr += o + o.raw_memclear(adr) + class ArrayItemsOffset(AddressOffset): @@ -153,6 +196,10 @@ immortal = self.TYPE._gckind == 'raw') return cast_ptr_to_adr(p) + def raw_memclear(self, adr): + # should really zero out the length field, but we can't + pass + class ArrayLengthOffset(AddressOffset): @@ -191,6 +238,9 @@ headerptr = self.gcheaderbuilder.new_header(gcobjadr.get()) return cast_ptr_to_adr(headerptr) + def raw_memclear(self, adr): + headerptr = adr.get() + sizeof(lltype.typeOf(headerptr).TO).raw_memclear(cast_ptr_to_adr(headerptr)) class GCHeaderAntiOffset(AddressOffset): def __init__(self, gcheaderbuilder): @@ -560,15 +610,10 @@ return size def raw_memclear(adr, size): - # hack hack hack - # stab stab stab - assert (adr.offset is None or - (isinstance(adr.offset, ArrayItemsOffset) - and isinstance(lltype.typeOf(adr.ob).TO, lltype.FixedSizeArray))) - TYPE = lltype.typeOf(adr.ob) - fresh = lltype.malloc(TYPE.TO, zero=True, flavor='raw') - from pypy.rpython.rctypes.rmodel import reccopy - reccopy(fresh, adr.ob) + if not isinstance(size, AddressOffset): + raise NotImplementedError(size) + assert lltype.typeOf(adr) == Address + size.raw_memclear(adr) def raw_memcopy(source, dest, size): source = source.get() Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun Sep 24 01:06:32 2006 @@ -21,7 +21,9 @@ from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.rtyper import LowLevelOpList -import sets, os +from pypy.rpython.rbuiltin import gen_cast +from pypy.rpython.rarithmetic import ovfcheck +import sets, os, sys def var_ispyobj(var): if hasattr(var, 'concretetype'): @@ -425,27 +427,51 @@ gc_header_offset = self.gcheaderbuilder.size_gc_header self.deallocator_graphs_needing_transforming = [] # create incref graph + HDRPTR = lltype.Ptr(self.HDR) def ll_incref(adr): if adr: - gcheader = adr - gc_header_offset - gcheader.signed[0] = gcheader.signed[0] + 1 + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) + gcheader.refcount = gcheader.refcount + 1 def ll_decref(adr, dealloc): if adr: - gcheader = adr - gc_header_offset - refcount = gcheader.signed[0] - 1 - gcheader.signed[0] = refcount + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) + refcount = gcheader.refcount - 1 + gcheader.refcount = refcount if refcount == 0: dealloc(adr) def ll_decref_simple(adr): if adr: - gcheader = adr - gc_header_offset - refcount = gcheader.signed[0] - 1 + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) + refcount = gcheader.refcount - 1 if refcount == 0: llop.gc_free(lltype.Void, adr) else: - gcheader.signed[0] = refcount + gcheader.refcount = refcount def ll_no_pointer_dealloc(adr): llop.gc_free(lltype.Void, adr) + + def ll_malloc_fixedsize(size): + size = gc_header_offset + size + result = lladdress.raw_malloc(size) + lladdress.raw_memclear(result, size) + result += gc_header_offset + return result + def ll_malloc_varsize_no_length(length, size, itemsize): + try: + fixsize = gc_header_offset + size + varsize = ovfcheck(itemsize * length) + tot_size = ovfcheck(fixsize + varsize) + except OverflowError: + raise MemoryError + result = lladdress.raw_malloc(tot_size) + lladdress.raw_memclear(result, tot_size) + result += gc_header_offset + return result + def ll_malloc_varsize(length, size, itemsize, lengthoffset): + result = ll_malloc_varsize_no_length(length, size, itemsize) + (result + lengthoffset).signed[0] = length + return result + if self.translator: self.increfptr = self.inittime_helper( ll_incref, [llmemory.Address], lltype.Void) @@ -456,6 +482,12 @@ ll_decref_simple, [llmemory.Address], lltype.Void) self.no_pointer_dealloc_ptr = self.inittime_helper( ll_no_pointer_dealloc, [llmemory.Address], lltype.Void) + self.malloc_fixedsize_ptr = self.inittime_helper( + ll_malloc_fixedsize, [lltype.Signed], llmemory.Address) + self.malloc_varsize_no_length_ptr = self.inittime_helper( + ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address) + self.malloc_varsize_ptr = self.inittime_helper( + ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address) self.mixlevelannotator.finish() # for now # cache graphs: self.decref_funcptrs = {} @@ -526,12 +558,63 @@ result.extend(self.pop_alive(oldval)) return result -## -- maybe add this for tests and for consistency -- -## def consider_constant(self, TYPE, value): -## p = value._as_ptr() -## if not self.gcheaderbuilder.get_header(p): -## hdr = new_header(p) -## hdr.refcount = sys.maxint // 2 + def replace_malloc(self, op, livevars, block): + TYPE = op.result.concretetype.TO + assert not TYPE._is_varsize() + c_size = Constant(llmemory.sizeof(TYPE), lltype.Signed) + ops = [] + v_raw = varoftype(llmemory.Address) + return [SpaceOperation("direct_call", + [self.malloc_fixedsize_ptr, c_size], + v_raw), + SpaceOperation("cast_adr_to_ptr", + [v_raw], + op.result)] + + def replace_malloc_varsize(self, op, livevars, block): + def intconst(c): return Constant(c, lltype.Signed) + + TYPE = op.result.concretetype.TO + assert TYPE._is_varsize() + + c_const_size = intconst(llmemory.sizeof(TYPE, 0)) + if isinstance(TYPE, lltype.Struct): + ARRAY = TYPE._flds[TYPE._arrayfld] + else: + ARRAY = TYPE + assert isinstance(ARRAY, lltype.Array) + c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) + + ops = [] + v_raw = varoftype(llmemory.Address) + if ARRAY._hints.get("nolength", False): + ops.append( + SpaceOperation("direct_call", + [self.malloc_varsize_no_length_ptr, op.args[-1], + c_const_size, c_item_size], + v_raw)) + else: + if isinstance(TYPE, lltype.Struct): + offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + llmemory.ArrayLengthOffset(ARRAY) + else: + offset_to_length = llmemory.ArrayLengthOffset(ARRAY) + ops.append( + SpaceOperation("direct_call", + [self.malloc_varsize_ptr, op.args[-1], + c_const_size, c_item_size, intconst(offset_to_length)], + v_raw)) + + ops.append(SpaceOperation("cast_adr_to_ptr", [v_raw], op.result)) + return ops + + def consider_constant(self, TYPE, value): + if value is not lltype.top_container(value): + return + if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)): + p = value._as_ptr() + if not self.gcheaderbuilder.get_header(p): + hdr = self.gcheaderbuilder.new_header(p) + hdr.refcount = sys.maxint // 2 def static_deallocation_funcptr_for_type(self, TYPE): if TYPE in self.static_deallocator_funcptrs: @@ -559,13 +642,13 @@ exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE) try: v = cast_adr_to_ptr(addr, PTR_TYPE) - gcheader = addr - gc_header_offset + gcheader = cast_adr_to_ptr(addr - gc_header_offset, HDRPTR) # refcount is at zero, temporarily bump it to 1: - gcheader.signed[0] = 1 + gcheader.refcount = 1 destr_v = cast_pointer(DESTR_ARG, v) ll_call_destructor(destrptr, destr_v) - refcount = gcheader.signed[0] - 1 - gcheader.signed[0] = refcount + refcount = gcheader.refcount - 1 + gcheader.refcount = refcount if refcount == 0: %s llop.gc_free(lltype.Void, addr) @@ -591,7 +674,8 @@ 'PTR_TYPE': lltype.Ptr(TYPE), 'DESTR_ARG': DESTR_ARG, 'EXC_INSTANCE_TYPE': self.translator.rtyper.exceptiondata.lltype_of_exception_value, - 'll_call_destructor': ll_call_destructor} + 'll_call_destructor': ll_call_destructor, + 'HDRPTR':lltype.Ptr(self.HDR)} exec src in d this = d['ll_deallocator'] fptr = self.annotate_helper(this, [llmemory.Address], lltype.Void) @@ -620,11 +704,11 @@ gc_header_offset = self.gcheaderbuilder.size_gc_header def ll_dealloc(addr): # bump refcount to 1 - gcheader = addr - gc_header_offset - gcheader.signed[0] = 1 + gcheader = llmemory.cast_adr_to_ptr(addr - gc_header_offset, lltype.Ptr(self.HDR)) + gcheader.refcount = 1 v = llmemory.cast_adr_to_ptr(addr, QUERY_ARG_TYPE) rtti = queryptr(v) - gcheader.signed[0] = 0 + gcheader.refcount = 0 llop.gc_call_rtti_destructor(lltype.Void, rtti, addr) fptr = self.annotate_helper(ll_dealloc, [llmemory.Address], lltype.Void) self.dynamic_deallocator_funcptrs[TYPE] = fptr Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py Sun Sep 24 01:06:32 2006 @@ -69,9 +69,9 @@ def rtype_and_transform(func, inputtypes, transformcls, specialize=True, check=True): t = rtype(func, inputtypes, specialize) + transformer = transformcls(t) etrafo = ExceptionTransformer(t) etrafo.transform_completely() - transformer = transformcls(t) graphs_borrowed = {} for graph in t.graphs: graphs_borrowed[graph] = transformer.transform_graph(graph) @@ -586,7 +586,8 @@ t, transformer = rtype_and_transform( f, [int], gctransform.RefcountingGCTransformer, check=False) fgraph = graphof(t, f) - TYPE = fgraph.startblock.operations[0].result.concretetype.TO + s_instance = t.annotator.bookkeeper.valueoftype(A) + TYPE = t.rtyper.getrepr(s_instance).lowleveltype.TO p = transformer.dynamic_deallocation_funcptr_for_type(TYPE) t.rtyper.specialize_more_blocks() @@ -722,3 +723,99 @@ res = llinterp.eval_graph(entrygraph, [ll_argv]) assert ''.join(res.chars) == "2" + +def llinterpreter_for_refcounted_graph(f, args_s): + from pypy.rpython.llinterp import LLInterpreter + from pypy.translator.c.genc import CStandaloneBuilder + from pypy.translator.c import gc + + t = rtype(f, args_s) + cbuild = CStandaloneBuilder(t, f, gc.RefcountingGcPolicy) + db = cbuild.generate_graphs_for_llinterp() + graph = cbuild.getentrypointptr()._obj.graph + llinterp = LLInterpreter(t.rtyper) + if conftest.option.view: + t.view() + return llinterp, graph + res = llinterp.eval_graph(graph, [0]) + assert res == f(0) + res = llinterp.eval_graph(graph, [1]) + assert res == f(1) + + +def test_llinterp_refcounted_graph(): + from pypy.annotation.model import SomeInteger + + class C: + pass + c = C() + c.x = 1 + def g(x): + if x: + return c + else: + d = C() + d.x = 2 + return d + def f(x): + return g(x).x + + llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()]) + + res = llinterp.eval_graph(graph, [0]) + assert res == f(0) + res = llinterp.eval_graph(graph, [1]) + assert res == f(1) + +def test_llinterp_refcounted_graph_varsize(): + from pypy.annotation.model import SomeInteger + + def f(x): + r = [] + for i in range(x): + if i % 2: + r.append(x) + return len(r) + + + llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()]) + + res = llinterp.eval_graph(graph, [0]) + assert res == f(0) + res = llinterp.eval_graph(graph, [10]) + assert res == f(10) + +def test_llinterp_refcounted_graph_with_del(): + from pypy.annotation.model import SomeInteger + + class D: + pass + + delcounter = D() + delcounter.dels = 0 + + class C: + def __del__(self): + delcounter.dels += 1 + c = C() + c.x = 1 + def h(x): + if x: + return c + else: + d = C() + d.x = 2 + return d + def g(x): + return h(x).x + def f(x): + r = g(x) + return r + delcounter.dels + + llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeInteger()]) + + res = llinterp.eval_graph(graph, [1]) + assert res == 1 + res = llinterp.eval_graph(graph, [0]) + assert res == 3 + From mwh at codespeak.net Sun Sep 24 22:24:40 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 24 Sep 2006 22:24:40 +0200 (CEST) Subject: [pypy-svn] r32619 - pypy/dist/pypy/rpython/memory Message-ID: <20060924202440.C608610075@code0.codespeak.net> Author: mwh Date: Sun Sep 24 22:24:39 2006 New Revision: 32619 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: so this fixes all c compilations using refcounting (oops) Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun Sep 24 22:24:39 2006 @@ -427,21 +427,21 @@ gc_header_offset = self.gcheaderbuilder.size_gc_header self.deallocator_graphs_needing_transforming = [] # create incref graph - HDRPTR = lltype.Ptr(self.HDR) + #HDRPTR = lltype.Ptr(self.HDR) def ll_incref(adr): if adr: - gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, lltype.Ptr(self.HDR)) gcheader.refcount = gcheader.refcount + 1 def ll_decref(adr, dealloc): if adr: - gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, lltype.Ptr(self.HDR)) refcount = gcheader.refcount - 1 gcheader.refcount = refcount if refcount == 0: dealloc(adr) def ll_decref_simple(adr): if adr: - gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset,lltype.Ptr(self.HDR)) refcount = gcheader.refcount - 1 if refcount == 0: llop.gc_free(lltype.Void, adr) From mwh at codespeak.net Sun Sep 24 22:42:42 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 24 Sep 2006 22:42:42 +0200 (CEST) Subject: [pypy-svn] r32621 - pypy/dist/pypy/rpython/memory Message-ID: <20060924204242.DEE2910075@code0.codespeak.net> Author: mwh Date: Sun Sep 24 22:42:40 2006 New Revision: 32621 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: remove the lltype.Ptr(self.HDR) i'd missed when making the change before. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun Sep 24 22:42:40 2006 @@ -427,21 +427,21 @@ gc_header_offset = self.gcheaderbuilder.size_gc_header self.deallocator_graphs_needing_transforming = [] # create incref graph - #HDRPTR = lltype.Ptr(self.HDR) + HDRPTR = lltype.Ptr(self.HDR) def ll_incref(adr): if adr: - gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, lltype.Ptr(self.HDR)) + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) gcheader.refcount = gcheader.refcount + 1 def ll_decref(adr, dealloc): if adr: - gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, lltype.Ptr(self.HDR)) + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) refcount = gcheader.refcount - 1 gcheader.refcount = refcount if refcount == 0: dealloc(adr) def ll_decref_simple(adr): if adr: - gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset,lltype.Ptr(self.HDR)) + gcheader = llmemory.cast_adr_to_ptr(adr - gc_header_offset, HDRPTR) refcount = gcheader.refcount - 1 if refcount == 0: llop.gc_free(lltype.Void, adr) @@ -698,13 +698,14 @@ queryptr = rtti._obj.query_funcptr if queryptr._obj in self.queryptr2dynamic_deallocator_funcptr: return self.queryptr2dynamic_deallocator_funcptr[queryptr._obj] - + RTTI_PTR = lltype.Ptr(lltype.RuntimeTypeInfo) QUERY_ARG_TYPE = lltype.typeOf(queryptr).TO.ARGS[0] gc_header_offset = self.gcheaderbuilder.size_gc_header + HDRPTR = lltype.Ptr(self.HDR) def ll_dealloc(addr): # bump refcount to 1 - gcheader = llmemory.cast_adr_to_ptr(addr - gc_header_offset, lltype.Ptr(self.HDR)) + gcheader = llmemory.cast_adr_to_ptr(addr - gc_header_offset, HDRPTR) gcheader.refcount = 1 v = llmemory.cast_adr_to_ptr(addr, QUERY_ARG_TYPE) rtti = queryptr(v) From ac at codespeak.net Mon Sep 25 12:15:51 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 12:15:51 +0200 (CEST) Subject: [pypy-svn] r32624 - pypy/dist/pypy/translator/tool/pygame Message-ID: <20060925101551.14CBD10074@code0.codespeak.net> Author: ac Date: Mon Sep 25 12:15:50 2006 New Revision: 32624 Modified: pypy/dist/pypy/translator/tool/pygame/drawgraph.py Log: Fix workaround for bug in SDL. Modified: pypy/dist/pypy/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/drawgraph.py (original) +++ pypy/dist/pypy/translator/tool/pygame/drawgraph.py Mon Sep 25 12:15:50 2006 @@ -635,9 +635,12 @@ while i < len(parts): part = parts[i] word = part[0] - antialias = not re_nonword.match(word) # SDL bug with anti-aliasing try: - img = font.render(word, antialias, *part[1:]) + try: + img = font.render(word, False, *part[1:]) + except pygame.error, e: + # Try *with* anti-aliasing to work around a bug in SDL + img = font.render(word, True, *part[1:]) except pygame.error: del parts[i] # Text has zero width else: From ac at codespeak.net Mon Sep 25 15:08:09 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 15:08:09 +0200 (CEST) Subject: [pypy-svn] r32629 - in pypy/dist/pypy/interpreter: astcompiler test Message-ID: <20060925130809.5DE7E10074@code0.codespeak.net> Author: ac Date: Mon Sep 25 15:08:08 2006 New Revision: 32629 Modified: pypy/dist/pypy/interpreter/astcompiler/pycodegen.py pypy/dist/pypy/interpreter/test/test_compiler.py Log: Fix issue #247. Modified: pypy/dist/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/pycodegen.py Mon Sep 25 15:08:08 2006 @@ -504,6 +504,9 @@ kind, loop_block = self.setups[top] if kind == LOOP: break + elif kind == END_FINALLY: + msg = "'continue' not supported inside 'finally' clause" + raise SyntaxError( msg, node.lineno ) if kind != LOOP: raise SyntaxError( "'continue' not properly in loop", node.lineno) self.emitop_block('CONTINUE_LOOP', loop_block) Modified: pypy/dist/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_compiler.py (original) +++ pypy/dist/pypy/interpreter/test/test_compiler.py Mon Sep 25 15:08:08 2006 @@ -402,6 +402,34 @@ space.exec_(code, w_d, w_d) assert space.int_w(space.getitem(w_d, space.wrap('result'))) == 42 + def test_continue_in_finally(self): + space = self.space + snippet = str(py.code.Source(r''' +def test(): + for abc in range(10): + try: pass + finally: + continue # 'continue' inside 'finally' + + ''')) + space.raises_w(space.w_SyntaxError, self.compiler.compile, + snippet, '', 'exec', 0) + + def test_continue_in_nested_finally(self): + space = self.space + snippet = str(py.code.Source(r''' +def test(): + for abc in range(10): + try: pass + finally: + try: + continue # 'continue' inside 'finally' + except: + pass + ''')) + space.raises_w(space.w_SyntaxError, self.compiler.compile, + snippet, '', 'exec', 0) + class TestECCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = self.space.getexecutioncontext().compiler @@ -416,6 +444,10 @@ test_unicodeliterals = skip_on_2_3 test_none_assignment = skip_on_2_3 test_import = skip_on_2_3 + elif sys.version_info < (2, 5): + def skip_on_2_4(self): + py.test.skip("syntax not supported by the CPython 2.4 compiler") + test_continue_in_nested_finally = skip_on_2_4 class TestPythonAstCompiler(BaseTestCompiler): def setup_method(self, method): From ac at codespeak.net Mon Sep 25 16:28:37 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 16:28:37 +0200 (CEST) Subject: [pypy-svn] r32633 - pypy/dist/pypy/translator/backendopt Message-ID: <20060925142837.0D46110074@code0.codespeak.net> Author: ac Date: Mon Sep 25 16:28:37 2006 New Revision: 32633 Modified: pypy/dist/pypy/translator/backendopt/ssa.py Log: (arigo, arre) Oops, forgotten to check in this. Modified: pypy/dist/pypy/translator/backendopt/ssa.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/ssa.py (original) +++ pypy/dist/pypy/translator/backendopt/ssa.py Mon Sep 25 16:28:37 2006 @@ -174,18 +174,16 @@ variables_used = {} for op in block.operations: for v in op.args: - if isinstance(v, Variable): - variables_used[v] = True - if isinstance(block.exitswitch, Variable): - variables_used[v] = True + variables_used[v] = True + variables_used[block.exitswitch] = True for link in block.exits: for v in link.args: - if isinstance(v, Variable): - variables_used[v] = True + variables_used[v] = True for v in variables_used: - if v not in variables_created: - pending.append((block, v)) + if isinstance(v, Variable): + if v not in variables_created: + pending.append((block, v)) while pending: block, v = pending.pop() From ac at codespeak.net Mon Sep 25 16:30:36 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 16:30:36 +0200 (CEST) Subject: [pypy-svn] r32634 - in pypy/dist/pypy/interpreter/pyparser: . data Message-ID: <20060925143036.253F510079@code0.codespeak.net> Author: ac Date: Mon Sep 25 16:30:35 2006 New Revision: 32634 Removed: pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a_with Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a pypy/dist/pypy/interpreter/pyparser/ebnfparse.py pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py Log: Replace a hack using two grammars, one including the with statement and one without it, with another hack only using one grammar. Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Sep 25 16:30:35 2006 @@ -11,7 +11,6 @@ from pypy.interpreter.pyparser.parsestring import parsestr sym = pythonparse.PYTHON_PARSER.symbols -sym_with = pythonparse.PYTHON_PARSER.with_grammar.symbols DEBUG_MODE = 0 @@ -1362,7 +1361,8 @@ if name == 'with_statement': # found from __future__ import with_statement if not builder.with_enabled: - raise pythonparse.AlternateGrammarException() + builder.enable_with() + #raise pythonparse.AlternateGrammarException() builder.push(ast.From(from_name, names, atoms[0].lineno)) @@ -1537,15 +1537,12 @@ 'exprlist' : build_exprlist, 'decorator' : build_decorator, 'eval_input' : build_eval_input, + 'with_stmt' : build_with_stmt, } # Build two almost identical ASTRULES dictionaries ASTRULES = dict([(sym[key], value) for (key, value) in ASTRULES_Template.iteritems()]) - -ASTRULES_Template['with_stmt'] = build_with_stmt -ASTRULES_with = dict([(sym_with[key], value) for (key, value) in - (ASTRULES_Template).iteritems()]) del ASTRULES_Template ## Stack elements definitions ################################### @@ -1684,12 +1681,13 @@ self.rule_stack = [] self.space = space self.source_encoding = None - self.ASTRULES = ASTRULES self.with_enabled = False def enable_with(self): - self.ASTRULES = ASTRULES_with + if self.with_enabled: + return self.with_enabled = True + self.keywords.update({'with':None, }) # 'as': None}) def context(self): return AstBuilderContext(self.rule_stack) @@ -1729,7 +1727,7 @@ if rule.is_root(): ## if DEBUG_MODE: ## print "ALT:", sym.sym_name[rule.codename], self.rule_stack - builder_func = self.ASTRULES.get(rule.codename, None) + builder_func = ASTRULES.get(rule.codename, None) if builder_func: builder_func(self, 1) else: @@ -1750,7 +1748,7 @@ if rule.is_root(): ## if DEBUG_MODE: ## print "SEQ:", sym.sym_name[rule.codename] - builder_func = self.ASTRULES.get(rule.codename, None) + builder_func = ASTRULES.get(rule.codename, None) if builder_func: # print "REDUCING SEQUENCE %s" % sym.sym_name[rule.codename] builder_func(self, elts_number) Modified: pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a (original) +++ pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a Mon Sep 25 16:30:35 2006 @@ -63,12 +63,13 @@ exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite) +with_stmt: 'with' test [ NAME expr ] ':' suite # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [',' test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Mon Sep 25 16:30:35 2006 @@ -44,16 +44,17 @@ else: # error unknown or negative integer """ + ctx = source.context() tk = source.next() if tk.codename==self.codename: - if tk.value not in self.keywords: + if tk.value not in builder.keywords: ret = builder.token( tk.codename, tk.value, source ) return self.debug_return( ret, tk.codename, tk.value ) source.restore( ctx ) return 0 - def match_token(self, other): + def match_token(self, builder, other): """special case of match token for tokens which are really keywords """ if not isinstance(other, Token): @@ -62,7 +63,7 @@ return False if other.codename != self.codename: return False - if other.value in self.keywords: + if other.value in builder.keywords: return False return True Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Mon Sep 25 16:30:35 2006 @@ -142,6 +142,7 @@ class BaseGrammarBuilder(AbstractBuilder): """Base/default class for a builder""" + keywords = None def __init__(self, rules=None, debug=0, symbols={} ): AbstractBuilder.__init__(self, rules, debug, symbols ) # stacks contain different objects depending on the builder class @@ -246,7 +247,7 @@ token = source.peek() if self._trace: pos1 = source.get_pos() - in_first_set = self.match_first_set(token) + in_first_set = self.match_first_set(builder, token) if not in_first_set: # and not EmptyToken in self.first_set: if EmptyToken in self.first_set: ret = builder.sequence(self, source, 0 ) @@ -331,12 +332,12 @@ # XXX: first_set could probably be implemented with sets return [] - def match_first_set(self, other): + def match_first_set(self, builder, other): """matching is not equality: token('NAME','x') matches token('NAME',None) """ for tk in self.first_set: - if tk.match_token( other ): + if tk.match_token( builder, other ): return True return False @@ -377,7 +378,7 @@ # to see if this solve our problems with infinite recursion for rule in self.args: if USE_LOOKAHEAD: - if not rule.match_first_set(tok) and EmptyToken not in rule.first_set: + if not rule.match_first_set(builder, tok) and EmptyToken not in rule.first_set: if self._trace: print "Skipping impossible rule: %s" % (rule,) continue @@ -642,6 +643,10 @@ else: # error unknown or negative integer """ + if (self.value is not None and builder.keywords is not None + and self.value not in builder.keywords): + return 0 + ctx = source.context() tk = source.next() if tk.codename == self.codename: @@ -664,7 +669,7 @@ return "<%s>=='%s'" % (name, self.value) - def match_token(self, other): + def match_token(self, builder, other): """convenience '==' implementation, this is *not* a *real* equality test a Token instance can be compared to: - another Token instance in which case all fields (name and value) @@ -676,7 +681,10 @@ raise RuntimeError("Unexpected token type %r" % other) if other is EmptyToken: return False - res = other.codename == self.codename and self.value in [None, other.value] + if (self.value is not None and builder.keywords is not None + and self.value not in builder.keywords): + return False + res = other.codename == self.codename and self.value in [None, other.value] #print "matching", self, other, res return res Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Mon Sep 25 16:30:35 2006 @@ -31,7 +31,11 @@ grammar.build_first_sets(self.items) self.symbols = grammar_builder.symbols self.with_grammar = None - + self.keywords = dict.fromkeys(grammar_builder.keywords) + # Only when with_statement is enabled + self.keywords.pop('with', None) + self.keywords.pop('as', None) + def parse_source(self, textsrc, goal, builder, flags=0): """Parse a python source according to goal""" # Detect source encoding. @@ -52,22 +56,14 @@ def parse_lines(self, lines, goal, builder, flags=0): - if (self.with_grammar is not None and # don't recurse into ourself - flags & CO_FUTURE_WITH_STATEMENT): + builder.keywords = self.keywords.copy() + if flags & CO_FUTURE_WITH_STATEMENT: builder.enable_with() - return self.with_grammar.parse_lines(lines, goal, builder, flags) goalnumber = self.symbols.sym_values[goal] target = self.rules[goalnumber] src = Source(lines, flags) - result = None - try: - result = target.match(src, builder) - except AlternateGrammarException: # handle from __future__ import with_statement - if self.with_grammar is not None: - builder.enable_with() - return self.with_grammar.parse_lines(lines, goal, builder, flags) - if not result: + if not target.match(src, builder): line, lineno = src.debug() # XXX needs better error messages raise SyntaxError("invalid syntax", lineno, -1, line) @@ -148,8 +144,8 @@ return parser debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) -PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) -PYTHON_PARSER.with_grammar = python_grammar( PYTHON_GRAMMAR + '_with' ) +PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR) +#PYTHON_PARSER.with_grammar = python_grammar( PYTHON_GRAMMAR + '_with' ) def reload_grammar(version): """helper function to test with pypy different grammars""" From ac at codespeak.net Mon Sep 25 18:06:02 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 18:06:02 +0200 (CEST) Subject: [pypy-svn] r32635 - in pypy/dist/pypy: annotation interpreter/pyparser interpreter/pyparser/data Message-ID: <20060925160602.E8FDC10078@code0.codespeak.net> Author: ac Date: Mon Sep 25 18:06:02 2006 New Revision: 32635 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a pypy/dist/pypy/interpreter/pyparser/symbol.py Log: Introduce the 'as' keyword. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Mon Sep 25 18:06:02 2006 @@ -10,7 +10,7 @@ from pypy.objspace.flow.model import c_last_exception, checkgraph import py log = py.log.Producer("annrpython") -py.log.setconsumer("annrpython", ansi_log) +py.log.setconsumer("annrpython", None) from pypy.tool.error import format_blocked_annotation_error, format_someobject_error, AnnotatorError Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Sep 25 18:06:02 2006 @@ -1687,7 +1687,7 @@ if self.with_enabled: return self.with_enabled = True - self.keywords.update({'with':None, }) # 'as': None}) + self.keywords.update({'with':None, 'as': None}) def context(self): return AstBuilderContext(self.rule_stack) Modified: pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a (original) +++ pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a Mon Sep 25 18:06:02 2006 @@ -54,8 +54,8 @@ import_stmt: import_name | import_from import_name: 'import' dotted_as_names import_from: 'from' dotted_name 'import' ('*' | '(' import_as_names [','] ')' | import_as_names) -import_as_name: NAME [NAME NAME] -dotted_as_name: dotted_name [NAME NAME] +import_as_name: NAME [('as'|NAME) NAME] +dotted_as_name: dotted_name [('as' | NAME) NAME] import_as_names: import_as_name (',' import_as_name)* dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* @@ -69,7 +69,7 @@ for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite) -with_stmt: 'with' test [ NAME expr ] ':' suite +with_stmt: 'with' test [ 'as' expr ] ':' suite # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [',' test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT Modified: pypy/dist/pypy/interpreter/pyparser/symbol.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/symbol.py (original) +++ pypy/dist/pypy/interpreter/pyparser/symbol.py Mon Sep 25 18:06:02 2006 @@ -85,6 +85,7 @@ old_test = 334 or_test = 335 old_lambdef = 336 +with_stmt = 337 # Generate sym_name From ac at codespeak.net Mon Sep 25 18:10:29 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 18:10:29 +0200 (CEST) Subject: [pypy-svn] r32636 - pypy/dist/pypy/annotation Message-ID: <20060925161029.101661007C@code0.codespeak.net> Author: ac Date: Mon Sep 25 18:10:28 2006 New Revision: 32636 Modified: pypy/dist/pypy/annotation/annrpython.py Log: Oops, shouldn't have checked in that. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Mon Sep 25 18:10:28 2006 @@ -10,7 +10,7 @@ from pypy.objspace.flow.model import c_last_exception, checkgraph import py log = py.log.Producer("annrpython") -py.log.setconsumer("annrpython", None) +py.log.setconsumer("annrpython", ansi_log) from pypy.tool.error import format_blocked_annotation_error, format_someobject_error, AnnotatorError From ac at codespeak.net Mon Sep 25 18:34:51 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 18:34:51 +0200 (CEST) Subject: [pypy-svn] r32637 - in pypy/dist/pypy/interpreter: pyparser test Message-ID: <20060925163451.E463F1007A@code0.codespeak.net> Author: ac Date: Mon Sep 25 18:34:50 2006 New Revision: 32637 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/test/test_syntax.py Log: Add some tests for the 'as' keyword. Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Sep 25 18:34:50 2006 @@ -1262,8 +1262,6 @@ else: token = atoms[2] assert isinstance(token, TokenObject) - if token.get_value() != 'as': - raise SyntaxError("invalid syntax", token.lineno, token.col) varexpr = atoms[3] var = to_lvalue(varexpr, consts.OP_ASSIGN) body = atoms[5] Modified: pypy/dist/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_syntax.py (original) +++ pypy/dist/pypy/interpreter/test/test_syntax.py Mon Sep 25 18:34:50 2006 @@ -472,6 +472,21 @@ pass else: assert False, 'Assignment to with did not raise SyntaxError' + + def test_as_as_identifier(self): + exec "as = 9" + exec "import sys as foo" + + def test_as_as_keyword(self): + try: + exec "from __future__ import with_statement\nas = 9" + except SyntaxError: + pass + else: + assert False, 'Assignment to as did not raise SyntaxError' + + exec "from __future__ import with_statement\nimport sys as foo" + def test_with_propagate_compileflag(self): s = """from __future__ import with_statement From auc at codespeak.net Mon Sep 25 18:46:00 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Mon, 25 Sep 2006 18:46:00 +0200 (CEST) Subject: [pypy-svn] r32638 - pypy/dist/pypy/objspace/cclp/constraint Message-ID: <20060925164600.9A6541007E@code0.codespeak.net> Author: auc Date: Mon Sep 25 18:45:59 2006 New Revision: 32638 Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py Log: transl. fix Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/domain.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/domain.py Mon Sep 25 18:45:59 2006 @@ -109,7 +109,9 @@ return self._space.newbool(self._space.eq_w(self._values, w_other._values)) def __ne__(self, w_other): - return not self == w_other + if not isinstance(w_other, W_FiniteDomain): + return self._space.newbool(True) + return self._space.newbool(self._space.ne_w(self._values, w_other._values)) @@ -117,7 +119,7 @@ # function bolted into the space to serve as constructor def make_fd(space, w_values): assert isinstance(w_values, W_ListObject) - return space.wrap(W_FiniteDomain(space, w_values)) + return W_FiniteDomain(space, w_values) app_make_fd = gateway.interp2app(make_fd) From ac at codespeak.net Mon Sep 25 18:58:13 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 25 Sep 2006 18:58:13 +0200 (CEST) Subject: [pypy-svn] r32639 - pypy/dist/pypy/translator/goal Message-ID: <20060925165813.8700E10060@code0.codespeak.net> Author: ac Date: Mon Sep 25 18:58:12 2006 New Revision: 32639 Modified: pypy/dist/pypy/translator/goal/targetlogicstandalone.py pypy/dist/pypy/translator/goal/targetmultiplespaces.py pypy/dist/pypy/translator/goal/targetpypymain.py pypy/dist/pypy/translator/goal/targetpypystandalone.py pypy/dist/pypy/translator/goal/targetthunkstandalone.py Log: Do not turn off translation of classobj. Modified: pypy/dist/pypy/translator/goal/targetlogicstandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetlogicstandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetlogicstandalone.py Mon Sep 25 18:58:12 2006 @@ -82,9 +82,6 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr - # disable translation of the whole of classobjinterp.py - Space.setup_old_style_classes = lambda self: None - config.objspace.nofaking = True config.objspace.compiler = "ast" config.translating = True Modified: pypy/dist/pypy/translator/goal/targetmultiplespaces.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetmultiplespaces.py (original) +++ pypy/dist/pypy/translator/goal/targetmultiplespaces.py Mon Sep 25 18:58:12 2006 @@ -94,9 +94,6 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - usemodules = [] if tgt_options.usemodules: for modname in tgt_options.usemodules.split(","): Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Mon Sep 25 18:58:12 2006 @@ -82,9 +82,6 @@ if getattr(options, "lowmem", False): config.objspace.geninterp = False - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - usemodules = [] if tgt_options.usemodules: for modname in tgt_options.usemodules.split(","): Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Mon Sep 25 18:58:12 2006 @@ -115,9 +115,6 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - usemodules = [] if tgt_options.usemodules: for modname in tgt_options.usemodules.split(","): Modified: pypy/dist/pypy/translator/goal/targetthunkstandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetthunkstandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetthunkstandalone.py Mon Sep 25 18:58:12 2006 @@ -79,9 +79,6 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr - # disable translation of the whole of classobjinterp.py - Space.setup_old_style_classes = lambda self: None - if tgt_options.usemodules: for modname in tgt_options.usemodules.split(','): setattr(config.objspace.usemodules, modname, True) From auc at codespeak.net Mon Sep 25 19:07:23 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Mon, 25 Sep 2006 19:07:23 +0200 (CEST) Subject: [pypy-svn] r32640 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060925170723.893BF10077@code0.codespeak.net> Author: auc Date: Mon Sep 25 19:07:21 2006 New Revision: 32640 Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py pypy/dist/pypy/objspace/cclp/constraint/domain.py pypy/dist/pypy/objspace/cclp/types.py Log: transl. fixes Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/distributor.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/distributor.py Mon Sep 25 19:07:21 2006 @@ -18,7 +18,9 @@ def spawn_distributor(space, distributor): thread = ClonableCoroutine(space) - thread._cspace = ClonableCoroutine.w_getcurrent(space)._cspace + current = ClonableCoroutine.w_getcurrent(space) + assert hasattr(current, '_cspace') + thread._cspace = current._cspace thunk = DistributorThunk(space, distributor, thread) thread.bind(thunk) if not we_are_translated(): @@ -112,7 +114,7 @@ if not isinstance(fanout, int): raise OperationError(object_space.w_RuntimeError, object_space.wrap("fanout must be a positive integer")) - return object_space.wrap(W_NaiveDistributor(object_space, fanout)) + return W_NaiveDistributor(object_space, fanout) app_make_naive_distributor = interp2app(make_naive_distributor, unwrap_spec = [baseobjspace.ObjSpace, int]) Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/domain.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/domain.py Mon Sep 25 19:07:21 2006 @@ -4,6 +4,7 @@ from pypy.interpreter.gateway import interp2app from pypy.objspace.std.listobject import W_ListObject, W_TupleObject +from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.model import StdObjSpaceMultiMethod @@ -89,7 +90,9 @@ def size(self): """computes the size of a finite domain""" - return self._space.len(self._values).intval + l = self._space.len(self._values) + assert isinstance(l, W_IntObject) + return l.intval __len__ = size def w_get_values(self): Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Mon Sep 25 19:07:21 2006 @@ -42,7 +42,9 @@ self.w_dom = w_dom self.name = space.str_w(w_name) self.w_nam = w_name - cspace = ClonableCoroutine.w_getcurrent(space)._cspace + current = ClonableCoroutine.w_getcurrent(space) + assert hasattr(current, '_cspace') + cspace = current._cspace if cspace is None: w("-- WARNING : you are instanciating a constraint var in the top-level space") else: From auc at codespeak.net Tue Sep 26 10:48:22 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 10:48:22 +0200 (CEST) Subject: [pypy-svn] r32643 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060926084822.6907B1008A@code0.codespeak.net> Author: auc Date: Tue Sep 26 10:48:18 2006 New Revision: 32643 Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py pypy/dist/pypy/objspace/cclp/misc.py pypy/dist/pypy/objspace/cclp/space.py pypy/dist/pypy/objspace/cclp/thread.py pypy/dist/pypy/objspace/cclp/types.py Log: helper func. to help the annotation Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/distributor.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/distributor.py Tue Sep 26 10:48:18 2006 @@ -12,15 +12,13 @@ from pypy.objspace.cclp.types import W_AbstractDistributor, Solution from pypy.objspace.cclp.thunk import DistributorThunk -from pypy.objspace.cclp.misc import w, ClonableCoroutine +from pypy.objspace.cclp.misc import w, ClonableCoroutine, get_current_cspace from pypy.objspace.cclp.global_state import scheduler from pypy.objspace.cclp.interp_var import interp_free def spawn_distributor(space, distributor): thread = ClonableCoroutine(space) - current = ClonableCoroutine.w_getcurrent(space) - assert hasattr(current, '_cspace') - thread._cspace = current._cspace + thread._cspace = get_current_cspace(space) thunk = DistributorThunk(space, distributor, thread) thread.bind(thunk) if not we_are_translated(): Modified: pypy/dist/pypy/objspace/cclp/misc.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/misc.py (original) +++ pypy/dist/pypy/objspace/cclp/misc.py Tue Sep 26 10:48:18 2006 @@ -19,6 +19,13 @@ os.write(1, msg) os.write(1, ' ') +def get_current_cspace(space): + curr = ClonableCoroutine.w_getcurrent(space) + assert isinstance(curr, ClonableCoroutine) + assert hasattr(curr, '_cspace') + return curr._cspace + + def interp_id(space, w_obj): "debugging purposes only" assert isinstance(w_obj, baseobjspace.W_Root) Modified: pypy/dist/pypy/objspace/cclp/space.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/space.py (original) +++ pypy/dist/pypy/objspace/cclp/space.py Tue Sep 26 10:48:18 2006 @@ -4,7 +4,7 @@ from pypy.objspace.std.intobject import W_IntObject -from pypy.objspace.cclp.misc import ClonableCoroutine, w +from pypy.objspace.cclp.misc import ClonableCoroutine, get_current_cspace, w from pypy.objspace.cclp.thunk import CSpaceThunk, PropagatorThunk from pypy.objspace.cclp.global_state import scheduler from pypy.objspace.cclp.variable import newvar @@ -34,7 +34,7 @@ def choose(space, w_n): assert isinstance(w_n, W_IntObject) n = space.int_w(w_n) - cspace = ClonableCoroutine.w_getcurrent(space)._cspace + cspace = get_current_cspace(space) if cspace != None: assert isinstance(cspace, W_CSpace) try: @@ -51,7 +51,7 @@ def tell(space, w_constraint): assert isinstance(w_constraint, constraint.W_AbstractConstraint) - ClonableCoroutine.w_getcurrent(space)._cspace.tell(w_constraint) + get_current_cspace(space).tell(w_constraint) app_tell = gateway.interp2app(tell) Modified: pypy/dist/pypy/objspace/cclp/thread.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thread.py (original) +++ pypy/dist/pypy/objspace/cclp/thread.py Tue Sep 26 10:48:18 2006 @@ -2,7 +2,7 @@ from pypy.rpython.objectmodel import we_are_translated from pypy.objspace.cclp.types import W_Var, W_Future, W_FailedValue -from pypy.objspace.cclp.misc import w, v, ClonableCoroutine +from pypy.objspace.cclp.misc import w, v, ClonableCoroutine, get_current_cspace from pypy.objspace.cclp.thunk import FutureThunk, ProcedureThunk from pypy.objspace.cclp.global_state import scheduler @@ -21,7 +21,7 @@ w_Future = W_Future(space) thunk = FutureThunk(space, w_callable, args, w_Future, coro) coro.bind(thunk) - coro._cspace = ClonableCoroutine.w_getcurrent(space)._cspace + coro._cspace = get_current_cspace(space) if not we_are_translated(): w("FUTURE", str(id(coro)), "for", str(w_callable.name)) scheduler[0].add_new_thread(coro) @@ -41,7 +41,7 @@ #coro.cspace = ClonableCoroutine.w_getcurrent(space).cspace thunk = ProcedureThunk(space, w_callable, args, coro) coro.bind(thunk) - coro._cspace = ClonableCoroutine.w_getcurrent(space)._cspace + coro._cspace = get_current_cspace(space) if not we_are_translated(): w("STACKLET", str(id(coro)), "for", str(w_callable.name)) scheduler[0].add_new_thread(coro) Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Tue Sep 26 10:48:18 2006 @@ -1,7 +1,7 @@ from pypy.interpreter import baseobjspace, gateway, typedef from pypy.interpreter.error import OperationError -from pypy.objspace.cclp.misc import w, ClonableCoroutine +from pypy.objspace.cclp.misc import w, ClonableCoroutine, get_current_cspace W_Root = baseobjspace.W_Root @@ -42,9 +42,7 @@ self.w_dom = w_dom self.name = space.str_w(w_name) self.w_nam = w_name - current = ClonableCoroutine.w_getcurrent(space) - assert hasattr(current, '_cspace') - cspace = current._cspace + cspace = get_current_cspace(space) if cspace is None: w("-- WARNING : you are instanciating a constraint var in the top-level space") else: @@ -99,7 +97,7 @@ assert isinstance(fanout, int) self._space = space self._fanout = fanout - self._cspace = ClonableCoroutine.w_getcurrent(space)._cspace + self._cspace = get_current_cspace(space) W_AbstractDistributor.typedef = typedef.TypeDef("W_AbstractDistributor") From mwh at codespeak.net Tue Sep 26 11:58:48 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 26 Sep 2006 11:58:48 +0200 (CEST) Subject: [pypy-svn] r32645 - in pypy/dist/pypy/translator/c: . src Message-ID: <20060926095848.2E9B610070@code0.codespeak.net> Author: mwh Date: Tue Sep 26 11:58:46 2006 New Revision: 32645 Modified: pypy/dist/pypy/translator/c/gc.py pypy/dist/pypy/translator/c/src/mem.h Log: make genc marginally more gc transformer agnostic (could be made more so) Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Tue Sep 26 11:58:46 2006 @@ -67,10 +67,14 @@ transformerclass = gctransform.RefcountingGCTransformer def common_gcheader_definition(self, defnode): - return [('refcount', lltype.Signed)] + HDR = defnode.db.gctransformer.HDR + return [(name, HDR._flds[name]) for name in HDR._names] def common_gcheader_initdata(self, defnode): - return [CDefinedIntSymbolic('REFCOUNT_IMMORTAL')] + gct = defnode.db.gctransformer + hdr = gct.gcheaderbuilder.header_of_object(top_container(defnode.obj)) + HDR = gct.HDR + return [getattr(hdr, fldname) for fldname in HDR._names] # for structs Modified: pypy/dist/pypy/translator/c/src/mem.h ============================================================================== --- pypy/dist/pypy/translator/c/src/mem.h (original) +++ pypy/dist/pypy/translator/c/src/mem.h Tue Sep 26 11:58:46 2006 @@ -71,12 +71,6 @@ } /* else { ...} -- generated by funcgen.py */ - -/* XXX hack to initialize the refcount of global structures: officially, - we need a value equal to the number of references to this global from - other globals, plus one. This upper bound "approximation" will do... */ -#define REFCOUNT_IMMORTAL (INT_MAX/2) - #if RAW_MALLOC_ZERO_FILLED #define OP_ZERO_MALLOC OP_RAW_MALLOC From arigo at codespeak.net Tue Sep 26 12:26:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Sep 2006 12:26:54 +0200 (CEST) Subject: [pypy-svn] r32647 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060926102654.91F5B10072@code0.codespeak.net> Author: arigo Date: Tue Sep 26 12:26:52 2006 New Revision: 32647 Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py Log: The parenttypeptr field of vtables is not used any more, actually. Killing it means that the vtable of classes which are never instantiated is (probably) no longer reachable, so it will not be found by the genc database and left out of the final C code. Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Tue Sep 26 12:26:52 2006 @@ -27,7 +27,7 @@ # A root class "object" has: # # struct object_vtable { -# struct object_vtable* parenttypeptr; +# // struct object_vtable* parenttypeptr; not used any more # RuntimeTypeInfo * rtti; # Signed subclassrange_min; //this is also the id of the class itself # Signed subclassrange_max; @@ -61,7 +61,7 @@ hints = {'immutable': True}) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', - ('parenttypeptr', CLASSTYPE), + #('parenttypeptr', CLASSTYPE), ('subclassrange_min', Signed), ('subclassrange_max', Signed), ('rtti', Ptr(RuntimeTypeInfo)), @@ -180,9 +180,9 @@ """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: - # initialize the 'parenttypeptr' and 'name' fields + # initialize the 'subclassrange_*' and 'name' fields if rsubcls.classdef is not None: - vtable.parenttypeptr = rsubcls.rbase.getvtable() + #vtable.parenttypeptr = rsubcls.rbase.getvtable() vtable.subclassrange_min = rsubcls.classdef.minid vtable.subclassrange_max = rsubcls.classdef.maxid else: #for the root class From pedronis at codespeak.net Tue Sep 26 13:35:36 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 26 Sep 2006 13:35:36 +0200 (CEST) Subject: [pypy-svn] r32648 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20060926113536.42DF710072@code0.codespeak.net> Author: pedronis Date: Tue Sep 26 13:35:32 2006 New Revision: 32648 Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py pypy/dist/pypy/interpreter/astcompiler/astgen.py Log: make Node and Expression also not subclassable. Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/ast.py Tue Sep 26 13:35:32 2006 @@ -91,6 +91,7 @@ filename = interp_attrproperty('filename', cls=Node), ) +Node.typedef.acceptable_as_base_class = False class EmptyNode(Node): def accept(self, visitor): @@ -152,8 +153,8 @@ mutate=interp2app(descr_expression_mutate, unwrap_spec=[ObjSpace, W_Root, W_Root] ), node=GetSetProperty(Expression.fget_node, Expression.fset_node ), ) - +Expression.typedef.acceptable_as_base_class = False class AbstractFunction(Node): Modified: pypy/dist/pypy/interpreter/astcompiler/astgen.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/astgen.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/astgen.py Tue Sep 26 13:35:32 2006 @@ -733,6 +733,7 @@ filename = interp_attrproperty('filename', cls=Node), ) +Node.typedef.acceptable_as_base_class = False class EmptyNode(Node): def accept(self, visitor): @@ -794,8 +795,8 @@ mutate=interp2app(descr_expression_mutate, unwrap_spec=[ObjSpace, W_Root, W_Root] ), node=GetSetProperty(Expression.fget_node, Expression.fset_node ), ) - +Expression.typedef.acceptable_as_base_class = False ''' epilogue = ''' From mwh at codespeak.net Tue Sep 26 14:55:31 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 26 Sep 2006 14:55:31 +0200 (CEST) Subject: [pypy-svn] r32649 - pypy/extradoc/sprintinfo/ddorf2006b Message-ID: <20060926125531.C975A10075@code0.codespeak.net> Author: mwh Date: Tue Sep 26 14:55:30 2006 New Revision: 32649 Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt Log: my ddorf details Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006b/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006b/people.txt Tue Sep 26 14:55:30 2006 @@ -10,6 +10,7 @@ ==================== ============== ===================== Carl Friedrich Bolz always there private Armin Rigo 27th / - private +Michael Hudson 29th / - private ==================== ============== ===================== People on the following list were present at previous sprints: From auc at codespeak.net Tue Sep 26 15:02:19 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 15:02:19 +0200 (CEST) Subject: [pypy-svn] r32650 - pypy/dist/pypy/objspace/cclp Message-ID: <20060926130219.D792C10074@code0.codespeak.net> Author: auc Date: Tue Sep 26 15:02:17 2006 New Revision: 32650 Modified: pypy/dist/pypy/objspace/cclp/variable.py Log: more explicit error reports Modified: pypy/dist/pypy/objspace/cclp/variable.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/variable.py (original) +++ pypy/dist/pypy/objspace/cclp/variable.py Tue Sep 26 15:02:17 2006 @@ -339,9 +339,9 @@ w_d1 = w_x.getdict() #returns wrapped dict or unwrapped None ... w_d2 = w_y.getdict() if None in [w_d1, w_d2]: - raise_unification_failure(space) + raise_unification_failure(space, str(w_x) + " != " + str(w_y)) else: - return space.unify(w_d1, w_d2) + return unify__Dict_Dict(space, w_d1, w_d2) return space.w_None def unify__Var_Var(space, w_x, w_y): @@ -366,7 +366,7 @@ def unify__Tuple_Tuple(space, w_i1, w_i2): if len(w_i1.wrappeditems) != len(w_i2.wrappeditems): - raise_unification_failure(space) + raise_unification_failure(space, "tuples of different lengths.") idx, top = (-1, space.int_w(space.len(w_i1))-1) while idx < top: idx += 1 @@ -379,7 +379,7 @@ def unify__List_List(space, w_i1, w_i2): if len(w_i1.wrappeditems) != len(w_i2.wrappeditems): - raise_unification_failure(space) + raise_unification_failure(space, "lists of different lengths.") idx, top = (-1, space.int_w(space.len(w_i1))-1) while idx < top: idx += 1 From auc at codespeak.net Tue Sep 26 15:03:38 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 15:03:38 +0200 (CEST) Subject: [pypy-svn] r32651 - pypy/dist/pypy/objspace/cclp Message-ID: <20060926130338.340A910034@code0.codespeak.net> Author: auc Date: Tue Sep 26 15:03:36 2006 New Revision: 32651 Modified: pypy/dist/pypy/objspace/cclp/thunk.py Log: more type correctness (from rpython pov) Modified: pypy/dist/pypy/objspace/cclp/thunk.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thunk.py (original) +++ pypy/dist/pypy/objspace/cclp/thunk.py Tue Sep 26 15:03:36 2006 @@ -6,6 +6,7 @@ from pypy.objspace.cclp.types import W_Var, W_Future, W_FailedValue, ConsistencyError, Solution from pypy.objspace.cclp.interp_var import interp_wait, interp_entail, interp_bind, interp_free, interp_wait_or +from pypy.rpython.objectmodel import we_are_translated def logic_args(args): "returns logic vars found in unpacked normalized args" @@ -84,6 +85,7 @@ scheduler[0].trace_vars(self._coro, logic_args(self.args.unpack())) cspace = self._coro._cspace cspace.distributor = self._coro + space = self.space try: try: _AppThunk.call(self) @@ -100,7 +102,7 @@ w("-- clean (valueless) EXIT of cspace", str(id(self._coro))) interp_bind(cspace._solution, self.costate.w_tempval) if self.is_distributor(): - interp_bind(cspace._choice, self.space.newint(1)) + interp_bind(cspace._choice, space.newint(1)) finally: scheduler[0].remove_thread(self._coro) scheduler[0].schedule() @@ -131,8 +133,9 @@ except ConsistencyError: cspace.fail() except: - import traceback - traceback.print_exc() + if not we_are_translated(): + import traceback + traceback.print_exc() finally: self.coro._dead = True scheduler[0].remove_thread(self.coro) @@ -154,7 +157,7 @@ try: while dist.distributable(): choice = cspace.choose(dist.fanout()) - dist.distribute(choice) + dist.w_distribute(choice) w("-- DISTRIBUTOR thunk exited because a solution was found") #XXX assert that all propagators are entailed for var in cspace._solution.w_bound_to.wrappeditems: @@ -166,10 +169,11 @@ w("-- DISTRIBUTOR thunk exited because", str(e)) interp_bind(cspace._choice, self.space.newint(0)) except: - import traceback - traceback.print_exc() + if not we_are_translated(): + import traceback + traceback.print_exc() finally: - interp_bind(cspace._finished, True) + interp_bind(cspace._finished, self.space.w_True) coro._dead = True scheduler[0].remove_thread(coro) scheduler[0].schedule() From auc at codespeak.net Tue Sep 26 15:05:00 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 15:05:00 +0200 (CEST) Subject: [pypy-svn] r32652 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060926130500.699E41006C@code0.codespeak.net> Author: auc Date: Tue Sep 26 15:04:57 2006 New Revision: 32652 Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py pypy/dist/pypy/objspace/cclp/constraint/domain.py pypy/dist/pypy/objspace/cclp/space.py Log: more of the same (types) Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/constraint.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py Tue Sep 26 15:04:57 2006 @@ -198,6 +198,7 @@ ord_vars = BTree() for variable in self._variables: + assert isinstance(variable, W_Variable) ord_vars.add((variable.w_dom).size(), (variable, variable.w_dom)) Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/domain.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/domain.py Tue Sep 26 15:04:57 2006 @@ -8,7 +8,7 @@ from pypy.objspace.std.model import StdObjSpaceMultiMethod -from pypy.objspace.cclp.types import W_AbstractDomain, W_Var, ConsistencyError +from pypy.objspace.cclp.types import W_AbstractDomain, W_Var, W_Root, ConsistencyError from pypy.objspace.cclp.interp_var import interp_bind, interp_free all_mms = {} @@ -38,10 +38,17 @@ def give_synchronizer(self): return self._changed + + def contains(self, w_val): + sp = self._space + assert isinstance(w_val, W_Root) + return sp.is_true(sp.contains(self._values, w_val)) + __contains__ = contains + def _value_removed(self): "The implementation of remove_value should call this method" #atomic - interp_bind(self._changed, True) + interp_bind(self._changed, self._space.w_True) self.clear_change() #/atomic Modified: pypy/dist/pypy/objspace/cclp/space.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/space.py (original) +++ pypy/dist/pypy/objspace/cclp/space.py Tue Sep 26 15:04:57 2006 @@ -38,7 +38,7 @@ if cspace != None: assert isinstance(cspace, W_CSpace) try: - return space.newint(cspace.choose(w_n.intval)) + return cspace.choose(w_n.intval) except ConsistencyError: raise OperationError(space.w_ConsistencyError, space.wrap("the space is failed")) @@ -103,7 +103,7 @@ assert interp_free(self._committed) assert n > 0 assert n <= self._last_choice - interp_bind(self._committed, n) + interp_bind(self._committed, w_n) def tell(self, w_constraint): space = self.space @@ -118,7 +118,7 @@ def fail(self): self._failed = True - interp_bind(self._finished, True) + interp_bind(self._finished, self.space.w_True) interp_bind(self._choice, self.space.newint(0)) self._store = {} From auc at codespeak.net Tue Sep 26 16:08:50 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 16:08:50 +0200 (CEST) Subject: [pypy-svn] r32653 - pypy/dist/pypy/objspace/cclp Message-ID: <20060926140850.3C7BC10076@code0.codespeak.net> Author: auc Date: Tue Sep 26 16:08:46 2006 New Revision: 32653 Modified: pypy/dist/pypy/objspace/cclp/interp_var.py pypy/dist/pypy/objspace/cclp/thunk.py pypy/dist/pypy/objspace/cclp/types.py pypy/dist/pypy/objspace/cclp/variable.py Log: type declarations, small fixes Modified: pypy/dist/pypy/objspace/cclp/interp_var.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/interp_var.py (original) +++ pypy/dist/pypy/objspace/cclp/interp_var.py Tue Sep 26 16:08:46 2006 @@ -1,10 +1,11 @@ from pypy.objspace.cclp.variable import wait__Var, _assign_aliases, _entail -from pypy.objspace.cclp.types import W_Var, W_CVar +from pypy.objspace.cclp.types import W_Root, W_Var, W_CVar from pypy.objspace.cclp.global_state import scheduler from pypy.objspace.cclp.misc import w def interp_free(w_var): + assert isinstance(w_var, W_Var) return isinstance(w_var.w_bound_to, W_Var) def interp_wait(space, obj): @@ -13,16 +14,19 @@ class RebindingError(Exception): pass -def interp_bind(w_var, obj): +def interp_bind(w_var, w_obj): + # w_obj is NOT a W_Var if interp_free(w_var): - return interp_assign_aliases(w_var, obj) - if w_var.w_bound_to == obj: + return interp_assign_aliases(w_var, w_obj) + if w_var.w_bound_to == w_obj: return raise RebindingError class EntailmentError(Exception): pass def interp_entail(w_v1, w_v2): + assert isinstance(w_v1, W_Var) + assert isinstance(w_v2, W_Var) w_v1val = w_v1.w_bound_to w_v2val = w_v2.w_bound_to if not interp_free(w_v1): @@ -41,6 +45,7 @@ w_curr = w_var while 1: w_next = w_curr.w_bound_to + assert isinstance(w_next, W_Var) _assign(w_curr, w_val) # notify the blocked threads scheduler[0].unblock_on(w_curr) @@ -54,6 +59,7 @@ def _assign_entailed(w_var, w_val): w(" :assign entailed") for var in w_var.entails: + assert isinstance(var, W_Var) if interp_free(var): interp_assign_aliases(var, w_val) else: @@ -63,7 +69,7 @@ def _assign(w_var, w_val): assert isinstance(w_var, W_Var) if isinstance(w_var, W_CVar): - if not w_val in w_var.w_dom._values.content: + if not w_var.w_dom.contains(w_val): raise ValueError, "assignment out of domain" w_var.w_bound_to = w_val Modified: pypy/dist/pypy/objspace/cclp/thunk.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thunk.py (original) +++ pypy/dist/pypy/objspace/cclp/thunk.py Tue Sep 26 16:08:46 2006 @@ -150,8 +150,8 @@ def call(self): coro = self.coro + cspace = coro._cspace try: - cspace = coro._cspace cspace.distributor = coro dist = self.dist try: Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Tue Sep 26 16:08:46 2006 @@ -117,6 +117,7 @@ w_curr = w_var while 1: w_next = w_curr.w_bound_to + assert isinstance(w_next, W_Var) al.append(w_curr) if space.is_true(space.is_nb_(w_next, w_var)): break Modified: pypy/dist/pypy/objspace/cclp/variable.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/variable.py (original) +++ pypy/dist/pypy/objspace/cclp/variable.py Tue Sep 26 16:08:46 2006 @@ -122,6 +122,7 @@ w_curr = w_var1 while 1: w_next = w_curr.w_bound_to + assert isinstance(w_next, W_Var) if w_next is w_var2: return space.newbool(True) if w_next is w_var1: @@ -138,6 +139,7 @@ w_curr = w_start while 1: w_next = w_curr.w_bound_to + assert isinstance(w_next, W_Var) if space.is_true(space.is_nb_(w_next, w_start)): return w_curr w_curr = w_next @@ -260,6 +262,7 @@ w_curr = w_var while 1: w_next = w_curr.w_bound_to + assert isinstance(w_next, W_Var) _assign(space, w_curr, w_val) # notify the blocked threads scheduler[0].unblock_on(w_curr) From auc at codespeak.net Tue Sep 26 16:12:18 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 16:12:18 +0200 (CEST) Subject: [pypy-svn] r32654 - pypy/dist/pypy/objspace/test Message-ID: <20060926141218.A655F10076@code0.codespeak.net> Author: auc Date: Tue Sep 26 16:12:16 2006 New Revision: 32654 Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py Log: doctor some results so that we still pass (are we correct ?) Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Tue Sep 26 16:12:16 2006 @@ -448,27 +448,18 @@ assert len(sched_info()['threads']) == 1 def test_fib(self): - skip("recursion limits breakage") def fib(X): if X<2: return 1 else: return future(fib, X-1) + fib(X-2) - + X = newvar() F = future(fib, X) + # values > 11 triggers exhaustion of the cpython stack unify(11, X) assert F == 144 - X = newvar() - F = future(fib, X) - - try: - unify(50, X) - print F - except Exception, e: - print e - def test_stacklet(self): reset_scheduler() @@ -786,13 +777,27 @@ Solution = newvar() stacklet(solve, s, commit_to, Solution) if commit_to == 1: - assert Solution == [('room B', 'day 1 PM'), ('room A', 'day 1 PM'), - ('room B', 'day 2 AM'), ('room B', 'day 1 AM'), - ('room A', 'day 2 PM'), ('room C', 'day 2 AM'), - ('room C', 'day 2 PM'), ('room C', 'day 1 PM'), - ('room C', 'day 1 AM'), ('room B', 'day 2 PM')] + assert set(Solution) == set([('room B', 'day 2 PM'), + ('room C', 'day 2 PM'), + ('room A', 'day 1 PM'), + ('room C', 'day 1 AM'), + ('room A', 'day 2 AM'), + ('room A', 'day 1 AM'), + ('room C', 'day 2 AM'), + ('room B', 'day 1 AM'), + ('room B', 'day 2 AM'), + ('room C', 'day 1 PM')]) else: - assert Solution == False + assert set(Solution) == set([('room B', 'day 1 PM'), + ('room A', 'day 1 PM'), + ('room B', 'day 2 AM'), + ('room B', 'day 1 AM'), + ('room A', 'day 2 PM'), + ('room C', 'day 2 AM'), + ('room C', 'day 2 PM'), + ('room C', 'day 1 PM'), + ('room C', 'day 1 AM'), + ('room B', 'day 2 PM')]) #XXX who's still stuck there ? #assert len(sched_all()['threads']) == 1 From auc at codespeak.net Tue Sep 26 17:21:01 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 17:21:01 +0200 (CEST) Subject: [pypy-svn] r32655 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060926152101.1183210076@code0.codespeak.net> Author: auc Date: Tue Sep 26 17:20:56 2006 New Revision: 32655 Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py pypy/dist/pypy/objspace/cclp/thunk.py pypy/dist/pypy/objspace/cclp/types.py Log: more type info ... Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/constraint.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py Tue Sep 26 17:20:56 2006 @@ -9,7 +9,8 @@ from pypy.objspace.constraint.computationspace import W_ComputationSpace -from pypy.objspace.cclp.types import W_Constraint, W_CVar as W_Variable +from pypy.objspace.cclp.types import W_Constraint, W_AbstractDomain, W_Root, \ + W_CVar as W_Variable from pypy.objspace.std.model import StdObjSpaceMultiMethod @@ -97,9 +98,13 @@ for variable in self._variables: assert isinstance(variable, W_Variable) domain = variable.w_dom + assert isinstance(domain, W_AbstractDomain) values = domain.get_values() + assert isinstance(values, list) variables.append((domain.size(), [variable.w_name(), values, 0, len(values)])) - kwargs.content[variable.w_name()] = values[0] + first_value = values[0] + assert isinstance(first_value, W_Root) + kwargs.content[variable.w_name()] = first_value # sort variables to instanciate those with fewer possible values first sort(variables) self._assign_values_state = variables Modified: pypy/dist/pypy/objspace/cclp/thunk.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thunk.py (original) +++ pypy/dist/pypy/objspace/cclp/thunk.py Tue Sep 26 17:20:56 2006 @@ -3,9 +3,12 @@ from pypy.objspace.cclp.misc import w from pypy.objspace.cclp.global_state import scheduler -from pypy.objspace.cclp.types import W_Var, W_Future, W_FailedValue, ConsistencyError, Solution -from pypy.objspace.cclp.interp_var import interp_wait, interp_entail, interp_bind, interp_free, interp_wait_or +from pypy.objspace.cclp.types import W_Var, W_CVar, W_Future, W_FailedValue, \ + ConsistencyError, Solution, W_AbstractDomain +from pypy.objspace.cclp.interp_var import interp_wait, interp_entail, \ + interp_bind, interp_free, interp_wait_or +from pypy.objspace.std.listobject import W_ListObject from pypy.rpython.objectmodel import we_are_translated def logic_args(args): @@ -123,8 +126,14 @@ if entailed: break # we will block on domains being pruned - wait_list = [var.w_dom.give_synchronizer() - for var in self.const._variables] + wait_list = [] + _vars = self.const._variables + assert isinstance(_vars, list) + for var in _vars: + assert isinstance(var, W_CVar) + dom = var.w_dom + assert isinstance(dom, W_AbstractDomain) + wait_list.append(dom.give_synchronizer()) #or the cspace being dead wait_list.append(cspace._finished) interp_wait_or(self.space, wait_list) @@ -160,7 +169,11 @@ dist.w_distribute(choice) w("-- DISTRIBUTOR thunk exited because a solution was found") #XXX assert that all propagators are entailed - for var in cspace._solution.w_bound_to.wrappeditems: + sol = cspace._solution + assert isinstance(sol, W_Var) + varset = sol.w_bound_to + assert isinstance(varset, W_ListObject) + for var in varset.wrappeditems: assert var.w_dom.size() == 1 interp_bind(var, var.w_dom.get_values()[0]) assert interp_free(cspace._choice) Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Tue Sep 26 17:20:56 2006 @@ -88,6 +88,11 @@ self._space = space self._changed = W_Var(self._space) + def give_synchronizer(self): + pass + + def get_values(self): + pass W_AbstractDomain.typedef = typedef.TypeDef("W_AbstractDomain") From auc at codespeak.net Tue Sep 26 19:09:17 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 26 Sep 2006 19:09:17 +0200 (CEST) Subject: [pypy-svn] r32657 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060926170917.61FF91007E@code0.codespeak.net> Author: auc Date: Tue Sep 26 19:09:04 2006 New Revision: 32657 Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py pypy/dist/pypy/objspace/cclp/scheduler.py pypy/dist/pypy/objspace/cclp/space.py pypy/dist/pypy/objspace/cclp/thunk.py pypy/dist/pypy/objspace/cclp/types.py Log: more tweaklets to help the annotator Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/constraint.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py Tue Sep 26 19:09:04 2006 @@ -101,7 +101,8 @@ assert isinstance(domain, W_AbstractDomain) values = domain.get_values() assert isinstance(values, list) - variables.append((domain.size(), [variable.w_name(), values, 0, len(values)])) + variables.append((domain.size(), + [variable.w_name(), values, 0, len(values)])) first_value = values[0] assert isinstance(first_value, W_Root) kwargs.content[variable.w_name()] = first_value Modified: pypy/dist/pypy/objspace/cclp/scheduler.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/scheduler.py (original) +++ pypy/dist/pypy/objspace/cclp/scheduler.py Tue Sep 26 19:09:04 2006 @@ -14,6 +14,7 @@ def __init__(self, space): self.space = space self._main = ClonableCoroutine.w_getcurrent(space) + assert isinstance(self._main, ClonableCoroutine) self._init_head(self._main) self._init_blocked() self._switch_count = 0 @@ -86,6 +87,7 @@ if self.is_stable(cspace): return curr = ClonableCoroutine.w_getcurrent(self.space) + assert isinstance(curr, ClonableCoroutine) self._asking[curr] = cspace self._blocked[curr] = True # either we choose() from inside @@ -136,6 +138,7 @@ to_be_run = self._head sentinel = to_be_run current = ClonableCoroutine.w_getcurrent(self.space) + assert isinstance(current, ClonableCoroutine) while (to_be_run in self._blocked) \ or to_be_run.is_dead() \ or (to_be_run == current): @@ -150,7 +153,7 @@ break if to_be_run == sentinel: if not dont_pass: - return ClonableCoroutine.w_getcurrent(self.space) + return current w(str(sched_all(self.space))) ## we RESET sched state so as to keep being usable beyond that self._init_head(self._main) Modified: pypy/dist/pypy/objspace/cclp/space.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/space.py (original) +++ pypy/dist/pypy/objspace/cclp/space.py Tue Sep 26 19:09:04 2006 @@ -81,7 +81,8 @@ self.space.wait(self._choice) choice = self._choice.w_bound_to self._choice = newvar(self.space) - self._last_choice = choice.intval + assert isinstance(choice, W_IntObject) + self._last_choice = self.space.int_w(choice) return choice def choose(self, n): Modified: pypy/dist/pypy/objspace/cclp/thunk.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thunk.py (original) +++ pypy/dist/pypy/objspace/cclp/thunk.py Tue Sep 26 19:09:04 2006 @@ -141,7 +141,7 @@ break except ConsistencyError: cspace.fail() - except: + except Exception: # rpython doesn't like just except:\n ... if not we_are_translated(): import traceback traceback.print_exc() @@ -174,8 +174,11 @@ varset = sol.w_bound_to assert isinstance(varset, W_ListObject) for var in varset.wrappeditems: - assert var.w_dom.size() == 1 - interp_bind(var, var.w_dom.get_values()[0]) + assert isinstance(var, W_CVar) + dom = var.w_dom + assert isinstance(dom, W_AbstractDomain) + assert dom.size() == 1 + interp_bind(var, dom.get_values()[0]) assert interp_free(cspace._choice) interp_bind(cspace._choice, self.space.newint(1)) except ConsistencyError, e: Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Tue Sep 26 19:09:04 2006 @@ -94,6 +94,9 @@ def get_values(self): pass + def size(self): + pass + W_AbstractDomain.typedef = typedef.TypeDef("W_AbstractDomain") class W_AbstractDistributor(baseobjspace.Wrappable): From ac at codespeak.net Wed Sep 27 13:11:32 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 27 Sep 2006 13:11:32 +0200 (CEST) Subject: [pypy-svn] r32665 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20060927111132.627AE10077@code0.codespeak.net> Author: ac Date: Wed Sep 27 13:11:31 2006 New Revision: 32665 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/objspace/std/objspace.py Log: (pedronis, arre) Reduce the number of RPython classes created for every user subclassable type. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Wed Sep 27 13:11:31 2006 @@ -87,9 +87,18 @@ no_hash_descr = interp2app(descr__hash__unhashable) # ____________________________________________________________ - def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False, weakrefable=False): + if needsdel: + hasdict = wants_slots = weakrefable = True + if hasdict: + weakrefable = True + else: + wants_slots = True + return _get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel, weakrefable) +get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" + +def _get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel, weakrefable): key = cls, hasdict, wants_slots, needsdel, weakrefable try: return _subclass_cache[key] @@ -97,7 +106,6 @@ subcls = _buildusercls(cls, hasdict, wants_slots, needsdel, weakrefable) _subclass_cache[key] = subcls return subcls -get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" _subclass_cache = {} def _buildusercls(cls, hasdict, wants_slots, wants_del, weakrefable): @@ -123,7 +131,7 @@ name = ''.join(name) if weakrefable: - supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, + supercls = _get_unique_interplevel_subclass(cls, hasdict, wants_slots, wants_del, False) class Proto(object): _lifeline_ = None @@ -132,7 +140,7 @@ def setweakref(self, space, weakreflifeline): self._lifeline_ = weakreflifeline elif wants_del: - supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, + supercls = _get_unique_interplevel_subclass(cls, hasdict, wants_slots, False, False) parent_destructor = getattr(cls, '__del__', None) class Proto(object): @@ -145,11 +153,13 @@ if parent_destructor is not None: parent_destructor(self) elif wants_slots: - supercls = get_unique_interplevel_subclass(cls, hasdict, False, False, False) + supercls = _get_unique_interplevel_subclass(cls, hasdict, False, False, False) class Proto(object): + slots_w = None def user_setup_slots(self, nslots): - self.slots_w = [None] * nslots + if nslots > 0: + self.slots_w = [None] * nslots def setslotvalue(self, index, w_value): self.slots_w[index] = w_value @@ -157,7 +167,7 @@ def getslotvalue(self, index): return self.slots_w[index] elif hasdict: - supercls = get_unique_interplevel_subclass(cls, False, False, False, False) + supercls = _get_unique_interplevel_subclass(cls, False, False, False, False) class Proto(object): def getdict(self): @@ -169,11 +179,11 @@ space.wrap("setting dictionary to a non-dict")) self.w__dict__ = w_dict - def user_setup(self, space, w_subtype, nslots): + def user_setup(self, space, w_subtype): self.space = space self.w__class__ = w_subtype self.w__dict__ = space.newdict() - self.user_setup_slots(nslots) + self.user_setup_slots(w_subtype.nslots) else: supercls = cls @@ -187,10 +197,10 @@ self.w__class__ = w_subtype - def user_setup(self, space, w_subtype, nslots): + def user_setup(self, space, w_subtype): self.space = space self.w__class__ = w_subtype - self.user_setup_slots(nslots) + self.user_setup_slots(w_subtype.nslots) def user_setup_slots(self, nslots): assert nslots == 0 Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Sep 27 13:11:31 2006 @@ -438,7 +438,7 @@ w_subtype = w_type.check_user_subclass(w_subtype) subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel, w_subtype.weakrefable) instance = instantiate(subcls) - instance.user_setup(self, w_subtype, w_subtype.nslots) + instance.user_setup(self, w_subtype) else: raise OperationError(self.w_TypeError, self.wrap("%s.__new__(%s): only for the type %s" % ( From antocuni at codespeak.net Wed Sep 27 15:54:07 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 27 Sep 2006 15:54:07 +0200 (CEST) Subject: [pypy-svn] r32666 - pypy/extradoc/sprintinfo/ddorf2006b Message-ID: <20060927135407.AE1D110070@code0.codespeak.net> Author: antocuni Date: Wed Sep 27 15:54:05 2006 New Revision: 32666 Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt Log: Add my info. Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006b/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006b/people.txt Wed Sep 27 15:54:05 2006 @@ -11,6 +11,7 @@ Carl Friedrich Bolz always there private Armin Rigo 27th / - private Michael Hudson 29th / - private +Antonio Cuni always there private ==================== ============== ===================== People on the following list were present at previous sprints: @@ -38,7 +39,6 @@ Anders Chrigstroem ? ? Samuele Pedroni ? ? Christian Tismer ? ? -Antonio Cuni ? ? Anders Lehmann ? ? Niklaus Haldimann ? ? Christian Tismer ? ? From mwh at codespeak.net Wed Sep 27 16:15:01 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 27 Sep 2006 16:15:01 +0200 (CEST) Subject: [pypy-svn] r32667 - in pypy/dist/pypy: rpython/memory rpython/memory/test translator/c/test Message-ID: <20060927141501.9402810060@code0.codespeak.net> Author: mwh Date: Wed Sep 27 16:14:58 2006 New Revision: 32667 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/test/test_gctransform.py pypy/dist/pypy/translator/c/test/test_lltyped.py Log: a fix and two tests for the refcountinggctransformer's handling of string allocations. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed Sep 27 16:14:58 2006 @@ -577,12 +577,15 @@ TYPE = op.result.concretetype.TO assert TYPE._is_varsize() - c_const_size = intconst(llmemory.sizeof(TYPE, 0)) if isinstance(TYPE, lltype.Struct): ARRAY = TYPE._flds[TYPE._arrayfld] else: ARRAY = TYPE assert isinstance(ARRAY, lltype.Array) + if ARRAY._hints.get('isrpystring', False): + c_const_size = intconst(llmemory.sizeof(TYPE, 1)) + else: + c_const_size = intconst(llmemory.sizeof(TYPE, 0)) c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) ops = [] Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py Wed Sep 27 16:14:58 2006 @@ -785,6 +785,23 @@ res = llinterp.eval_graph(graph, [10]) assert res == f(10) +def test_llinterp_refcounted_graph_str(): + from pypy.annotation.model import SomeString + from pypy.rpython.lltypesystem.rstr import string_repr + + def f(x): + return len(x + 'a') + + + llinterp, graph = llinterpreter_for_refcounted_graph(f, [SomeString()]) + + cc = string_repr.convert_const + + res = llinterp.eval_graph(graph, [cc('a')]) + assert res == f('a') + res = llinterp.eval_graph(graph, [cc('brrrrrr')]) + assert res == f('brrrrrr') + def test_llinterp_refcounted_graph_with_del(): from pypy.annotation.model import SomeInteger Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Wed Sep 27 16:14:58 2006 @@ -266,3 +266,24 @@ res1 = fn(1) res2 = fn(0) assert res1 == res2 + + def test_null_padding(self): + from pypy.rpython.lltypesystem import llmemory + from pypy.rpython.lltypesystem import rstr + chars_offset = llmemory.FieldOffset(rstr.STR, 'chars') + \ + llmemory.ArrayItemsOffset(rstr.STR.chars) + # sadly, there's no way of forcing this to fail if the strings + # are allocated in a region of memory such that they just + # happen to get a NUL byte anyway :/ (a debug build will + # always fail though) + def trailing_byte(s): + adr_s = llmemory.cast_ptr_to_adr(s) + return (adr_s + chars_offset).char[len(s)] + def f(x=int): + r = 0 + for i in range(x): + r += ord(trailing_byte(' '*(100-x*x))) + return r + fn = self.getcompiled(f) + res = fn(10) + assert res == 0 From pedronis at codespeak.net Wed Sep 27 16:33:31 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Sep 2006 16:33:31 +0200 (CEST) Subject: [pypy-svn] r32668 - pypy/extradoc/sprintinfo/ddorf2006b Message-ID: <20060927143331.E1FFA10060@code0.codespeak.net> Author: pedronis Date: Wed Sep 27 16:33:30 2006 New Revision: 32668 Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt Log: dates for me and arre. fixed arigo date. Modified: pypy/extradoc/sprintinfo/ddorf2006b/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006b/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006b/people.txt Wed Sep 27 16:33:30 2006 @@ -9,9 +9,11 @@ Name Arrive/Depart Accomodation ==================== ============== ===================== Carl Friedrich Bolz always there private -Armin Rigo 27th / - private +Armin Rigo 28th / - private Michael Hudson 29th / - private Antonio Cuni always there private +Samuele Pedroni 28th-6th Hotel an der Uni +Anders Chrigstroem 29th-6th Hotel an der Uni ==================== ============== ===================== People on the following list were present at previous sprints: From mwh at codespeak.net Wed Sep 27 16:37:43 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 27 Sep 2006 16:37:43 +0200 (CEST) Subject: [pypy-svn] r32669 - pypy/dist/pypy/translator/c/test Message-ID: <20060927143743.A641C10060@code0.codespeak.net> Author: mwh Date: Wed Sep 27 16:37:41 2006 New Revision: 32669 Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py Log: it seems someone didn't really have their brain plugged in when trying to make test_union pass on a big endian system :) Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Wed Sep 27 16:37:41 2006 @@ -244,13 +244,13 @@ hints={'union': True}) u = malloc(U, immortal=True) def llf(c=int): - u.s = 0x1020 + u.s = 0x10203040 u.c = chr(c) return u.s fn = self.getcompiled(llf) res = fn(0x33) - assert res in [0x1033, 0x3320] + assert res in [0x10203033, 0x33203040] def test_sizeof_void_array(self): from pypy.rpython.lltypesystem import llmemory From auc at codespeak.net Wed Sep 27 18:03:57 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Wed, 27 Sep 2006 18:03:57 +0200 (CEST) Subject: [pypy-svn] r32670 - pypy/dist/pypy/module/_stackless Message-ID: <20060927160357.764D31006F@code0.codespeak.net> Author: auc Date: Wed Sep 27 18:03:55 2006 New Revision: 32670 Modified: pypy/dist/pypy/module/_stackless/clonable.py Log: with this, it is possible to build a pypy where running app-level coroutines cloned from freshly-created ones work Modified: pypy/dist/pypy/module/_stackless/clonable.py ============================================================================== --- pypy/dist/pypy/module/_stackless/clonable.py (original) +++ pypy/dist/pypy/module/_stackless/clonable.py Wed Sep 27 18:03:55 2006 @@ -14,7 +14,6 @@ from pypy.tool import stdlib_opcode as pythonopcode class ClonableCoroutine(InterpClonableCoroutine): - local_pool = None #XXX cut'n'pasted from AppCoroutine # so, watch changes in coroutine.py @@ -183,6 +182,25 @@ self.frame = switch_frame + def w_clone(self): + if not we_are_translated(): + raise NotImplementedError + if self.getcurrent() is self: + raise RuntimeError("clone() cannot clone the current coroutine; " + "use fork() instead") + if self.local_pool is None: # force it now + self.local_pool = gc_swap_pool(gc_swap_pool(None)) + # cannot gc_clone() directly self, because it is not in its own + # local_pool. Moreover, it has a __del__, which cloning doesn't + # support properly at the moment. + copy = ClonableCoroutine(self.space) + copy.costate = self.costate # or clone thereof + #copy = InterpClonableCoroutine(self.costate) + copy.parent = self.parent + copy.frame, copy.local_pool = gc_clone(self.frame, self.local_pool) + return copy + + def makeStaticMethod(module, classname, funcname): space = module.space space.appexec(map(space.wrap, (module, classname, funcname)), """ @@ -227,6 +245,7 @@ __new__ = interp2app(ClonableCoroutine.descr_method__new__.im_func), _framestack = GetSetProperty(w_descr__framestack), getcurrent = interp2app(ClonableCoroutine.w_getcurrent), + clone = interp2app(ClonableCoroutine.w_clone), __reduce__ = interp2app(ClonableCoroutine.descr__reduce__, unwrap_spec=['self', ObjSpace]), __setstate__ = interp2app(ClonableCoroutine.descr__setstate__, From auc at codespeak.net Wed Sep 27 18:15:40 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Wed, 27 Sep 2006 18:15:40 +0200 (CEST) Subject: [pypy-svn] r32671 - pypy/dist/pypy/objspace/test Message-ID: <20060927161540.582841006F@code0.codespeak.net> Author: auc Date: Wed Sep 27 18:15:38 2006 New Revision: 32671 Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py Log: don't look Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Wed Sep 27 18:15:38 2006 @@ -777,16 +777,16 @@ Solution = newvar() stacklet(solve, s, commit_to, Solution) if commit_to == 1: - assert set(Solution) == set([('room B', 'day 2 PM'), - ('room C', 'day 2 PM'), - ('room A', 'day 1 PM'), - ('room C', 'day 1 AM'), - ('room A', 'day 2 AM'), - ('room A', 'day 1 AM'), - ('room C', 'day 2 AM'), - ('room B', 'day 1 AM'), - ('room B', 'day 2 AM'), - ('room C', 'day 1 PM')]) + assert set(Solution) == set([('room A', 'day 1 AM'), + ('room B', 'day 1 AM'), + ('room B', 'day 2 PM'), + ('room A', 'day 1 PM'), + ('room A', 'day 2 AM'), + ('room C', 'day 2 PM'), + ('room C', 'day 2 AM'), + ('room C', 'day 1 AM'), + ('room C', 'day 1 PM'), + ('room B', 'day 2 AM')]) else: assert set(Solution) == set([('room B', 'day 1 PM'), ('room A', 'day 1 PM'), From auc at codespeak.net Wed Sep 27 18:16:27 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Wed, 27 Sep 2006 18:16:27 +0200 (CEST) Subject: [pypy-svn] r32672 - pypy/dist/pypy/objspace/cclp/constraint/test Message-ID: <20060927161627.0F49610074@code0.codespeak.net> Author: auc Date: Wed Sep 27 18:16:25 2006 New Revision: 32672 Modified: pypy/dist/pypy/objspace/cclp/constraint/test/test_fd.py Log: one more test (for __eq__ and __ne__ on domains) Modified: pypy/dist/pypy/objspace/cclp/constraint/test/test_fd.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/test/test_fd.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/test/test_fd.py Wed Sep 27 18:16:25 2006 @@ -20,6 +20,15 @@ def test_remove_all_values(self): fd = FiniteDomain([3]) raises(ConsistencyError, fd.remove_value, 3) + + + def test_predicates(self): + fd1 = FiniteDomain([3]) + fd2 = FiniteDomain([3, 4]) + assert fd1 != fd2 + assert not (fd1 == fd2) + assert fd1 == FiniteDomain([3]) + assert not (fd1 != FiniteDomain([3])) def test_remove_values(self): fd = FiniteDomain([1, 2, 3]) From auc at codespeak.net Wed Sep 27 18:20:49 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Wed, 27 Sep 2006 18:20:49 +0200 (CEST) Subject: [pypy-svn] r32673 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060927162049.C846210072@code0.codespeak.net> Author: auc Date: Wed Sep 27 18:20:46 2006 New Revision: 32673 Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py pypy/dist/pypy/objspace/cclp/constraint/domain.py pypy/dist/pypy/objspace/cclp/misc.py pypy/dist/pypy/objspace/cclp/scheduler.py pypy/dist/pypy/objspace/cclp/space.py pypy/dist/pypy/objspace/cclp/types.py Log: other transl. fixes so far Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/constraint.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py Wed Sep 27 18:20:46 2006 @@ -6,6 +6,7 @@ from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.stringobject import W_StringObject +from pypy.objspace.std.dictobject import W_DictObject from pypy.objspace.constraint.computationspace import W_ComputationSpace @@ -14,8 +15,8 @@ from pypy.objspace.std.model import StdObjSpaceMultiMethod -from pypy.objspace.constraint.btree import BTree -from pypy.objspace.constraint.util import sort, reverse +#from pypy.objspace.constraint.btree import BTree +#from pypy.objspace.constraint.util import sort all_mms = {} @@ -73,6 +74,13 @@ make_filter_mm.register(make_filter__List_String, W_ListObject, W_StringObject) all_mms['make_filter'] = make_filter_mm +class Quadruple(object): + def __init__(self, zero, one, two, three): + self.zero = zero + self.one = one + self.two = two + self.three = three + class W_Expression(W_AbstractConstraint): """A constraint represented as a python expression.""" @@ -101,13 +109,19 @@ assert isinstance(domain, W_AbstractDomain) values = domain.get_values() assert isinstance(values, list) - variables.append((domain.size(), - [variable.w_name(), values, 0, len(values)])) + ds = domain.size() + w_name = variable.w_name() + lval = len(values) + vstruct = (ds, Quadruple(w_name, values, 0, lval)) + variables.append(vstruct) + # was meant to be: + #variables.append((domain.size(), + # [w_name, values, 0, len(values)])) first_value = values[0] assert isinstance(first_value, W_Root) kwargs.content[variable.w_name()] = first_value # sort variables to instanciate those with fewer possible values first - sort(variables) + variables.sort() self._assign_values_state = variables return kwargs @@ -117,51 +131,62 @@ variables = self._assign_values_state for _, curr in variables: - w_name = curr[0] - dom_values = curr[1] - dom_index = curr[2] - dom_len = curr[3] + w_name = curr.zero + dom_values = curr.one + dom_index = curr.two + dom_len = curr.three if dom_index < dom_len: - kwargs.content[w_name] = dom_values[curr[2]] - curr[2] = dom_index + 1 + kwargs.content[w_name] = dom_values[curr.two] + curr.two = dom_index + 1 break else: - curr[2] = 0 + curr.two = 0 kwargs.content[w_name] = dom_values[0] else: # it's over raise StopIteration - #XXX this smells return kwargs def revise(self): """generic propagation algorithm for n-ary expressions""" + sp = self._space maybe_entailed = True ffunc = self.filter_func result_cache = self._init_result_cache() + assert isinstance(result_cache, W_DictObject) kwargs = self._assign_values() + assert isinstance(kwargs, W_DictObject) while 1: try: kwargs = self._next_value(kwargs) + assert isinstance(kwargs, W_DictObject) except StopIteration: break if maybe_entailed: for varname, val in kwargs.content.iteritems(): - if val not in result_cache.content[varname].content: + val_dict = result_cache.content[varname] + assert isinstance(val_dict, W_DictObject) + if val not in val_dict.content: break else: continue - if self._space.is_true(self._space.call(self._space.wrap(ffunc), - self._space.newlist([]), kwargs)): + if sp.is_true(sp.call(sp.wrap(ffunc), + sp.newlist([]), kwargs)): for var, val in kwargs.content.items(): - result_cache.content[var].content[val] = self._space.w_True + var_dict = result_cache.content[var] + assert isinstance(var_dict, W_DictObject) + var_dict.content[val] = sp.w_True else: maybe_entailed = False try: for varname, keep in result_cache.content.items(): - domain = self._names_to_vars[self._space.str_w(varname)].w_dom + var = self._names_to_vars[sp.str_w(varname)] + assert isinstance(var, W_Variable) + assert isinstance(keep, W_DictObject) + domain = var.w_dom + assert isinstance(domain, W_AbstractDomain) domain.remove_values([val for val in domain._values.content.keys() if val not in keep.content]) @@ -202,20 +227,25 @@ def revise(self): _spc = self._space - ord_vars = BTree() + #ord_vars = BTree() + variables = [] for variable in self._variables: assert isinstance(variable, W_Variable) - ord_vars.add((variable.w_dom).size(), - (variable, variable.w_dom)) + dom = variable.w_dom + assert isinstance(dom, W_AbstractDomain) + variables.append((dom.size(), variable)) - variables = ord_vars.values() + variables.sort() + # variable = ord_vars.values() # if a domain has a size of 1, # then the value must be removed from the other domains - for var, dom in variables: + for _, var in variables: + dom = var.w_dom if dom.size() == 1: #print "AllDistinct removes values" - for _var, _dom in variables: + for _, _var in variables: + _dom = _var.w_dom if not _var._same_as(var): try: _dom.remove_value(dom.get_values()[0]) @@ -226,7 +256,8 @@ # if there are less values than variables, the constraint fails values = {} - for var, dom in variables: + for _, var in variables: + dom = var.w_dom for val in dom.w_get_values().wrappeditems: values[val] = 0 @@ -236,7 +267,8 @@ _spc.wrap("ConsistencyFailure")) # the constraint is entailed if all domains have a size of 1 - for _var, dom in variables: + for _, var in variables: + dom = var.w_dom if not dom.size() == 1: return False @@ -249,7 +281,7 @@ "W_AllDistinct", W_AbstractConstraint.typedef, revise = interp2app(W_AllDistinct.w_revise)) -# function bolted into the space to serve as constructor +#function bolted into the space to serve as constructor def make_alldistinct(object_space, w_variables): assert isinstance(w_variables, W_ListObject) assert len(w_variables.wrappeditems) > 0 Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/domain.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/domain.py Wed Sep 27 18:20:46 2006 @@ -121,7 +121,9 @@ def __ne__(self, w_other): if not isinstance(w_other, W_FiniteDomain): return self._space.newbool(True) - return self._space.newbool(self._space.ne_w(self._values, w_other._values)) + if self._space.eq_w(self._values, w_other._values): + return self._space.newbool(False) + return self._space.newbool(True) Modified: pypy/dist/pypy/objspace/cclp/misc.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/misc.py (original) +++ pypy/dist/pypy/objspace/cclp/misc.py Wed Sep 27 18:20:46 2006 @@ -22,10 +22,8 @@ def get_current_cspace(space): curr = ClonableCoroutine.w_getcurrent(space) assert isinstance(curr, ClonableCoroutine) - assert hasattr(curr, '_cspace') return curr._cspace - def interp_id(space, w_obj): "debugging purposes only" assert isinstance(w_obj, baseobjspace.W_Root) Modified: pypy/dist/pypy/objspace/cclp/scheduler.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/scheduler.py (original) +++ pypy/dist/pypy/objspace/cclp/scheduler.py Wed Sep 27 18:20:46 2006 @@ -168,7 +168,7 @@ "insert 'thread' at end of running queue" assert isinstance(thread, ClonableCoroutine) # cspace account mgmt - if thread._cspace != None: + if thread._cspace is not None: self._per_space_live_threads.get(thread._cspace, 0) self.inc_live_thread_count(thread._cspace) self._chain_insert(thread) Modified: pypy/dist/pypy/objspace/cclp/space.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/space.py (original) +++ pypy/dist/pypy/objspace/cclp/space.py Wed Sep 27 18:20:46 2006 @@ -127,6 +127,10 @@ self._store = {} return self._solution + def __ne__(self, other): + if other is self: + return False + return True W_CSpace.typedef = typedef.TypeDef("W_CSpace", Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Wed Sep 27 18:20:46 2006 @@ -94,6 +94,9 @@ def get_values(self): pass + def remove_values(self, values): + assert isinstance(values, list) + def size(self): pass From mwh at codespeak.net Wed Sep 27 19:01:50 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 27 Sep 2006 19:01:50 +0200 (CEST) Subject: [pypy-svn] r32674 - pypy/dist/pypy/translator/c Message-ID: <20060927170150.830181006F@code0.codespeak.net> Author: mwh Date: Wed Sep 27 19:01:48 2006 New Revision: 32674 Modified: pypy/dist/pypy/translator/c/gc.py Log: i hate test_database Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Wed Sep 27 19:01:48 2006 @@ -67,14 +67,20 @@ transformerclass = gctransform.RefcountingGCTransformer def common_gcheader_definition(self, defnode): - HDR = defnode.db.gctransformer.HDR - return [(name, HDR._flds[name]) for name in HDR._names] + if defnode.db.gctransformer is not None: + HDR = defnode.db.gctransformer.HDR + return [(name, HDR._flds[name]) for name in HDR._names] + else: + return [] def common_gcheader_initdata(self, defnode): - gct = defnode.db.gctransformer - hdr = gct.gcheaderbuilder.header_of_object(top_container(defnode.obj)) - HDR = gct.HDR - return [getattr(hdr, fldname) for fldname in HDR._names] + if defnode.db.gctransformer is not None: + gct = defnode.db.gctransformer + hdr = gct.gcheaderbuilder.header_of_object(top_container(defnode.obj)) + HDR = gct.HDR + return [getattr(hdr, fldname) for fldname in HDR._names] + else: + return [] # for structs From mwh at codespeak.net Wed Sep 27 19:03:28 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 27 Sep 2006 19:03:28 +0200 (CEST) Subject: [pypy-svn] r32675 - pypy/dist/pypy/translator/c/test Message-ID: <20060927170328.AB6241006F@code0.codespeak.net> Author: mwh Date: Wed Sep 27 19:03:27 2006 New Revision: 32675 Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py Log: untabify Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Wed Sep 27 19:03:27 2006 @@ -256,16 +256,16 @@ from pypy.rpython.lltypesystem import llmemory A = Array(Void) size1 = llmemory.sizeof(A, 1) - size2 = llmemory.sizeof(A, 14) + size2 = llmemory.sizeof(A, 14) def f(x=int): - if x: - return size1 - else: - return size2 - fn = self.getcompiled(f) - res1 = fn(1) - res2 = fn(0) - assert res1 == res2 + if x: + return size1 + else: + return size2 + fn = self.getcompiled(f) + res1 = fn(1) + res2 = fn(0) + assert res1 == res2 def test_null_padding(self): from pypy.rpython.lltypesystem import llmemory @@ -284,6 +284,6 @@ for i in range(x): r += ord(trailing_byte(' '*(100-x*x))) return r - fn = self.getcompiled(f) - res = fn(10) + fn = self.getcompiled(f) + res = fn(10) assert res == 0 From arigo at codespeak.net Wed Sep 27 19:18:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 19:18:41 +0200 (CEST) Subject: [pypy-svn] r32676 - in pypy/dist/pypy/rpython: . test Message-ID: <20060927171841.226A01006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 19:18:39 2006 New Revision: 32676 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: (arre, pedronis, arigo) Yet another missing case in rpbc! Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Sep 27 19:18:39 2006 @@ -324,6 +324,9 @@ return v if r_fpbc1.lowleveltype is Void: return inputconst(r_fpbc2, r_fpbc1.s_pbc.const) + if r_fpbc2.lowleveltype is Void: + wrapper = HalfConcreteWrapper(r_fpbc2.get_unique_llfn) + return inputconst(Void, wrapper) return NotImplemented class OverriddenFunctionPBCRepr(Repr): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Sep 27 19:18:39 2006 @@ -1401,6 +1401,23 @@ res = self.interpret(f, [1]) assert res == 42 + def test_funcornone_to_func(self): + def g(y): + return y*2 + def f(x): + if x > 0: + g1 = g + else: + g1 = None + x += 1 + if g1: + return g1(x) + else: + return -1 + + res = self.interpret(f, [20]) + assert res == 42 + # We don't care about the following test_hlinvoke tests working on # ootype. Maybe later. This kind of thing is only used in rdict From arigo at codespeak.net Wed Sep 27 20:56:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 20:56:43 +0200 (CEST) Subject: [pypy-svn] r32677 - in pypy/dist/pypy: module/_socket rpython/rctypes/socketmodule Message-ID: <20060927185643.49DAC1006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 20:56:40 2006 New Revision: 32677 Modified: pypy/dist/pypy/module/_socket/rsocket.py pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Log: Intermediate check-in. Modified: pypy/dist/pypy/module/_socket/rsocket.py ============================================================================== --- pypy/dist/pypy/module/_socket/rsocket.py (original) +++ pypy/dist/pypy/module/_socket/rsocket.py Wed Sep 27 20:56:40 2006 @@ -317,7 +317,7 @@ self.proto = proto def error_handler(self): - return CSocketError(_c.errno()) + return last_error() # convert an Address into an app-level object def addr_as_object(self, space, address): @@ -487,8 +487,53 @@ def __str__(self): return _c.socket_strerror(self.errno) +def last_error(): + return CSocketError(_c.errno()) + class GAIError(BaseSocketError): def __init__(self, errno): self.errno = errno def __str__(self): return _c.gai_strerror(self.errno) + +# ____________________________________________________________ + +if _c.AF_UNIX is None: + socketpair_default_family = _c.AF_INET +else: + socketpair_default_family = _c.AF_UNIX + +def socketpair(family=socketpair_default_family, type=_c.SOCK_STREAM, proto=0): + """socketpair([family[, type[, proto]]]) -> (socket object, socket object) + + Create a pair of socket objects from the sockets returned by the platform + socketpair() function. + The arguments are the same as for socket() except the default family is + AF_UNIX if defined on the platform; otherwise, the default is AF_INET. + """ + result = _c.socketpair_t() + res = _c.socketpair(family, type, proto, byref(result)) + if res < 0: + raise last_error() + return (make_socket(result[0], family, type, proto), + make_socket(result[1], family, type, proto)) + +def fromfd(fd, family, type, proto=0): + # Dup the fd so it and the socket can be closed independently + fd = _c.dup(fd) + if fd < 0: + raise last_error() + return make_socket(fd, family, type, proto) + +def gethostname(): + buf = create_string_buffer(1024) + res = _c.gethostname(buf, sizeof(buf)-1) + if res < 0: + raise last_error() + buf[sizeof(buf)-1] = '\x00' + return buf.value + +def gethostbyname(name): + address = INETAddress.from_null() + address.makeipaddr(name) + return address Modified: pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py (original) +++ pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Wed Sep 27 20:56:40 2006 @@ -384,7 +384,7 @@ socketpair_t = ARRAY(c_int, 2) socketpair = socketdll.socketpair -socketpair.argtypes = [c_int, c_int, c_int, POINTER(c_int)] +socketpair.argtypes = [c_int, c_int, c_int, POINTER(socketpair_t)] socketpair.restype = c_int shutdown = socketdll.shutdown From arigo at codespeak.net Wed Sep 27 20:57:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 20:57:22 +0200 (CEST) Subject: [pypy-svn] r32678 - pypy/dist/pypy/objspace/std Message-ID: <20060927185722.C16501006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 20:57:21 2006 New Revision: 32678 Modified: pypy/dist/pypy/objspace/std/unicodeobject.py Log: Comment out confusing code. Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Wed Sep 27 20:57:21 2006 @@ -79,12 +79,13 @@ return space.wrap(1) return space.wrap(0) -def cmp__Unicode_ANY(space, w_left, w_right): - try: - w_right = space.call_function(space.w_unicode, w_right) - except: - return space.wrap(1) - return space.cmp(w_left, w_right) +## XXX what?? the following seems unnecessary +##def cmp__Unicode_ANY(space, w_left, w_right): +## try: +## w_right = space.call_function(space.w_unicode, w_right) +## except: +## return space.wrap(1) +## return space.cmp(w_left, w_right) def ord__Unicode(space, w_uni): if len(w_uni._value) != 1: From arigo at codespeak.net Wed Sep 27 20:59:15 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 20:59:15 +0200 (CEST) Subject: [pypy-svn] r32679 - pypy/dist/pypy/objspace/flow Message-ID: <20060927185915.513011006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 20:59:13 2006 New Revision: 32679 Modified: pypy/dist/pypy/objspace/flow/model.py Log: A more precise checkgraph() for the exit links after an exitswitch. This one also doesn't complain about a switch with only a 'default' path, as the JIT creates (as an intermediate to more complete switches). Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Wed Sep 27 20:59:13 2006 @@ -644,7 +644,17 @@ else: assert isinstance(block.exitswitch, Variable) assert block.exitswitch in vars - assert len(block.exits) > 1 + if (len(block.exits) == 2 and block.exits[0].exitcase is False + and block.exits[1].exitcase is True): + # a boolean switch + pass + else: + # a multiple-cases switch (or else the False and True + # branches are in the wrong order) + assert len(block.exits) >= 1 + assert block.exits[-1].exitcase == "default" + cases = [Constant(link.exitcase) for link in block.exits] + assert len(dict.fromkeys(cases)) == len(cases) allexitcases = {} for link in block.exits: From arigo at codespeak.net Wed Sep 27 21:00:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 21:00:17 +0200 (CEST) Subject: [pypy-svn] r32680 - pypy/dist/pypy/translator Message-ID: <20060927190017.C5DF11006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 21:00:15 2006 New Revision: 32680 Modified: pypy/dist/pypy/translator/simplify.py Log: Fixes to avoid relying on having-a-single-exit as meaning that there is no exitswitch (see r32679). Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Wed Sep 27 21:00:15 2006 @@ -60,10 +60,11 @@ def visit(link): if isinstance(link, Link): while not link.target.operations: - if (len(link.target.exits) != 1 and - link.target.exitswitch != c_last_exception): - break block1 = link.target + if block1.exitswitch is not None: + break + if not block1.exits: + break exit = block1.exits[0] assert block1 is not exit.target, ( "the graph contains an empty infinite loop") @@ -321,9 +322,10 @@ stack = list(block.exits) while stack: link = stack.pop() - if (len(link.prevblock.exits) == 1 and + if (link.prevblock.exitswitch is None and len(entrymap[link.target]) == 1 and link.target.exits): # stop at the returnblock + assert len(link.prevblock.exits) == 1 renaming = {} for vprev, vtarg in zip(link.args, link.target.inputargs): renaming[vtarg] = vprev From arigo at codespeak.net Wed Sep 27 21:03:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 21:03:06 +0200 (CEST) Subject: [pypy-svn] r32681 - in pypy/dist/pypy: objspace/cpy rpython Message-ID: <20060927190306.253121006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 21:03:04 2006 New Revision: 32681 Modified: pypy/dist/pypy/objspace/cpy/appsupport.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/extregistry.py Log: (pedronis, arre, arigo) Clean-up: extregistry entries can assume that they always have a bookkeeper during annotation, nowadays. Modified: pypy/dist/pypy/objspace/cpy/appsupport.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/appsupport.py (original) +++ pypy/dist/pypy/objspace/cpy/appsupport.py Wed Sep 27 21:03:04 2006 @@ -36,9 +36,7 @@ _type_ = W_AppLevel def compute_annotation(self): - from pypy.annotation.bookkeeper import getbookkeeper - bk = getbookkeeper() - return lookup_type(W_Object).compute_annotation() + return lookup_type(W_Object).compute_annotation_bk(self.bookkeeper) def genc_pyobj(self, pyobjmaker): dictname = pyobjmaker.nameof(self.instance.w_moddict) @@ -51,9 +49,7 @@ _type_ = W_AppLevelModDict def compute_annotation(self): - from pypy.annotation.bookkeeper import getbookkeeper - bk = getbookkeeper() - return lookup_type(W_Object).compute_annotation() + return lookup_type(W_Object).compute_annotation_bk(self.bookkeeper) def genc_pyobj(self, pyobjmaker): import marshal Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed Sep 27 21:03:04 2006 @@ -322,11 +322,10 @@ assert s_F.is_constant() assert s_callable.is_constant() F = s_F.const - if hasattr(self, 'bookkeeper'): - args_s = [annmodel.lltype_to_annotation(T) for T in F.TO.ARGS] - key = (llhelper, s_callable.const) - s_res = self.bookkeeper.emulate_pbc_call(key, s_callable, args_s) - assert annmodel.lltype_to_annotation(F.TO.RESULT).contains(s_res) + args_s = [annmodel.lltype_to_annotation(T) for T in F.TO.ARGS] + key = (llhelper, s_callable.const) + s_res = self.bookkeeper.emulate_pbc_call(key, s_callable, args_s) + assert annmodel.lltype_to_annotation(F.TO.RESULT).contains(s_res) return annmodel.SomePtr(F) def specialize_call(self, hop): Modified: pypy/dist/pypy/rpython/extregistry.py ============================================================================== --- pypy/dist/pypy/rpython/extregistry.py (original) +++ pypy/dist/pypy/rpython/extregistry.py Wed Sep 27 21:03:04 2006 @@ -97,8 +97,9 @@ return self.compute_annotation() def compute_annotation(self): + # callers should always use compute_annotation_bk()! # default implementation useful for built-in functions, - # can be overriden + # can be overriden. func = self.instance assert func is not None from pypy.annotation import model as annmodel From arigo at codespeak.net Wed Sep 27 21:11:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 21:11:23 +0200 (CEST) Subject: [pypy-svn] r32682 - in pypy/dist/pypy/rpython: . test Message-ID: <20060927191123.D93F51006F@code0.codespeak.net> Author: arigo Date: Wed Sep 27 21:11:22 2006 New Revision: 32682 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/test/test_llann.py Log: (pedronis, arre, arigo) Mostly obscure extensions to annlowlevel.py to cope with what the JIT requires: capability to build delayed function pointers whose lltype is still computed early; and a bunch of cast_xxx() functions to convert between low-level and high-level representations of objects. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed Sep 27 21:11:22 2006 @@ -119,8 +119,9 @@ class MixLevelAnnotatorPolicy(LowLevelAnnotatorPolicy): - def __init__(pol, rtyper): - pol.rtyper = rtyper + def __init__(pol, annhelper): + pol.annhelper = annhelper + pol.rtyper = annhelper.rtyper def default_specialize(pol, funcdesc, args_s): name = funcdesc.name @@ -147,9 +148,9 @@ def __init__(self, rtyper): self.rtyper = rtyper - self.policy = MixLevelAnnotatorPolicy(rtyper) + self.policy = MixLevelAnnotatorPolicy(self) self.pending = [] # list of (ll_function, graph, args_s, s_result) - self.delayedreprs = [] + self.delayedreprs = {} self.delayedconsts = [] self.delayedfuncs = [] self.original_graph_count = len(rtyper.annotator.translator.graphs) @@ -167,18 +168,26 @@ self.pending.append((ll_function, graph, args_s, s_result)) return graph - def delayedfunction(self, ll_function, args_s, s_result): + def delayedfunction(self, ll_function, args_s, s_result, needtype=False): # get a delayed pointer to the low-level function, annotated as # specified. The pointer is only valid after finish() was called. graph = self.getgraph(ll_function, args_s, s_result) - return self.graph2delayed(graph) + if needtype: + ARGS = [self.getdelayedrepr(s_arg, False).lowleveltype + for s_arg in args_s] + RESULT = self.getdelayedrepr(s_result, False).lowleveltype + FUNCTYPE = lltype.FuncType(ARGS, RESULT) + else: + FUNCTYPE = None + return self.graph2delayed(graph, FUNCTYPE) def constfunc(self, ll_function, args_s, s_result): p = self.delayedfunction(ll_function, args_s, s_result) return Constant(p, lltype.typeOf(p)) - def graph2delayed(self, graph): - FUNCTYPE = lltype.ForwardReference() + def graph2delayed(self, graph, FUNCTYPE=None): + if FUNCTYPE is None: + FUNCTYPE = lltype.ForwardReference() # obscure hack: embed the name of the function in the string, so # that the genc database can get it even before the delayedptr # is really computed @@ -191,20 +200,25 @@ p = self.graph2delayed(graph) return Constant(p, lltype.typeOf(p)) - def getdelayedrepr(self, s_value): + def getdelayedrepr(self, s_value, check_never_seen=True): """Like rtyper.getrepr(), but the resulting repr will not be setup() at all before finish() is called. """ r = self.rtyper.getrepr(s_value) - r.set_setup_delayed(True) - self.delayedreprs.append(r) + if check_never_seen: + r.set_setup_delayed(True) + delayed = True + else: + delayed = r.set_setup_maybe_delayed() + if delayed: + self.delayedreprs[r] = True return r - def s_r_instanceof(self, cls, can_be_None=True): + def s_r_instanceof(self, cls, can_be_None=True, check_never_seen=True): classdesc = self.rtyper.annotator.bookkeeper.getdesc(cls) classdef = classdesc.getuniqueclassdef() s_instance = annmodel.SomeInstance(classdef, can_be_None) - r_instance = self.getdelayedrepr(s_instance) + r_instance = self.getdelayedrepr(s_instance, check_never_seen) return s_instance, r_instance def delayedconst(self, repr, obj): @@ -259,10 +273,14 @@ rtyper.call_all_setups() for p, graph in self.delayedfuncs: real_p = rtyper.getcallable(graph) - lltype.typeOf(p).TO.become(lltype.typeOf(real_p).TO) + REAL = lltype.typeOf(real_p).TO + FUNCTYPE = lltype.typeOf(p).TO + if isinstance(FUNCTYPE, lltype.ForwardReference): + FUNCTYPE.become(REAL) + assert FUNCTYPE == REAL p._become(real_p) rtyper.specialize_more_blocks() - del self.delayedreprs[:] + self.delayedreprs.clear() del self.delayedconsts[:] del self.delayedfuncs[:] @@ -330,7 +348,73 @@ def specialize_call(self, hop): return hop.args_r[1].get_unique_llfn() - + +# ____________________________________________________________ + +def cast_object_to_ptr(PTR, object): + raise NotImplementedError("cast_object_to_ptr") + +def cast_instance_to_base_ptr(instance): + return cast_object_to_ptr(base_ptr_lltype(), instance) + +def base_ptr_lltype(): + from pypy.rpython.lltypesystem.rclass import OBJECTPTR + return OBJECTPTR + +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) + + def specialize_call(self, hop): + v_arg = hop.inputarg(hop.args_r[1], arg=1) + assert isinstance(v_arg.concretetype, lltype.Ptr) + return hop.genop('cast_pointer', [v_arg], + resulttype = hop.r_result.lowleveltype) + +# ____________________________________________________________ + +def cast_base_ptr_to_instance(Class, ptr): + raise NotImplementedError("cast_base_ptr_to_instance") + +class CastBasePtrToInstanceEntry(extregistry.ExtRegistryEntry): + _about_ = cast_base_ptr_to_instance + + def compute_result_annotation(self, s_Class, s_ptr): + assert s_Class.is_constant() + classdef = self.bookkeeper.getuniqueclassdef(s_Class.const) + return annmodel.SomeInstance(classdef, can_be_None=True) + + def specialize_call(self, hop): + v_arg = hop.inputarg(hop.args_r[1], arg=1) + assert isinstance(v_arg.concretetype, lltype.Ptr) + return hop.genop('cast_pointer', [v_arg], + resulttype = hop.r_result.lowleveltype) + +# ____________________________________________________________ + +## XXX finish me +##def cast_instance_to_ptr(Class, instance): +## raise NotImplementedError("cast_instance_to_ptr") + +##class CastInstanceToPtrEntry(extregistry.ExtRegistryEntry): +## _about_ = cast_instance_to_ptr + +## def compute_result_annotation(self, s_Class, s_instance): +## assert s_Class.is_constant() +## pol = self.bookkeeper.annotator.policy +## s_Instance, r_Instance = pol.annhelper.s_r_instanceof(s_Class.const) +## return annmodel.SomePtr(r_Instance.lowleveltype) + +## def specialize_call(self, hop): +## v_arg = hop.inputarg(hop.args_r[1], arg=1) +## assert isinstance(v_arg.concretetype, lltype.Ptr) +## return hop.genop('cast_pointer', [v_arg], +## resulttype = hop.r_result.lowleveltype) + # ____________________________________________________________ def placeholder_sigarg(s): @@ -401,3 +485,22 @@ else: meth._annenforceargs_ = sig return adtmeths + +# ____________________________________________________________ + +class cachedtype(type): + """Metaclass for classes that should only have one instance per + tuple of arguments given to the constructor.""" + + def __init__(selfcls, name, bases, dict): + super(cachedtype, selfcls).__init__(name, bases, dict) + selfcls._instancecache = {} + + def __call__(selfcls, *args): + d = selfcls._instancecache + try: + return d[args] + except KeyError: + instance = d[args] = selfcls.__new__(selfcls, *args) + instance.__init__(*args) + return instance Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Wed Sep 27 21:11:22 2006 @@ -90,6 +90,11 @@ else: self._initialized = setupstate.NOTINITIALIZED + def set_setup_maybe_delayed(self): + if self._initialized == setupstate.NOTINITIALIZED: + self._initialized = setupstate.DELAYED + return self._initialized == setupstate.DELAYED + def __getattr__(self, name): # Assume that when an attribute is missing, it's because setup() needs # to be called Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Wed Sep 27 21:11:22 2006 @@ -1,10 +1,12 @@ from pypy.rpython.lltypesystem.lltype import * +from pypy.rpython.lltypesystem.rclass import OBJECTPTR, fishllattr from pypy.translator.translator import TranslationContext from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import annotate_lowlevel_helper from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.rpython.annlowlevel import PseudoHighLevelCallable -from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.annlowlevel import llhelper, cast_instance_to_base_ptr +from pypy.rpython.annlowlevel import base_ptr_lltype from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.test.test_llinterp import interpret from pypy.objspace.flow import FlowObjSpace @@ -371,3 +373,20 @@ res = interpret(h, [8, 5, 2]) assert res == 99 + + +def test_cast_instance_to_base_ptr(): + class A: + def __init__(self, x, y): + self.x = x + self.y = y + + def f(x, y): + a = A(x, y) + a1 = cast_instance_to_base_ptr(a) + return a1 + + res = interpret(f, [5, 10]) + assert typeOf(res) == base_ptr_lltype() + assert fishllattr(res, 'x') == 5 + assert fishllattr(res, 'y') == 10 From arigo at codespeak.net Wed Sep 27 21:21:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Sep 2006 21:21:53 +0200 (CEST) Subject: [pypy-svn] r32683 - in pypy/branch/jit-promotion: . pypy/jit/codegen pypy/jit/codegen/llgraph pypy/jit/hintannotator pypy/jit/timeshifter pypy/jit/timeshifter/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/test Message-ID: <20060927192153.D80E210075@code0.codespeak.net> Author: arigo Date: Wed Sep 27 21:21:50 2006 New Revision: 32683 Added: pypy/branch/jit-promotion/ - copied from r32681, pypy/dist/ pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py (contents, props changed) pypy/branch/jit-promotion/pypy/rpython/annlowlevel.py - copied unchanged from r32682, pypy/dist/pypy/rpython/annlowlevel.py pypy/branch/jit-promotion/pypy/rpython/rmodel.py - copied unchanged from r32682, pypy/dist/pypy/rpython/rmodel.py pypy/branch/jit-promotion/pypy/rpython/test/test_llann.py - copied unchanged from r32682, pypy/dist/pypy/rpython/test/test_llann.py Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/jit-promotion/pypy/jit/codegen/model.py pypy/branch/jit-promotion/pypy/jit/hintannotator/model.py pypy/branch/jit-promotion/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py pypy/branch/jit-promotion/pypy/jit/timeshifter/rvalue.py pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py pypy/branch/jit-promotion/pypy/rpython/lltypesystem/lloperation.py Log: (arre, pedronis, arigo) Intermediate check-in to share this big batch of changes: see test_promotion for the goal. Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py Wed Sep 27 21:21:50 2006 @@ -125,14 +125,15 @@ result = op.fold(*examples) return lltype.typeOf(result) -def gencallableconst(name, targetcontainer, gv_FUNCTYPE): +def gencallableconst(name, targetcontainer, returncontainer, gv_FUNCTYPE): # 'name' is just a way to track things if not isinstance(name, str): name = LLSupport.from_rstr(name) target = from_opaque_object(targetcontainer.obj) + returnblock = from_opaque_object(returncontainer.obj) FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value fptr = lltype.functionptr(FUNCTYPE, name, - graph=_buildgraph(target, FUNCTYPE)) + graph=_buildgraph(target, returnblock, FUNCTYPE)) return genconst(fptr) def genconst(llvalue): @@ -202,6 +203,29 @@ return pseudotuple(to_opaque_object(false_link), to_opaque_object(true_link)) +def closeblockswitch(blockcontainer, exitswitch): + block = from_opaque_object(blockcontainer.obj) + exitswitch = from_opaque_object(exitswitch) + assert isinstance(exitswitch, flowmodel.Variable) + block.exitswitch = exitswitch + default_link = flowmodel.Link([], None) + default_link.exitcase = "default" + default_link.llexitcase = None + block.closeblock(default_link) + return to_opaque_object(default_link) + +def add_case(blockcontainer, exitcase): + block = from_opaque_object(blockcontainer.obj) + exitcase = from_opaque_object(exitcase) + assert isinstance(exitcase, flowmodel.Constant) + assert isinstance(block.exitswitch, Variable) + case_link = flowmodel.Link([], None) + case_link.exitcase = exitcase.value + case_link.llexitcase = exitcase.value + exits = block.exits[:-1] + (case_link,) + block.exits[-1:] + block.recloseblock(*exits) + return to_opaque_object(case_link) + class pseudotuple(object): # something that looks both like a hl and a ll tuple def __init__(self, *items): @@ -239,32 +263,32 @@ vars = _inputvars(vars) _closelink(link, vars, targetblock) -def closereturnlink(link, returnvar): - returnvar = from_opaque_object(returnvar) - link = from_opaque_object(link) - v = flowmodel.Variable() - v.concretetype = returnvar.concretetype - pseudoreturnblock = flowmodel.Block([v]) - pseudoreturnblock.operations = () - _closelink(link, [returnvar], pseudoreturnblock) - -def _patchgraph(graph, RESULT): - returntype = None - links = [] - for link in graph.iterlinks(): - if link.target.operations == (): - assert len(link.args) == 1 # for now - if returntype is None: - returntype = link.target.inputargs[0].concretetype - else: - assert returntype == link.target.inputargs[0].concretetype - links.append(link) - if returntype is None: - returntype = lltype.Void - graph.returnblock.inputargs[0].concretetype = RESULT - targetblock = casting_bridge([returntype], [RESULT], graph.returnblock) - for link in links: - link.target = targetblock +##def closereturnlink(link, returnvar): +## returnvar = from_opaque_object(returnvar) +## link = from_opaque_object(link) +## v = flowmodel.Variable() +## v.concretetype = returnvar.concretetype +## pseudoreturnblock = flowmodel.Block([v]) +## pseudoreturnblock.operations = () +## _closelink(link, [returnvar], pseudoreturnblock) + +##def _patchgraph(graph, RESULT): +## returntype = None +## links = [] +## for link in graph.iterlinks(): +## if link.target.operations == (): +## assert len(link.args) == 1 # for now +## if returntype is None: +## returntype = link.target.inputargs[0].concretetype +## else: +## assert returntype == link.target.inputargs[0].concretetype +## links.append(link) +## if returntype is None: +## returntype = lltype.Void +## graph.returnblock.inputargs[0].concretetype = RESULT +## targetblock = casting_bridge([returntype], [RESULT], graph.returnblock) +## for link in links: +## link.target = targetblock class PseudoRTyper(object): def __init__(self): @@ -297,20 +321,28 @@ else: return target -def _buildgraph(block, FUNCTYPE): +def _buildgraph(block, existingreturnblock, FUNCTYPE): ARGS = [v.concretetype for v in block.inputargs] startblock =casting_bridge(FUNCTYPE.ARGS, ARGS, block) graph = flowmodel.FunctionGraph('generated', startblock) - _patchgraph(graph, FUNCTYPE.RESULT) + + returntype = existingreturnblock.inputargs[0].concretetype + RESULT = FUNCTYPE.RESULT + graph.returnblock.inputargs[0].concretetype = RESULT + prereturnblock = casting_bridge([returntype], [RESULT], graph.returnblock) + existingreturnblock.closeblock(flowmodel.Link( + [existingreturnblock.inputargs[0]], + prereturnblock)) flowmodel.checkgraph(graph) eliminate_empty_blocks(graph) join_blocks(graph) graph.rgenop = True return graph -def buildgraph(blockcontainer, FUNCTYPE): +def buildgraph(blockcontainer, returncontainer, FUNCTYPE): block = from_opaque_object(blockcontainer.obj) - return _buildgraph(block, FUNCTYPE) + returnblock = from_opaque_object(returncontainer.obj) + return _buildgraph(block, returnblock, FUNCTYPE) def testgengraph(gengraph, args, viewbefore=False, executor=LLInterpreter): if viewbefore: @@ -318,9 +350,9 @@ llinterp = executor(PseudoRTyper()) return llinterp.eval_graph(gengraph, args) -def runblock(blockcontainer, FUNCTYPE, args, +def runblock(blockcontainer, returncontainer, FUNCTYPE, args, viewbefore=False, executor=LLInterpreter): - graph = buildgraph(blockcontainer, FUNCTYPE) + graph = buildgraph(blockcontainer, returncontainer, FUNCTYPE) return testgengraph(graph, args, viewbefore, executor) # ____________________________________________________________ @@ -396,8 +428,10 @@ setannotation(isconst, annmodel.SomeBool()) setannotation(closeblock1, s_Link) setannotation(closeblock2, s_LinkPair) +setannotation(closeblockswitch, s_Link) +setannotation(add_case, s_Link) setannotation(closelink, None) -setannotation(closereturnlink, None) +#setannotation(closereturnlink, None) setannotation(isptrtype, annmodel.SomeBool()) Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py Wed Sep 27 21:21:50 2006 @@ -1,7 +1,7 @@ from pypy.rpython.objectmodel import specialize from pypy.rpython.lltypesystem import lltype from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator -from pypy.jit.codegen.model import GenVar, GenConst +from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.llgraph import llimpl from pypy.rpython.lltypesystem.rclass import fishllattr @@ -30,14 +30,29 @@ class LLBlock(CodeGenBlock): - def __init__(self, b): + def __init__(self, b, g): self.b = b + self.g = g + +class LLFlexSwitch(CodeGenSwitch): + + def __init__(self, b, g): + self.b = b + self.g = g + + def add_case(self, gv_case): + l_case = llimpl.add_case(self.b, gv_case.v) + builder = LLBuilder(self.g) + builder.lnk = l_case + return builder + class LLBuilder(CodeGenerator): lnk = llimpl.nulllink - def __init__(self): + def __init__(self, g): self.rgenop = rgenop + self.g = g @specialize.arg(1) def genop1(self, opname, gv_arg): @@ -114,7 +129,7 @@ llimpl.closelink(lnk, args_gv, self.b) for i in range(len(args_gv)): args_gv[i] = newb_args_gv[i] - return LLBlock(self.b) + return LLBlock(self.b, self.g) def finish_and_goto(self, args_gv, targetblock): lnk = self.lnk or llimpl.closeblock1(self.b) @@ -122,15 +137,13 @@ llimpl.closelink(lnk, args_gv, targetblock.b) def finish_and_return(self, sigtoken, gv_returnvar): - lnk = self.lnk or llimpl.closeblock1(self.b) - self.lnk = llimpl.nulllink - llimpl.closereturnlink(lnk, - (gv_returnvar or gv_dummy_placeholder).v) + gv_returnvar = gv_returnvar or gv_dummy_placeholder + self.finish_and_goto([gv_returnvar], LLBlock(self.g, self.g)) def jump_if_true(self, gv_cond): l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) self.b = llimpl.nullblock - later_builder = LLBuilder() + later_builder = LLBuilder(self.g) later_builder.lnk = l_true self.lnk = l_false return later_builder @@ -138,24 +151,35 @@ def jump_if_false(self, gv_cond): l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) self.b = llimpl.nullblock - later_builder = LLBuilder() + later_builder = LLBuilder(self.g) later_builder.lnk = l_false self.lnk = l_true return later_builder + def flexswitch(self, gv_switchvar): + l_default = llimpl.closeblockswitch(self.b, gv_switchvar.v) + flexswitch = LLFlexSwitch(self.b, self.g) + self.b = llimpl.nullblock + self.lnk = l_default + return flexswitch + class RGenOp(AbstractRGenOp): gv_Void = gv_Void def newgraph(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE)): - builder = LLBuilder() + returnblock = llimpl.newblock() + llimpl.geninputarg(returnblock, gv_RESULT.v) + g = returnblock # for now + builder = LLBuilder(g) inputargs_gv = builder._newblock(ARGS_gv) - return builder, LLBlock(builder.b), inputargs_gv + return builder, LLBlock(builder.b, builder.g), inputargs_gv def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, entrypoint): return LLConst(llimpl.gencallableconst(name, entrypoint.b, + entrypoint.g, gv_FUNCTYPE.v)) @staticmethod @@ -201,6 +225,11 @@ constPrebuiltGlobal = genconst + def replay(self, block, kinds): + builder = LLBuilder(block.g) + args_gv = builder._newblock(kinds) + return builder, args_gv + # not RPython, just for debugging. Specific to llgraph. @staticmethod def reveal(gv): @@ -210,15 +239,6 @@ v = fishllattr(gv, 'v') return llimpl.reveal(v) - # Builds a real flow.model.FunctionGraph. Specific to llgraph. - @staticmethod - def buildgraph(block, FUNCTYPE): - if hasattr(block, 'b'): - b = block.b - else: - b = fishllattr(block, 'b') - return llimpl.buildgraph(b, FUNCTYPE) - def _freeze_(self): return True # no real point in using a full class in llgraph Modified: pypy/branch/jit-promotion/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/model.py Wed Sep 27 21:21:50 2006 @@ -23,3 +23,7 @@ class AbstractRGenOp(object): pass + + +class CodeGenSwitch(object): + pass Modified: pypy/branch/jit-promotion/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/jit-promotion/pypy/jit/hintannotator/model.py Wed Sep 27 21:21:50 2006 @@ -258,6 +258,10 @@ # turn a variable to a constant origin = getbookkeeper().myorigin() return SomeLLAbstractConstant(hs_v1.concretetype, {origin: True}) + if hs_flags.const.get('promote', False): + hs_concrete = SomeLLAbstractConstant(hs_v1.concretetype, {}) + hs_concrete.eager_concrete = True + return hs_concrete def getfield(hs_v1, hs_fieldname): S = hs_v1.concretetype.TO @@ -311,8 +315,6 @@ return hs_c1 def hint(hs_c1, hs_flags): - if hs_flags.const.get('variable', False): # only for testing purposes!!! - return SomeLLAbstractVariable(hs_c1.concretetype) if hs_flags.const.get('concrete', False): for o in hs_c1.origins: o.set_fixed() @@ -322,6 +324,7 @@ if hs_flags.const.get('forget', False): assert isinstance(hs_c1, SomeLLAbstractConstant) return reorigin(hs_c1) + return SomeLLAbstractValue.hint(hs_c1, hs_flags) def direct_call(hs_f1, *args_hs): bookkeeper = getbookkeeper() Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/rcontainer.py Wed Sep 27 21:21:50 2006 @@ -1,5 +1,6 @@ import operator from pypy.rpython.lltypesystem import lltype +from pypy.rpython.annlowlevel import cachedtype from pypy.jit.timeshifter import rvalue class AbstractContainer(object): @@ -14,27 +15,8 @@ def op_getsubstruct(self, jitstate, fielddesc): raise NotImplementedError - # ____________________________________________________________ -class cachedtype(type): - """Metaclass for classes that should only have one instance per - tuple of arguments given to the constructor.""" - - def __init__(selfcls, name, bases, dict): - super(cachedtype, selfcls).__init__(name, bases, dict) - selfcls._instancecache = {} - - def __call__(selfcls, *args): - d = selfcls._instancecache - try: - return d[args] - except KeyError: - instance = d[args] = selfcls.__new__(selfcls, *args) - instance.__init__(*args) - return instance - - class StructTypeDesc(object): __metaclass__ = cachedtype firstsubstructdesc = None Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py Wed Sep 27 21:21:50 2006 @@ -1,8 +1,12 @@ import operator, weakref +from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype, lloperation, llmemory from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.timeshifter import rvalue from pypy.rpython.unroll import unrolling_iterable +from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr +from pypy.rpython.annlowlevel import cast_base_ptr_to_instance FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops()) @@ -184,7 +188,7 @@ incoming[i].genvar = linkargs[i] return newblock -def start_new_block(states_dic, jitstate, key): +def start_new_block(states_dic, jitstate, key, global_resumer): memo = rvalue.freeze_memo() frozen = jitstate.freeze(memo) memo = rvalue.exactmatch_memo() @@ -193,11 +197,17 @@ assert res, "exactmatch() failed" newblock = enter_next_block(jitstate, outgoingvarboxes) states_dic[key] = frozen, newblock + if global_resumer: + greens_gv = jitstate.greens + rgenop = jitstate.curbuilder.rgenop + jitstate.promotion_path = PromotionPathRoot(greens_gv, rgenop, + frozen, newblock, + global_resumer) start_new_block._annspecialcase_ = "specialize:arglltype(2)" -def retrieve_jitstate_for_merge(states_dic, jitstate, key): +def retrieve_jitstate_for_merge(states_dic, jitstate, key, global_resumer): if key not in states_dic: - start_new_block(states_dic, jitstate, key) + start_new_block(states_dic, jitstate, key, global_resumer) return False # continue frozen, oldblock = states_dic[key] @@ -219,7 +229,7 @@ box.forcevar(jitstate.curbuilder, replace_memo) if replace_memo.boxes: jitstate.replace(replace_memo) - start_new_block(states_dic, jitstate, key) + start_new_block(states_dic, jitstate, key, global_resumer) return False # continue retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)" @@ -304,6 +314,132 @@ ##def ll_gvar_from_constant(jitstate, ll_value): ## return jitstate.curbuilder.rgenop.genconst(ll_value) + + +class ResumingInfo(object): + def __init__(self, promotion_point, gv_value, path): + self.promotion_point = promotion_point + self.gv_value = gv_value + self.path = path + +class PromotionPoint(object): + def __init__(self, flexswitch, promotion_path): + assert promotion_path is not None + self.flexswitch = flexswitch + self.promotion_path = promotion_path + +class AbstractPromotionPath(object): + pass + +class PromotionPathRoot(AbstractPromotionPath): + def __init__(self, greens_gv, rgenop, frozen, portalblock, global_resumer): + self.greens_gv = greens_gv + self.rgenop = rgenop + self.frozen = frozen + self.portalblock = portalblock + self.global_resumer = global_resumer + + def follow_path(self, path): + return self + + def continue_compilation(self, resuminginfo): + incoming = [] + memo = rvalue.unfreeze_memo() + jitstate = self.frozen.unfreeze(incoming, memo) + kinds = [box.kind for box in incoming] + builder, vars_gv = self.rgenop.replay(self.portalblock, kinds) + for i in range(len(incoming)): + incoming[i].genvar = vars_gv[i] + jitstate.curbuilder = builder + jitstate.greens = self.greens_gv + jitstate.resuming = resuminginfo + assert jitstate.frame.backframe is None + self.global_resumer(jitstate) + +class PromotionPathNode(AbstractPromotionPath): + def __init__(self, next): + self.next = next + def follow_path(self, path): + path.append(self.direct) + return self.next.follow_path(path) + +class PromotionPathDirect(PromotionPathNode): + direct = True + +class PromotionPathIndirect(PromotionPathNode): + direct = False + +def ll_continue_compilation(promotion_point_ptr, value): + try: + promotion_point = cast_base_ptr_to_instance(PromotionPoint, + promotion_point_ptr) + path = [] + root = promotion_point.promotion_path.follow_path(path) + gv_value = root.rgenop.genconst(value) + resuminginfo = ResumingInfo(promotion_point, gv_value, path) + root.continue_compilation(resuminginfo) + except Exception, e: + llop.debug_fatalerror(lltype.Void, "compilation-time error", e) + +class PromotionDesc: + __metatype__ = cachedtype + + def __init__(self, ERASED, hrtyper): +## (s_PromotionPoint, +## r_PromotionPoint) = hrtyper.s_r_instanceof(PromotionPoint) + fnptr = hrtyper.annhelper.delayedfunction( + ll_continue_compilation, + [annmodel.SomePtr(base_ptr_lltype()), + annmodel.lltype_to_annotation(ERASED)], + annmodel.s_None, needtype=True) + RGenOp = hrtyper.RGenOp + self.gv_continue_compilation = RGenOp.constPrebuiltGlobal(fnptr) + self.sigtoken = RGenOp.sigToken(lltype.typeOf(fnptr).TO) +## self.PROMOTION_POINT = r_PromotionPoint.lowleveltype + + def _freeze_(self): + return True + +def ll_promote(jitstate, box, promotiondesc): + if box.is_constant(): + save_greens(jitstate, box.genvar) + return False + else: + incoming = [] + memo = rvalue.enter_block_memo() + jitstate.enter_block(incoming, memo) + switchblock = enter_next_block(jitstate, incoming) + + if jitstate.resuming is None: + builder = jitstate.curbuilder + flexswitch = builder.flexswitch(box.getgenvar(builder)) + # default case of the switch: + enter_block(jitstate) + pm = PromotionPoint(flexswitch, jitstate.promotion_path) + ll_pm = cast_instance_to_base_ptr(pm) + gv_pm = builder.rgenop.genconst(ll_pm) + builder.genop_call(promotiondesc.sigtoken, + promotiondesc.gv_continue_compilation, + [gv_pm, box.getgenvar(builder)]) + linkargs = [] + for box in incoming: + linkargs.append(box.getgenvar(builder)) + builder.finish_and_goto(linkargs, switchblock) + return True + else: + assert jitstate.promotion_path is None + resuming = jitstate.resuming + assert len(resuming.path) == 0 + pm = resuming.promotion_point + newbuilder = pm.flexswitch.add_case(resuming.gv_value) + + jitstate.resuming = None + jitstate.promotion_path = pm.promotion_path + jitstate.curbuilder = newbuilder + enter_block(jitstate) + save_greens(jitstate, resuming.gv_value) + return False + # ____________________________________________________________ class BaseDispatchQueue(object): @@ -346,6 +482,18 @@ assert vframe.backframe is None return fullmatch + def unfreeze(self, incomingvarboxes, memo): + local_boxes = [] + for fzbox in self.fz_local_boxes: + local_boxes.append(fzbox.unfreeze(incomingvarboxes, memo)) + if self.fz_backframe is not None: + backframe = self.fz_backframe.unfreeze(incomingvarboxes, memo) + else: + backframe = None + vframe = VirtualFrame(backframe, BaseDispatchQueue()) + vframe.local_boxes = local_boxes + return vframe + class FrozenJITState(object): #fz_frame = ... set by freeze() @@ -368,6 +516,12 @@ fullmatch = False return fullmatch + def unfreeze(self, incomingvarboxes, memo): + frame = self.fz_frame .unfreeze(incomingvarboxes, memo) + exc_type_box = self.fz_exc_type_box .unfreeze(incomingvarboxes, memo) + exc_value_box = self.fz_exc_value_box.unfreeze(incomingvarboxes, memo) + return JITState(None, frame, exc_type_box, exc_value_box) + class VirtualFrame(object): @@ -410,15 +564,17 @@ class JITState(object): returnbox = None next = None # for linked lists + resuming = None # or a ResumingInfo def __init__(self, builder, frame, exc_type_box, exc_value_box, - resumepoint=-1, newgreens=[]): + resumepoint=-1, newgreens=[], promotion_path=None): self.curbuilder = builder self.frame = frame self.exc_type_box = exc_type_box self.exc_value_box = exc_value_box self.resumepoint = resumepoint self.greens = newgreens + self.promotion_path = promotion_path def split(self, newbuilder, newresumepoint, newgreens): memo = rvalue.copy_memo() @@ -427,7 +583,9 @@ self.exc_type_box .copy(memo), self.exc_value_box.copy(memo), newresumepoint, - newgreens) + newgreens, + PromotionPathIndirect(self.promotion_path)) + self.promotion_path = PromotionPathDirect(self.promotion_path) # add the later_jitstate to the chain of pending-for-dispatch_next() dispatch_queue = self.frame.dispatch_queue later_jitstate.next = dispatch_queue.split_chain @@ -456,6 +614,9 @@ enter_graph._annspecialcase_ = 'specialize:arg(1)' # XXX is that too many specializations? ^^^ +class CompilationInterrupted(Exception): + pass + def merge_returning_jitstates(jitstate): return_chain = jitstate.frame.dispatch_queue.return_chain return_cache = {} @@ -463,17 +624,18 @@ while return_chain is not None: jitstate = return_chain return_chain = return_chain.next - res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + res = retrieve_jitstate_for_merge(return_cache, jitstate, (), None) if res is False: # not finished jitstate.next = still_pending still_pending = jitstate - assert still_pending is not None + if still_pending is None: + raise CompilationInterrupted most_general_jitstate = still_pending still_pending = still_pending.next while still_pending is not None: jitstate = still_pending still_pending = still_pending.next - res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + res = retrieve_jitstate_for_merge(return_cache, jitstate, (), None) assert res is True # finished return most_general_jitstate Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py Wed Sep 27 21:21:50 2006 @@ -191,6 +191,14 @@ # the graph is transformed already return self.annotator.bookkeeper.tsgraphsigs[tsgraph] + def get_residual_functype(self, tsgraph): + ha = self.annotator + args_hs, hs_res = self.get_sig_hs(ha.translator.graphs[0]) + RESTYPE = originalconcretetype(hs_res) + ARGS = [originalconcretetype(hs_arg) for hs_arg in args_hs + if not hs_arg.is_green()] + return lltype.FuncType(ARGS, RESTYPE) + def make_new_lloplist(self, block): return HintLowLevelOpList(self) @@ -230,8 +238,11 @@ try: return self.dispatchsubclasses[mergepointfamily] except KeyError: - attrnames = mergepointfamily.getattrnames() - subclass = rtimeshift.build_dispatch_subclass(attrnames) + if mergepointfamily.is_global: + subclass = rtimeshift.BaseDispatchQueue + else: + attrnames = mergepointfamily.getattrnames() + subclass = rtimeshift.build_dispatch_subclass(attrnames) self.dispatchsubclasses[mergepointfamily] = subclass return subclass @@ -357,24 +368,6 @@ [c_opdesc, v_jitstate] + args_v, ts.s_RedBox) - def translate_op_hint(self, hop): - # don't try to generate hint operations, just discard them - hints = hop.args_v[-1].value - if hints.get('forget', False): - T = originalconcretetype(hop.args_s[0]) - v_redbox = hop.inputarg(self.getredrepr(T), arg=0) - assert isinstance(hop.r_result, GreenRepr) - ts = self - c_T = hop.inputconst(lltype.Void, T) - s_T = ts.rtyper.annotator.bookkeeper.immutablevalue(T) - s_res = annmodel.lltype_to_annotation(T) - return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue, - [ts.s_RedBox, s_T], - [v_redbox, c_T], - s_res) - - return hop.inputarg(hop.r_result, arg=0) - def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc pass @@ -738,17 +731,25 @@ args_s, args_v, annmodel.s_None) - def translate_op_merge_point(self, hop): + def translate_op_merge_point(self, hop, global_resumer=None): mpfamily = hop.args_v[0].value attrname = hop.args_v[1].value DispatchQueueSubclass = self.get_dispatch_subclass(mpfamily) - def merge_point(jitstate, *key): - dispatch_queue = jitstate.frame.dispatch_queue - assert isinstance(dispatch_queue, DispatchQueueSubclass) - states_dic = getattr(dispatch_queue, attrname) - return rtimeshift.retrieve_jitstate_for_merge(states_dic, - jitstate, key) + if mpfamily.is_global: + states_dic = {} + def merge_point(jitstate, *key): + return rtimeshift.retrieve_jitstate_for_merge(states_dic, + jitstate, key, + global_resumer) + else: + def merge_point(jitstate, *key): + dispatch_queue = jitstate.frame.dispatch_queue + assert isinstance(dispatch_queue, DispatchQueueSubclass) + states_dic = getattr(dispatch_queue, attrname) + return rtimeshift.retrieve_jitstate_for_merge(states_dic, + jitstate, key, + global_resumer) greens_v = [] greens_s = [] @@ -767,6 +768,37 @@ [v_jitstate ] + greens_v, annmodel.SomeBool()) + def translate_op_global_merge_point(self, hop): + mpfamily = hop.args_v[0].value + attrname = hop.args_v[1].value + N = mpfamily.resumepoint_after_mergepoint[attrname] + tsgraph = mpfamily.tsgraph + ts_fnptr = self.gettscallable(tsgraph) + TS_FUNC = lltype.typeOf(ts_fnptr) + dummy_args = [ARG._defl() for ARG in TS_FUNC.TO.ARGS[1:]] + dummy_args = tuple(dummy_args) + JITSTATE = self.r_JITState.lowleveltype + RESIDUAL_FUNCTYPE = self.get_residual_functype(tsgraph) + residualSigToken = self.RGenOp.sigToken(RESIDUAL_FUNCTYPE) + ll_finish_jitstate = self.ll_finish_jitstate + + args_s = [self.s_JITState] + [annmodel.lltype_to_annotation(ARG) + for ARG in TS_FUNC.TO.ARGS[1:]] + s_res = self.s_JITState + tsfn = annlowlevel.PseudoHighLevelCallable(ts_fnptr, args_s, s_res) + + def call_for_global_resuming(jitstate): + jitstate.resumepoint = N + try: + finaljitstate = tsfn(jitstate, *dummy_args) + except rtimeshift.CompilationInterrupted: + pass + else: + ll_finish_jitstate(finaljitstate, residualSigToken) + + return self.translate_op_merge_point(hop, + global_resumer = call_for_global_resuming) + def translate_op_save_return(self, hop): v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.save_return, @@ -781,11 +813,29 @@ [v_jitstate ], self.s_JITState) hop.llops.setjitstate(v_newjs) + + def translate_op_getresumepoint(self, hop): + v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.getresumepoint, [self.s_JITState], - [v_newjs ], + [v_jitstate ], annmodel.SomeInteger()) + def translate_op_promote(self, hop): + TYPE = originalconcretetype(hop.args_s[0]) + r_arg = self.getredrepr(TYPE) + [v_box] = hop.inputargs(r_arg) + r_result = self.getgreenrepr(TYPE) + ERASED = annmodel.annotation_to_lltype(r_result.erased_annotation()) + desc = rtimeshift.PromotionDesc(ERASED, self) + s_desc = self.rtyper.annotator.bookkeeper.immutablevalue(desc) + c_desc = hop.inputconst(lltype.Void, desc) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_promote, + [self.s_JITState, self.s_RedBox, s_desc], + [v_jitstate , v_box , c_desc], + annmodel.SomeBool()) + # handling of the various kinds of calls def translate_op_oopspec_call(self, hop): Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/rvalue.py Wed Sep 27 21:21:50 2006 @@ -19,6 +19,9 @@ def copy_memo(): return Memo() +def unfreeze_memo(): + return Memo() + class RedBox(object): __slots__ = ['kind', 'genvar'] @@ -135,9 +138,9 @@ return memo[self] except KeyError: if self.is_constant(): - result = FrozenIntConst(self.genvar) + result = FrozenIntConst(self.kind, self.genvar) else: - result = FrozenIntVar() + result = FrozenIntVar(self.kind) memo[self] = result return result @@ -159,9 +162,9 @@ return memo[self] except KeyError: if self.is_constant(): - result = FrozenDoubleConst(self.genvar) + result = FrozenDoubleConst(self.kind, self.genvar) else: - result = FrozenDoubleVar() + result = FrozenDoubleVar(self.kind) memo[self] = result return result @@ -205,14 +208,14 @@ return boxmemo[self] except KeyError: if self.content: - result = FrozenPtrVirtual() + result = FrozenPtrVirtual(self.kind) boxmemo[self] = result result.fz_content = self.content.freeze(memo) else: if self.is_constant(): - result = FrozenPtrConst(self.genvar) + result = FrozenPtrConst(self.kind, self.genvar) else: - result = FrozenPtrVar() + result = FrozenPtrVar(self.kind) boxmemo[self] = result return result @@ -234,11 +237,14 @@ class FrozenValue(object): """An abstract value frozen in a saved state. """ + def __init__(self, kind): + self.kind = kind class FrozenIntConst(FrozenValue): - def __init__(self, gv_const): + def __init__(self, kind, gv_const): + self.kind = kind self.gv_const = gv_const def exactmatch(self, box, outgoingvarboxes, memo): @@ -250,6 +256,10 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + # XXX could return directly the original IntRedBox + return IntRedBox(self.kind, self.gv_const) + class FrozenIntVar(FrozenValue): @@ -265,10 +275,21 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + memo = memo.boxes + if self not in memo: + newbox = IntRedBox(self.kind, None) + incomingvarboxes.append(newbox) + memo[self] = newbox + return newbox + else: + return memo[self] + class FrozenDoubleConst(FrozenValue): - def __init__(self, gv_const): + def __init__(self, kind, gv_const): + self.kind = kind self.gv_const = gv_const def exactmatch(self, box, outgoingvarboxes, memo): @@ -280,6 +301,9 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + return DoubleRedBox(self.kind, self.gv_const) + class FrozenDoubleVar(FrozenValue): @@ -295,10 +319,21 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + memo = memo.boxes + if self not in memo: + newbox = DoubleRedBox(self.kind, None) + incomingvarboxes.append(newbox) + memo[self] = newbox + return newbox + else: + return memo[self] + class FrozenPtrConst(FrozenValue): - def __init__(self, gv_const): + def __init__(self, kind, gv_const): + self.kind = kind self.gv_const = gv_const def exactmatch(self, box, outgoingvarboxes, memo): @@ -310,6 +345,9 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + return PtrRedBox(self.kind, self.gv_const) + class FrozenPtrVar(FrozenValue): @@ -325,6 +363,16 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + memo = memo.boxes + if self not in memo: + newbox = PtrRedBox(self.kind, None) + incomingvarboxes.append(newbox) + memo[self] = newbox + return newbox + else: + return memo[self] + class FrozenPtrVirtual(FrozenValue): @@ -336,3 +384,7 @@ else: return self.fz_content.exactmatch(box.content, outgoingvarboxes, memo) + + def unfreeze(self, incomingvarboxes, memo): + #return self.fz_content.unfreeze(self.kind, incomingvarboxes, memo) + raise NotImplementedError Added: pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- (empty file) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py Wed Sep 27 21:21:50 2006 @@ -0,0 +1,26 @@ +import py +from pypy.rpython.lltypesystem import lltype +from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests +from pypy.rpython.objectmodel import hint + + +class TestPromotion(TimeshiftingTests): + + def test_simple_promotion(self): + def ll_two(k): + return (k+1)*2 + def ll_function(n): + k = hint(n, promote=True) + k = ll_two(k) + return hint(k, variable=True) + ll_function._global_merge_points_ = True + + # easy case: no promotion needed + res = self.timeshift(ll_function, [20], [0]) + assert res == 42 + self.check_insns({}) + + # the real test: with promotion + res = self.timeshift(ll_function, [20], []) + assert res == 42 + self.check_insns(int_add=0, int_mul=0) Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py Wed Sep 27 21:21:50 2006 @@ -99,8 +99,6 @@ fresh_jitstate = hrtyper.ll_fresh_jitstate finish_jitstate = hrtyper.ll_finish_jitstate - args_hs, hs_res = hrtyper.get_sig_hs(ha.translator.graphs[0]) - RESTYPE = originalconcretetype(hs_res) t = rtyper.annotator.translator for graph in ha.translator.graphs: checkgraph(graph) @@ -119,11 +117,10 @@ assert len(graph1.getargs()) == 1 + len(values) graph1varargs = graph1.getargs()[1:] timeshifted_entrypoint_args_s = [] - residual_argtypes = [] argcolors = [] generate_code_args_s = [] - for v, hs_arg, llvalue in zip(graph1varargs, args_hs, values): + for v, llvalue in zip(graph1varargs, values): s_var = annmodel.ll_to_annotation(llvalue) r = hrtyper.bindingrepr(v) residual_v = r.residual_values(llvalue) @@ -133,8 +130,6 @@ else: color = "red" assert residual_v == [llvalue], "XXX for now" - ARGTYPE = originalconcretetype(hs_arg) - residual_argtypes.append(ARGTYPE) timeshifted_entrypoint_args_s.append(hrtyper.s_RedBox) generate_code_args_s.append(annmodel.SomeBool()) argcolors.append(color) @@ -147,7 +142,7 @@ [hrtyper.s_JITState] + timeshifted_entrypoint_args_s, hrtyper.s_JITState) - FUNC = lltype.FuncType(residual_argtypes, RESTYPE) + FUNC = hrtyper.get_residual_functype(ha.translator.graphs[0]) argcolors = unrolling_iterable(argcolors) self.argcolors = argcolors @@ -180,9 +175,13 @@ timeshifted_entrypoint_args += (box,) top_jitstate = fresh_jitstate(builder) - top_jitstate = timeshifted_entrypoint(top_jitstate, + try: + top_jitstate = timeshifted_entrypoint(top_jitstate, *timeshifted_entrypoint_args) - finish_jitstate(top_jitstate, sigtoken) + except rtimeshift.CompilationInterrupted: + pass + else: + finish_jitstate(top_jitstate, sigtoken) gv_generated = rgenop.gencallableconst(sigtoken, "generated", entrypoint) Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py Wed Sep 27 21:21:50 2006 @@ -13,8 +13,11 @@ class MergePointFamily(object): - def __init__(self): + def __init__(self, tsgraph, is_global=False): + self.tsgraph = tsgraph + self.is_global = is_global self.count = 0 + self.resumepoint_after_mergepoint = {} def add(self): result = self.count self.count += 1 @@ -30,27 +33,32 @@ self.hannotator = hannotator self.graph = graph self.graphcolor = self.graph_calling_color(graph) + self.global_merge_points = self.graph_global_mps(self.graph) self.resumepoints = {} - self.mergepointfamily = MergePointFamily() + self.mergepoint_set = {} # set of blocks + self.mergepointfamily = MergePointFamily(graph, + self.global_merge_points) self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily) self.tsgraphs_seen = [] def transform(self): - mergepoints = list(self.enumerate_merge_points()) + self.compute_merge_points() self.insert_save_return() self.insert_splits() - for block in mergepoints: - self.insert_merge(block) self.split_after_calls() - self.insert_dispatcher() + self.handle_hints() + self.insert_merge_points() self.insert_enter_graph() + self.insert_dispatcher() self.insert_leave_graph() - def enumerate_merge_points(self): + def compute_merge_points(self): entrymap = mkentrymap(self.graph) for block, links in entrymap.items(): if len(links) > 1 and block is not self.graph.returnblock: - yield block + self.mergepoint_set[block] = True + if self.global_merge_points: + self.mergepoint_set[self.graph.startblock] = True def graph_calling_color(self, tsgraph): args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph] @@ -61,6 +69,12 @@ else: return 'red' + def graph_global_mps(self, tsgraph): + try: + return tsgraph.func._global_merge_points_ + except AttributeError: + return False + def timeshifted_graph_of(self, graph, args_v): bk = self.hannotator.bookkeeper args_hs = [self.hannotator.binding(v) for v in args_v] @@ -147,6 +161,13 @@ reds.append(v) return reds, greens + def before_start_block(self): + entryblock = self.new_block_before(self.graph.startblock) + entryblock.isstartblock = True + self.graph.startblock.isstartblock = False + self.graph.startblock = entryblock + return entryblock + def before_return_block(self): block = self.graph.returnblock block.operations = [] @@ -239,6 +260,21 @@ def get_resume_point(self, block): return self.get_resume_point_link(block).exitcase + def go_to_if(self, block, target, v_finished_flag): + block.exitswitch = v_finished_flag + [link_f] = block.exits + link_t = Link([self.c_dummy], target) + link_f.exitcase = False + link_t.exitcase = True + block.recloseblock(link_f, link_t) + + def go_to_dispatcher_if(self, block, v_finished_flag): + self.go_to_if(block, self.graph.returnblock, v_finished_flag) + + def insert_merge_points(self): + for block in self.mergepoint_set: + self.insert_merge(block) + def insert_merge(self, block): reds, greens = self.sort_by_color(block.inputargs) nextblock = self.naive_split_block(block, 0) @@ -246,15 +282,15 @@ self.genop(block, 'save_locals', reds) mp = self.mergepointfamily.add() c_mp = inputconst(lltype.Void, mp) - v_finished_flag = self.genop(block, 'merge_point', + if self.global_merge_points: + self.genop(block, 'save_greens', greens) + prefix = 'global_' + else: + prefix = '' + v_finished_flag = self.genop(block, '%smerge_point' % (prefix,), [self.c_mpfamily, c_mp] + greens, resulttype = lltype.Bool) - block.exitswitch = v_finished_flag - [link_f] = block.exits - link_t = Link([self.c_dummy], self.graph.returnblock) - link_f.exitcase = False - link_t.exitcase = True - block.recloseblock(link_f, link_t) + self.go_to_dispatcher_if(block, v_finished_flag) restoreops = [] mapping = {} @@ -269,10 +305,26 @@ SSA_to_SSI({block : True, # reachable from outside nextblock: False}, self.hannotator) + if self.global_merge_points: + N = self.get_resume_point(nextblock) + self.mergepointfamily.resumepoint_after_mergepoint[mp] = N + def insert_dispatcher(self): - if self.resumepoints: + if self.global_merge_points or self.resumepoints: block = self.before_return_block() - v_switchcase = self.genop(block, 'dispatch_next', [], + self.genop(block, 'dispatch_next', []) + if self.global_merge_points: + block = self.before_return_block() + entryblock = self.before_start_block() + v_rp = self.genop(entryblock, 'getresumepoint', [], + resulttype = lltype.Signed) + c_zero = inputconst(lltype.Signed, 0) + v_abnormal_entry = self.genop(entryblock, 'int_ge', + [v_rp, c_zero], + resulttype = lltype.Bool) + self.go_to_if(entryblock, block, v_abnormal_entry) + + v_switchcase = self.genop(block, 'getresumepoint', [], resulttype = lltype.Signed) block.exitswitch = v_switchcase defaultlink = block.exits[0] @@ -297,11 +349,7 @@ self.genop(block, 'save_return', []) def insert_enter_graph(self): - entryblock = self.new_block_before(self.graph.startblock) - entryblock.isstartblock = True - self.graph.startblock.isstartblock = False - self.graph.startblock = entryblock - + entryblock = self.before_start_block() self.genop(entryblock, 'enter_graph', [self.c_mpfamily]) def insert_leave_graph(self): @@ -363,6 +411,11 @@ def make_call(self, block, op, save_locals_vars, color='red'): self.genop(block, 'save_locals', save_locals_vars) targets = dict(self.graphs_from(op)) + for tsgraph in targets.values(): + if self.graph_global_mps(tsgraph): + # make sure jitstate.resumepoint is set to zero + self.genop(block, 'resetresumepoint', []) + break if len(targets) == 1: [tsgraph] = targets.values() c_tsgraph = inputconst(lltype.Void, tsgraph) @@ -475,5 +528,56 @@ link.args = [] link.target = self.get_resume_point_link(nextblock).target - self.insert_merge(nextblock) # to merge some of the possibly many - # return jitstates + self.mergepoint_set[nextblock] = True # to merge some of the possibly + # many return jitstates + + # __________ hints __________ + + def handle_hints(self): + for block in list(self.graph.iterblocks()): + for i in range(len(block.operations)-1, -1, -1): + op = block.operations[i] + if op.opname == 'hint': + hints = op.args[1].value + for key, value in hints.items(): + if value == True: + methname = 'handle_%s_hint' % (key,) + if hasattr(self, methname): + handler = getattr(self, methname) + break + else: + handler = self.handle_default_hint + handler(block, i) + + def handle_default_hint(self, block, i): + # just discard the hint by default + op = block.operations[i] + newop = SpaceOperation('same_as', [op.args[0]], op.result) + block.operations[i] = newop + + def handle_forget_hint(self, block, i): + # a hint for testing only + op = block.operations[i] + assert self.binding(op.result).is_green() + assert not self.binding(op.args[0]).is_green() + newop = SpaceOperation('revealconst', [op.args[0]], op.result) + block.operations[i] = newop + + def handle_promote_hint(self, block, i): + op = block.operations[i] + c_zero = inputconst(lltype.Signed, 0) + newop = SpaceOperation('restore_green', [c_zero], op.result) + block.operations[i] = newop + + link = support.split_block_with_keepalive(block, i, + annotator=self.hannotator) + nextblock = link.target + + reds, greens = self.sort_by_color(link.args) + v_promote = op.args[0] + if v_promote not in reds: + reds.append(v_promote) + self.genop(block, 'save_locals', reds) + v_finished_flag = self.genop(block, 'promote', [v_promote], + resulttype = lltype.Bool) + self.go_to_dispatcher_if(block, v_finished_flag) Modified: pypy/branch/jit-promotion/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/jit-promotion/pypy/rpython/lltypesystem/lloperation.py Wed Sep 27 21:21:50 2006 @@ -402,6 +402,7 @@ 'debug_pdb': LLOp(), 'debug_log_exc': LLOp(), 'debug_assert': LLOp(canfold=True), + 'debug_fatalerror': LLOp(), } # __________ operations on PyObjects __________ From pedronis at codespeak.net Wed Sep 27 22:03:08 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Sep 2006 22:03:08 +0200 (CEST) Subject: [pypy-svn] r32684 - pypy/dist/pypy/rpython Message-ID: <20060927200308.851BA1006F@code0.codespeak.net> Author: pedronis Date: Wed Sep 27 22:03:06 2006 New Revision: 32684 Modified: pypy/dist/pypy/rpython/llinterp.py Log: automatically upon opening show the trace of the last call chain in the llinterp html logging files. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed Sep 27 22:03:06 2006 @@ -903,22 +903,33 @@ HEADER = """
     """
 
-    FOOTER = """
""" + FOOTER = """ + + + """ - ENTER = ('''\n\t%s''' + ENTER = ('''\n\t%s''' '''\n
\t''') LEAVE = '''\n
\t''' @@ -951,17 +962,22 @@ self.count = 0 self.indentation = '' + self.depth = 0 + self.latest_call_chain = [] def stop(self): # end of a dump file if self.file: - print >> self.file, self.FOOTER + print >> self.file, self.FOOTER % (self.latest_call_chain[1:]) self.file.close() self.file = None def enter(self, graph): # enter evaluation of a graph if self.file: + del self.latest_call_chain[self.depth:] + self.depth += 1 + self.latest_call_chain.append(self.count) s = self.htmlquote(str(graph)) i = s.rfind(')') s = s[:i+1] + '' + s[i+1:] + '' @@ -979,6 +995,7 @@ if self.file: self.indentation = self.indentation[:-4] self.file.write(self.LEAVE.replace('\t', self.indentation)) + self.depth -= 1 def dump(self, text, bold=False): if self.file: From arigo at codespeak.net Thu Sep 28 00:35:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 00:35:36 +0200 (CEST) Subject: [pypy-svn] r32685 - in pypy/branch/jit-promotion/pypy: jit/codegen/llgraph jit/timeshifter jit/timeshifter/test rpython Message-ID: <20060927223536.2C83410060@code0.codespeak.net> Author: arigo Date: Thu Sep 28 00:35:30 2006 New Revision: 32685 Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py pypy/branch/jit-promotion/pypy/rpython/annlowlevel.py pypy/branch/jit-promotion/pypy/rpython/llinterp.py Log: (pedronis, arigo) Next intermediate check-in. The first real promotion tests pass! Fix the other tests tomorrow... good night. Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py Thu Sep 28 00:35:30 2006 @@ -41,6 +41,11 @@ block.inputargs.append(v) return to_opaque_object(v) +def getinputarg(blockcontainer, i): + block = from_opaque_object(blockcontainer.obj) + v = block.inputargs[i] + return to_opaque_object(v) + def _inputvars(vars): newvars = [] if not isinstance(vars, list): @@ -218,7 +223,7 @@ block = from_opaque_object(blockcontainer.obj) exitcase = from_opaque_object(exitcase) assert isinstance(exitcase, flowmodel.Constant) - assert isinstance(block.exitswitch, Variable) + assert isinstance(block.exitswitch, flowmodel.Variable) case_link = flowmodel.Link([], None) case_link.exitcase = exitcase.value case_link.llexitcase = exitcase.value @@ -258,10 +263,15 @@ raise TypeError def closelink(link, vars, targetblockcontainer): - link = from_opaque_object(link) - targetblock = from_opaque_object(targetblockcontainer.obj) - vars = _inputvars(vars) - _closelink(link, vars, targetblock) + try: + link = from_opaque_object(link) + targetblock = from_opaque_object(targetblockcontainer.obj) + vars = _inputvars(vars) + _closelink(link, vars, targetblock) + except Exception, e: + import sys; tb = sys.exc_info()[2] + import pdb; pdb.post_mortem(tb) + raise ##def closereturnlink(link, returnvar): ## returnvar = from_opaque_object(returnvar) @@ -355,6 +365,17 @@ graph = buildgraph(blockcontainer, returncontainer, FUNCTYPE) return testgengraph(graph, args, viewbefore, executor) +def show_incremental_progress(someblockcontainer): + from pypy import conftest + if conftest.option.view: + try: + someblock = from_opaque_object(someblockcontainer.obj) + someblock.show() + except Exception, e: + import sys; tb = sys.exc_info()[2] + import pdb; pdb.post_mortem(tb) + raise + # ____________________________________________________________ # RTyping of the above functions @@ -419,6 +440,7 @@ setannotation(initblock, None) setannotation(geninputarg, s_ConstOrVar) +setannotation(getinputarg, s_ConstOrVar) setannotation(genop, s_ConstOrVar) setannotation(gencallableconst, s_ConstOrVar) setannotation(genconst, s_ConstOrVar) @@ -439,3 +461,5 @@ setannotation(constFieldName, s_ConstOrVar, specialize_as_constant=True) setannotation(constTYPE, s_ConstOrVar, specialize_as_constant=True) #setannotation(placeholder, s_ConstOrVar, specialize_as_constant=True) + +setannotation(show_incremental_progress, None) Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py Thu Sep 28 00:35:30 2006 @@ -163,6 +163,9 @@ self.lnk = l_default return flexswitch + def show_incremental_progress(self): + llimpl.show_incremental_progress(self.g) + class RGenOp(AbstractRGenOp): gv_Void = gv_Void @@ -230,6 +233,10 @@ args_gv = builder._newblock(kinds) return builder, args_gv + def stop_replay(self, endblock, kinds): + return [LLVar(llimpl.getinputarg(endblock.b, i)) + for i in range(len(kinds))] + # not RPython, just for debugging. Specific to llgraph. @staticmethod def reveal(gv): Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/rtimeshift.py Thu Sep 28 00:35:30 2006 @@ -241,8 +241,15 @@ def split(jitstate, switchredbox, resumepoint, *greens_gv): exitgvar = switchredbox.getgenvar(jitstate.curbuilder) - later_builder = jitstate.curbuilder.jump_if_false(exitgvar) - jitstate.split(later_builder, resumepoint, list(greens_gv)) + if exitgvar.is_const: + return exitgvar.revealconst(lltype.Bool) + else: + if jitstate.resuming is None: + later_builder = jitstate.curbuilder.jump_if_false(exitgvar) + jitstate.split(later_builder, resumepoint, list(greens_gv)) + return True + else: + return jitstate.resuming.path.pop() def collect_split(jitstate_chain, resumepoint, *greens_gv): greens_gv = list(greens_gv) @@ -323,9 +330,10 @@ self.path = path class PromotionPoint(object): - def __init__(self, flexswitch, promotion_path): + def __init__(self, flexswitch, switchblock, promotion_path): assert promotion_path is not None self.flexswitch = flexswitch + self.switchblock = switchblock self.promotion_path = promotion_path class AbstractPromotionPath(object): @@ -355,6 +363,7 @@ jitstate.resuming = resuminginfo assert jitstate.frame.backframe is None self.global_resumer(jitstate) + builder.show_incremental_progress() class PromotionPathNode(AbstractPromotionPath): def __init__(self, next): @@ -379,7 +388,8 @@ resuminginfo = ResumingInfo(promotion_point, gv_value, path) root.continue_compilation(resuminginfo) except Exception, e: - llop.debug_fatalerror(lltype.Void, "compilation-time error", e) + lloperation.llop.debug_fatalerror(lltype.Void, + "compilation-time error", e) class PromotionDesc: __metatype__ = cachedtype @@ -401,8 +411,9 @@ return True def ll_promote(jitstate, box, promotiondesc): - if box.is_constant(): - save_greens(jitstate, box.genvar) + builder = jitstate.curbuilder + gv_switchvar = box.getgenvar(builder) + if gv_switchvar.is_const: return False else: incoming = [] @@ -411,16 +422,18 @@ switchblock = enter_next_block(jitstate, incoming) if jitstate.resuming is None: - builder = jitstate.curbuilder - flexswitch = builder.flexswitch(box.getgenvar(builder)) + gv_switchvar = box.genvar + flexswitch = builder.flexswitch(gv_switchvar) # default case of the switch: enter_block(jitstate) - pm = PromotionPoint(flexswitch, jitstate.promotion_path) + pm = PromotionPoint(flexswitch, switchblock, + jitstate.promotion_path) ll_pm = cast_instance_to_base_ptr(pm) gv_pm = builder.rgenop.genconst(ll_pm) + gv_switchvar = box.genvar builder.genop_call(promotiondesc.sigtoken, promotiondesc.gv_continue_compilation, - [gv_pm, box.getgenvar(builder)]) + [gv_pm, gv_switchvar]) linkargs = [] for box in incoming: linkargs.append(box.getgenvar(builder)) @@ -431,13 +444,20 @@ resuming = jitstate.resuming assert len(resuming.path) == 0 pm = resuming.promotion_point + + kinds = [box.kind for box in incoming] + vars_gv = jitstate.curbuilder.rgenop.stop_replay(pm.switchblock, + kinds) + for i in range(len(incoming)): + incoming[i].genvar = vars_gv[i] + box.genvar = resuming.gv_value + newbuilder = pm.flexswitch.add_case(resuming.gv_value) jitstate.resuming = None jitstate.promotion_path = pm.promotion_path jitstate.curbuilder = newbuilder enter_block(jitstate) - save_greens(jitstate, resuming.gv_value) return False # ____________________________________________________________ Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/rtyper.py Thu Sep 28 00:35:30 2006 @@ -710,8 +710,9 @@ args_s += [self.s_ConstOrVar] * len(greens_v) args_v = [v_jitstate, v_switch, c_resumepoint] args_v += greens_v - hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v, - annmodel.s_None) + return hop.llops.genmixlevelhelpercall(rtimeshift.split, + args_s, args_v, + annmodel.SomeBool()) def translate_op_collect_split(self, hop): GREENS = [v.concretetype for v in hop.args_v[1:]] Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py Thu Sep 28 00:35:30 2006 @@ -1,6 +1,7 @@ import py from pypy.rpython.lltypesystem import lltype from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests +from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL from pypy.rpython.objectmodel import hint @@ -24,3 +25,19 @@ res = self.timeshift(ll_function, [20], []) assert res == 42 self.check_insns(int_add=0, int_mul=0) + + def test_many_promotions(self): + def ll_two(k): + return k*k + def ll_function(n, total): + while n > 0: + k = hint(n, promote=True) + k = ll_two(k) + total += hint(k, variable=True) + n -= 1 + return total + ll_function._global_merge_points_ = True + + res = self.timeshift(ll_function, [10, 0], [], policy=P_NOVIRTUAL) + assert res == ll_function(10, 0) + self.check_insns(int_add=10, int_mul=0) Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 28 00:35:30 2006 @@ -271,9 +271,10 @@ # now try to run the residual graph generated by the builder residual_graph = ll_generated._obj.graph residual_graph.exceptiontransformed = self.hrtyper.exc_data_ptr + self.ll_generated = ll_generated + self.residual_graph = residual_graph if conftest.option.view: residual_graph.show() - self.insns = summary(residual_graph) if 'check_raises' not in kwds: res = llinterp.eval_graph(residual_graph, residualargs) @@ -313,6 +314,7 @@ return self.timeshift(ll_function, values, opt_consts, *args, **kwds) def check_insns(self, expected=None, **counts): + self.insns = summary(self.residual_graph) if expected is not None: assert self.insns == expected for opname, count in counts.items(): Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py Thu Sep 28 00:35:30 2006 @@ -192,6 +192,7 @@ self.insert_split_handling(block) def insert_split_handling(self, block): + # lots of clever in-line logic commented out v_redswitch = block.exitswitch link_f, link_t = block.exits if link_f.exitcase: @@ -199,35 +200,42 @@ assert link_f.exitcase is False assert link_t.exitcase is True - constant_block = Block([]) - nonconstant_block = Block([]) +## constant_block = Block([]) +## nonconstant_block = Block([]) - v_flag = self.genop(block, 'is_constant', [v_redswitch], - resulttype = lltype.Bool) - self.genswitch(block, v_flag, true = constant_block, - false = nonconstant_block) - - v_greenswitch = self.genop(constant_block, 'revealconst', - [v_redswitch], - resulttype = lltype.Bool) - constant_block.exitswitch = v_greenswitch - constant_block.closeblock(link_f, link_t) +## v_flag = self.genop(block, 'is_constant', [v_redswitch], +## resulttype = lltype.Bool) +## self.genswitch(block, v_flag, true = constant_block, +## false = nonconstant_block) + +## v_greenswitch = self.genop(constant_block, 'revealconst', +## [v_redswitch], +## resulttype = lltype.Bool) +## constant_block.exitswitch = v_greenswitch +## constant_block.closeblock(link_f, link_t) reds, greens = self.sort_by_color(link_f.args, link_f.target.inputargs) - self.genop(nonconstant_block, 'save_locals', reds) + self.genop(block, 'save_locals', reds) resumepoint = self.get_resume_point(link_f.target) c_resumepoint = inputconst(lltype.Signed, resumepoint) - self.genop(nonconstant_block, 'split', - [v_redswitch, c_resumepoint] + greens) + v_flag = self.genop(block, 'split', + [v_redswitch, c_resumepoint] + greens, + resulttype = lltype.Bool) + + block.exitswitch = v_flag + true_block = Block([]) + true_link = Link([], true_block) + true_link.exitcase = True + true_link.llexitcase = True + block.recloseblock(link_f, true_link) reds, greens = self.sort_by_color(link_t.args) - self.genop(nonconstant_block, 'save_locals', reds) - self.genop(nonconstant_block, 'enter_block', []) - nonconstant_block.closeblock(Link(link_t.args, link_t.target)) - - SSA_to_SSI({block : True, # reachable from outside - constant_block : False, - nonconstant_block: False}, self.hannotator) + self.genop(true_block, 'save_locals', reds) + self.genop(true_block, 'enter_block', []) + true_block.closeblock(Link(link_t.args, link_t.target)) + + SSA_to_SSI({block : True, # reachable from outside + true_block: False}, self.hannotator) def get_resume_point_link(self, block): try: @@ -565,8 +573,8 @@ def handle_promote_hint(self, block, i): op = block.operations[i] - c_zero = inputconst(lltype.Signed, 0) - newop = SpaceOperation('restore_green', [c_zero], op.result) + v_promote = op.args[0] + newop = SpaceOperation('revealconst', [v_promote], op.result) block.operations[i] = newop link = support.split_block_with_keepalive(block, i, @@ -574,9 +582,6 @@ nextblock = link.target reds, greens = self.sort_by_color(link.args) - v_promote = op.args[0] - if v_promote not in reds: - reds.append(v_promote) self.genop(block, 'save_locals', reds) v_finished_flag = self.genop(block, 'promote', [v_promote], resulttype = lltype.Bool) Modified: pypy/branch/jit-promotion/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/jit-promotion/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/jit-promotion/pypy/rpython/annlowlevel.py Thu Sep 28 00:35:30 2006 @@ -347,6 +347,7 @@ return annmodel.SomePtr(F) def specialize_call(self, hop): + hop.exception_cannot_occur() return hop.args_r[1].get_unique_llfn() # ____________________________________________________________ @@ -372,6 +373,7 @@ def specialize_call(self, hop): v_arg = hop.inputarg(hop.args_r[1], arg=1) assert isinstance(v_arg.concretetype, lltype.Ptr) + hop.exception_cannot_occur() return hop.genop('cast_pointer', [v_arg], resulttype = hop.r_result.lowleveltype) @@ -391,6 +393,7 @@ def specialize_call(self, hop): v_arg = hop.inputarg(hop.args_r[1], arg=1) assert isinstance(v_arg.concretetype, lltype.Ptr) + hop.exception_cannot_occur() return hop.genop('cast_pointer', [v_arg], resulttype = hop.r_result.lowleveltype) @@ -409,11 +412,7 @@ ## s_Instance, r_Instance = pol.annhelper.s_r_instanceof(s_Class.const) ## return annmodel.SomePtr(r_Instance.lowleveltype) -## def specialize_call(self, hop): -## v_arg = hop.inputarg(hop.args_r[1], arg=1) -## assert isinstance(v_arg.concretetype, lltype.Ptr) -## return hop.genop('cast_pointer', [v_arg], -## resulttype = hop.r_result.lowleveltype) +## ... # ____________________________________________________________ Modified: pypy/branch/jit-promotion/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/jit-promotion/pypy/rpython/llinterp.py (original) +++ pypy/branch/jit-promotion/pypy/rpython/llinterp.py Thu Sep 28 00:35:30 2006 @@ -27,6 +27,10 @@ extra = '' return '' % (type_name(etype), extra) +class LLFatalError(Exception): + def __str__(self): + return ': '.join([str(x) for x in self.args]) + def type_name(etype): if isinstance(lltype.typeOf(etype), lltype.Ptr): return ''.join(etype.name).rstrip('\x00') @@ -442,6 +446,14 @@ # do nothing, this is useful in compiled code pass + def op_debug_fatalerror(self, ll_msg, ll_exc=None): + msg = ''.join(ll_msg.chars) + if ll_exc is None: + raise LLFatalError(msg) + else: + ll_exc_type = lltype.cast_pointer(rclass.OBJECTPTR, ll_exc).typeptr + raise LLFatalError(msg, LLException(ll_exc_type, ll_exc)) + def op_keepalive(self, value): pass @@ -903,22 +915,33 @@ HEADER = """
     """
 
-    FOOTER = """
""" + FOOTER = """ + + + """ - ENTER = ('''\n\t%s''' + ENTER = ('''\n\t%s''' '''\n
\t''') LEAVE = '''\n
\t''' @@ -951,17 +974,22 @@ self.count = 0 self.indentation = '' + self.depth = 0 + self.latest_call_chain = [] def stop(self): # end of a dump file if self.file: - print >> self.file, self.FOOTER + print >> self.file, self.FOOTER % (self.latest_call_chain[1:]) self.file.close() self.file = None def enter(self, graph): # enter evaluation of a graph if self.file: + del self.latest_call_chain[self.depth:] + self.depth += 1 + self.latest_call_chain.append(self.count) s = self.htmlquote(str(graph)) i = s.rfind(')') s = s[:i+1] + '' + s[i+1:] + '' @@ -979,6 +1007,7 @@ if self.file: self.indentation = self.indentation[:-4] self.file.write(self.LEAVE.replace('\t', self.indentation)) + self.depth -= 1 def dump(self, text, bold=False): if self.file: From arigo at codespeak.net Thu Sep 28 09:24:16 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 09:24:16 +0200 (CEST) Subject: [pypy-svn] r32689 - in pypy/branch/jit-promotion/pypy: annotation jit/codegen/llgraph tool Message-ID: <20060928072416.5DAED1006F@code0.codespeak.net> Author: arigo Date: Thu Sep 28 09:24:13 2006 New Revision: 32689 Modified: pypy/branch/jit-promotion/pypy/annotation/annrpython.py pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/jit-promotion/pypy/tool/sourcetools.py Log: Clean-ups. Modified: pypy/branch/jit-promotion/pypy/annotation/annrpython.py ============================================================================== --- pypy/branch/jit-promotion/pypy/annotation/annrpython.py (original) +++ pypy/branch/jit-promotion/pypy/annotation/annrpython.py Thu Sep 28 09:24:13 2006 @@ -722,7 +722,8 @@ try: resultcell = consider_meth(*argcells) except Exception: - raise_nicer_exception(op) + graph = self.bookkeeper.position_key[0] + raise_nicer_exception(op, str(graph)) if resultcell is None: resultcell = annmodel.s_ImpossibleValue # no return value elif resultcell == annmodel.s_ImpossibleValue: Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/llimpl.py Thu Sep 28 09:24:13 2006 @@ -23,16 +23,41 @@ c = from_opaque_object(gv_type) return isinstance(c.value, lltype.Ptr) -def initblock(opaqueptr): - init_opaque_object(opaqueptr, flowmodel.Block([])) - def newblock(): - blockcontainer = lltype.malloc(BLOCKCONTAINERTYPE) - initblock(blockcontainer.obj) - return blockcontainer + block = flowmodel.Block([]) + return to_opaque_object(block) + +def newgraph(gv_FUNCTYPE): + FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value + inputargs = [] + erasedinputargs = [] + for ARG in FUNCTYPE.ARGS: + v = flowmodel.Variable() + v.concretetype = ARG + inputargs.append(v) + v = flowmodel.Variable() + v.concretetype = lltype.erasedType(ARG) + erasedinputargs.append(v) + startblock = flowmodel.Block(inputargs) + return_var = flowmodel.Variable() + return_var.concretetype = FUNCTYPE.RESULT + graph = flowmodel.FunctionGraph("in_progress", startblock, return_var) + v1 = flowmodel.Variable() + v1.concretetype = lltype.erasedType(FUNCTYPE.RESULT) + graph.prereturnblock = flowmodel.Block([v1]) + casting_link(graph.prereturnblock, [v1], graph.returnblock) + substartblock = flowmodel.Block(erasedinputargs) + casting_link(graph.startblock, inputargs, substartblock) + return to_opaque_object(graph) + +def getstartblock(graph): + graph = from_opaque_object(graph) + [link] = graph.startblock.exits + substartblock = link.target + return to_opaque_object(substartblock) -def geninputarg(blockcontainer, gv_CONCRETE_TYPE): - block = from_opaque_object(blockcontainer.obj) +def geninputarg(block, gv_CONCRETE_TYPE): + block = from_opaque_object(block) assert not block.operations, "block already contains operations" assert block.exits == [], "block already closed" CONCRETE_TYPE = from_opaque_object(gv_CONCRETE_TYPE).value @@ -41,8 +66,8 @@ block.inputargs.append(v) return to_opaque_object(v) -def getinputarg(blockcontainer, i): - block = from_opaque_object(blockcontainer.obj) +def getinputarg(block, i): + block = from_opaque_object(block) v = block.inputargs[i] return to_opaque_object(v) @@ -72,12 +97,12 @@ res.append(v) return res -def cast(blockcontainer, gv_TYPE, gv_var): +def cast(block, gv_TYPE, gv_var): TYPE = from_opaque_object(gv_TYPE).value v = from_opaque_object(gv_var) if TYPE != v.concretetype: assert v.concretetype == lltype.erasedType(TYPE) - block = from_opaque_object(blockcontainer.obj) + block = from_opaque_object(block) v2 = flowmodel.Variable() v2.concretetype = TYPE op = flowmodel.SpaceOperation('cast_pointer', [v], v2) @@ -95,12 +120,12 @@ return v2 return v -def genop(blockcontainer, opname, vars_gv, gv_RESULT_TYPE): +def genop(block, opname, vars_gv, gv_RESULT_TYPE): # 'opname' is a constant string # gv_RESULT_TYPE comes from constTYPE if not isinstance(opname, str): opname = LLSupport.from_rstr(opname) - block = from_opaque_object(blockcontainer.obj) + block = from_opaque_object(block) assert block.exits == [], "block already closed" opvars = _inputvars(vars_gv) if gv_RESULT_TYPE is guess: @@ -130,15 +155,15 @@ result = op.fold(*examples) return lltype.typeOf(result) -def gencallableconst(name, targetcontainer, returncontainer, gv_FUNCTYPE): +def gencallableconst(name, graph, gv_FUNCTYPE): # 'name' is just a way to track things if not isinstance(name, str): name = LLSupport.from_rstr(name) - target = from_opaque_object(targetcontainer.obj) - returnblock = from_opaque_object(returncontainer.obj) + graph = from_opaque_object(graph) + graph.name = name FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value fptr = lltype.functionptr(FUNCTYPE, name, - graph=_buildgraph(target, returnblock, FUNCTYPE)) + graph=_buildgraph(graph, FUNCTYPE)) return genconst(fptr) def genconst(llvalue): @@ -187,14 +212,14 @@ c.concretetype = lltype.Void return to_opaque_object(c) -def closeblock1(blockcontainer): - block = from_opaque_object(blockcontainer.obj) +def closeblock1(block): + block = from_opaque_object(block) link = flowmodel.Link([], None) block.closeblock(link) return to_opaque_object(link) -def closeblock2(blockcontainer, exitswitch): - block = from_opaque_object(blockcontainer.obj) +def closeblock2(block, exitswitch): + block = from_opaque_object(block) exitswitch = from_opaque_object(exitswitch) assert isinstance(exitswitch, flowmodel.Variable) block.exitswitch = exitswitch @@ -208,8 +233,8 @@ return pseudotuple(to_opaque_object(false_link), to_opaque_object(true_link)) -def closeblockswitch(blockcontainer, exitswitch): - block = from_opaque_object(blockcontainer.obj) +def closeblockswitch(block, exitswitch): + block = from_opaque_object(block) exitswitch = from_opaque_object(exitswitch) assert isinstance(exitswitch, flowmodel.Variable) block.exitswitch = exitswitch @@ -219,8 +244,8 @@ block.closeblock(default_link) return to_opaque_object(default_link) -def add_case(blockcontainer, exitcase): - block = from_opaque_object(blockcontainer.obj) +def add_case(block, exitcase): + block = from_opaque_object(block) exitcase = from_opaque_object(exitcase) assert isinstance(exitcase, flowmodel.Constant) assert isinstance(block.exitswitch, flowmodel.Variable) @@ -262,10 +287,10 @@ else: raise TypeError -def closelink(link, vars, targetblockcontainer): +def closelink(link, vars, targetblock): try: link = from_opaque_object(link) - targetblock = from_opaque_object(targetblockcontainer.obj) + targetblock = from_opaque_object(targetblock) vars = _inputvars(vars) _closelink(link, vars, targetblock) except Exception, e: @@ -273,86 +298,44 @@ import pdb; pdb.post_mortem(tb) raise -##def closereturnlink(link, returnvar): -## returnvar = from_opaque_object(returnvar) -## link = from_opaque_object(link) -## v = flowmodel.Variable() -## v.concretetype = returnvar.concretetype -## pseudoreturnblock = flowmodel.Block([v]) -## pseudoreturnblock.operations = () -## _closelink(link, [returnvar], pseudoreturnblock) - -##def _patchgraph(graph, RESULT): -## returntype = None -## links = [] -## for link in graph.iterlinks(): -## if link.target.operations == (): -## assert len(link.args) == 1 # for now -## if returntype is None: -## returntype = link.target.inputargs[0].concretetype -## else: -## assert returntype == link.target.inputargs[0].concretetype -## links.append(link) -## if returntype is None: -## returntype = lltype.Void -## graph.returnblock.inputargs[0].concretetype = RESULT -## targetblock = casting_bridge([returntype], [RESULT], graph.returnblock) -## for link in links: -## link.target = targetblock +def closereturnlink(link, returnvar, graph): + returnvar = from_opaque_object(returnvar) + link = from_opaque_object(link) + graph = from_opaque_object(graph) + _closelink(link, [returnvar], graph.prereturnblock) + +def casting_link(source, sourcevars, target): + assert len(sourcevars) == len(target.inputargs) + linkargs = [] + for v, target_v in zip(sourcevars, target.inputargs): + if v.concretetype == target_v.concretetype: + linkargs.append(v) + else: + erasedv = flowmodel.Variable() + erasedv.concretetype = target_v.concretetype + source.operations.append(flowmodel.SpaceOperation('cast_pointer', + [v], + erasedv)) + linkargs.append(erasedv) + source.closeblock(flowmodel.Link(linkargs, target)) + +# ____________________________________________________________ class PseudoRTyper(object): def __init__(self): from pypy.rpython.typesystem import LowLevelTypeSystem self.type_system = LowLevelTypeSystem.instance -def casting_bridge(FROMS, TOS, target): - if FROMS != TOS: - operations = [] - inputargs = [] - linkargs = [] - for FROM, TO in zip(FROMS, TOS): - v = flowmodel.Variable() - v.concretetype = FROM - inputargs.append(v) - if FROM == TO: - linkargs.append(v) - else: - erasedv = flowmodel.Variable() - erasedv.concretetype = TO - operations.append(flowmodel.SpaceOperation('cast_pointer', - [v], - erasedv)) - linkargs.append(erasedv) - bridgeblock = flowmodel.Block(inputargs) - bridgeblock.operations = operations - bridge = flowmodel.Link(linkargs, target) - bridgeblock.closeblock(bridge) - return bridgeblock - else: - return target - -def _buildgraph(block, existingreturnblock, FUNCTYPE): - ARGS = [v.concretetype for v in block.inputargs] - startblock =casting_bridge(FUNCTYPE.ARGS, ARGS, block) - graph = flowmodel.FunctionGraph('generated', startblock) - - returntype = existingreturnblock.inputargs[0].concretetype - RESULT = FUNCTYPE.RESULT - graph.returnblock.inputargs[0].concretetype = RESULT - prereturnblock = casting_bridge([returntype], [RESULT], graph.returnblock) - existingreturnblock.closeblock(flowmodel.Link( - [existingreturnblock.inputargs[0]], - prereturnblock)) +def _buildgraph(graph, FUNCTYPE): flowmodel.checkgraph(graph) eliminate_empty_blocks(graph) join_blocks(graph) graph.rgenop = True return graph -def buildgraph(blockcontainer, returncontainer, FUNCTYPE): - block = from_opaque_object(blockcontainer.obj) - returnblock = from_opaque_object(returncontainer.obj) - return _buildgraph(block, returnblock, FUNCTYPE) +def buildgraph(graph, FUNCTYPE): + graph = from_opaque_object(graph) + return _buildgraph(graph, FUNCTYPE) def testgengraph(gengraph, args, viewbefore=False, executor=LLInterpreter): if viewbefore: @@ -360,43 +343,40 @@ llinterp = executor(PseudoRTyper()) return llinterp.eval_graph(gengraph, args) -def runblock(blockcontainer, returncontainer, FUNCTYPE, args, +def runblock(graph, FUNCTYPE, args, viewbefore=False, executor=LLInterpreter): - graph = buildgraph(blockcontainer, returncontainer, FUNCTYPE) + graph = buildgraph(graph, FUNCTYPE) return testgengraph(graph, args, viewbefore, executor) -def show_incremental_progress(someblockcontainer): +def show_incremental_progress(graph): from pypy import conftest if conftest.option.view: - try: - someblock = from_opaque_object(someblockcontainer.obj) - someblock.show() - except Exception, e: - import sys; tb = sys.exc_info()[2] - import pdb; pdb.post_mortem(tb) - raise + graph = from_opaque_object(graph) + graph.show() # ____________________________________________________________ # RTyping of the above functions -from pypy.rpython.extfunctable import declaretype, declareptrtype, declare +from pypy.rpython.extfunctable import declareptrtype -blocktypeinfo = declaretype(flowmodel.Block, "Block") +blocktypeinfo = declareptrtype(flowmodel.Block, "Block") consttypeinfo = declareptrtype(flowmodel.Constant, "ConstOrVar") vartypeinfo = declareptrtype(flowmodel.Variable, "ConstOrVar") vartypeinfo.set_lltype(consttypeinfo.get_lltype()) # force same lltype linktypeinfo = declareptrtype(flowmodel.Link, "Link") +graphtypeinfo = declareptrtype(flowmodel.FunctionGraph, "FunctionGraph") CONSTORVAR = lltype.Ptr(consttypeinfo.get_lltype()) -BLOCKCONTAINERTYPE = blocktypeinfo.get_lltype() -BLOCK = lltype.Ptr(BLOCKCONTAINERTYPE) +BLOCK = lltype.Ptr(blocktypeinfo.get_lltype()) LINK = lltype.Ptr(linktypeinfo.get_lltype()) +GRAPH = lltype.Ptr(graphtypeinfo.get_lltype()) # support constants and types nullvar = lltype.nullptr(CONSTORVAR.TO) nullblock = lltype.nullptr(BLOCK.TO) nulllink = lltype.nullptr(LINK.TO) +nullgraph = lltype.nullptr(GRAPH.TO) gv_Void = constTYPE(lltype.Void) dummy_placeholder = placeholder(None) @@ -437,8 +417,12 @@ s_ConstOrVar = annmodel.SomePtr(CONSTORVAR)#annmodel.SomeExternalObject(flowmodel.Variable) s_Link = annmodel.SomePtr(LINK)#annmodel.SomeExternalObject(flowmodel.Link) s_LinkPair = annmodel.SomeTuple([s_Link, s_Link]) +s_Block = annmodel.SomePtr(BLOCK) +s_Graph = annmodel.SomePtr(GRAPH) -setannotation(initblock, None) +setannotation(newblock, s_Block) +setannotation(newgraph, s_Graph) +setannotation(getstartblock, s_Block) setannotation(geninputarg, s_ConstOrVar) setannotation(getinputarg, s_ConstOrVar) setannotation(genop, s_ConstOrVar) @@ -453,7 +437,7 @@ setannotation(closeblockswitch, s_Link) setannotation(add_case, s_Link) setannotation(closelink, None) -#setannotation(closereturnlink, None) +setannotation(closereturnlink, None) setannotation(isptrtype, annmodel.SomeBool()) Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/rgenop.py Thu Sep 28 09:24:13 2006 @@ -138,7 +138,9 @@ def finish_and_return(self, sigtoken, gv_returnvar): gv_returnvar = gv_returnvar or gv_dummy_placeholder - self.finish_and_goto([gv_returnvar], LLBlock(self.g, self.g)) + lnk = self.lnk or llimpl.closeblock1(self.b) + self.lnk = llimpl.nulllink + llimpl.closereturnlink(lnk, gv_returnvar.v, self.g) def jump_if_true(self, gv_cond): l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) @@ -172,17 +174,15 @@ def newgraph(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE)): - returnblock = llimpl.newblock() - llimpl.geninputarg(returnblock, gv_RESULT.v) - g = returnblock # for now - builder = LLBuilder(g) - inputargs_gv = builder._newblock(ARGS_gv) - return builder, LLBlock(builder.b, builder.g), inputargs_gv - - def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, - entrypoint): - return LLConst(llimpl.gencallableconst(name, entrypoint.b, - entrypoint.g, + graph = llimpl.newgraph(gv_FUNCTYPE.v) + builder = LLBuilder(graph) + builder.b = llimpl.getstartblock(graph) + inputargs_gv = [LLVar(llimpl.getinputarg(builder.b, i)) + for i in range(len(ARGS_gv))] + return builder, graph, inputargs_gv + + def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, graph): + return LLConst(llimpl.gencallableconst(name, graph, gv_FUNCTYPE.v)) @staticmethod Modified: pypy/branch/jit-promotion/pypy/tool/sourcetools.py ============================================================================== --- pypy/branch/jit-promotion/pypy/tool/sourcetools.py (original) +++ pypy/branch/jit-promotion/pypy/tool/sourcetools.py Thu Sep 28 09:24:13 2006 @@ -109,6 +109,8 @@ src = inspect.getsource(object) except IOError: return None + except IndentationError: + return None if hasattr(name, "__sourceargs__"): return src % name.__sourceargs__ return src From auc at codespeak.net Thu Sep 28 13:01:59 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Thu, 28 Sep 2006 13:01:59 +0200 (CEST) Subject: [pypy-svn] r32690 - in pypy/dist/pypy/objspace/cclp: . constraint constraint/test Message-ID: <20060928110159.C305210070@code0.codespeak.net> Author: auc Date: Thu Sep 28 13:01:55 2006 New Revision: 32690 Added: pypy/dist/pypy/objspace/cclp/constraint/btree.py (contents, props changed) pypy/dist/pypy/objspace/cclp/constraint/test/test_btree.py (contents, props changed) Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py pypy/dist/pypy/objspace/cclp/constraint/distributor.py pypy/dist/pypy/objspace/cclp/scheduler.py Log: transl. fixes (we seem to complete the annotation phase now) Added: pypy/dist/pypy/objspace/cclp/constraint/btree.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/cclp/constraint/btree.py Thu Sep 28 13:01:55 2006 @@ -0,0 +1,75 @@ +from pypy.interpreter import baseobjspace + +class Found(Exception): pass + +class BTree(object): + """binary tree""" + + def __init__(self): + self.leaf = True + + def _populate(self, key, val): + self.leaf = False + self.key = key + self.val = val + self.left = BTree() + self.right = BTree() + + def add(self, key, val): + assert isinstance(key, int) + assert isinstance(val, baseobjspace.W_Root) + if self.leaf: + self._populate(key, val) + else: + if key > self.key: + self.right.add(key, val) + else: + self.left.add(key, val) + + def _in(self, key): + if self.leaf: + return False + if self.key == key: raise Found + self.left._in(key) + self.right._in(key) + + def __contains__(self, key): + if self.leaf: return False + if self.key == key: return True + try: + self._in(key) + self._in(key) + return False + except Found: + return True + + def _infixly(self, output, ret=0): + """depending on the value of ret: + 0 : keys + 1 : values + 2 : both (items) + """ + if self.leaf: return + self.left._infixly(output, ret) + if ret == 0: + output.append(self.key) + elif ret == 1: + output.append(self.val) + else: + output.append((self.key, self.val)) + self.right._infixly(output, ret) + + def keys(self): + out = [] + self._infixly(out, ret=0) + return out + + def values(self): + out = [] + self._infixly(out, ret=1) + return out + + def items(self): + out = [] + self._infixly(out, ret=2) + return out Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/constraint.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py Thu Sep 28 13:01:55 2006 @@ -15,7 +15,7 @@ from pypy.objspace.std.model import StdObjSpaceMultiMethod -#from pypy.objspace.constraint.btree import BTree +from pypy.objspace.cclp.constraint.btree import BTree #from pypy.objspace.constraint.util import sort all_mms = {} @@ -74,7 +74,7 @@ make_filter_mm.register(make_filter__List_String, W_ListObject, W_StringObject) all_mms['make_filter'] = make_filter_mm -class Quadruple(object): +class Quadruple(W_Root): def __init__(self, zero, one, two, three): self.zero = zero self.one = one @@ -101,8 +101,8 @@ return result_cache def _assign_values(self): - variables = [] kwargs = self._space.newdict() + variables = BTree() for variable in self._variables: assert isinstance(variable, W_Variable) domain = variable.w_dom @@ -110,18 +110,18 @@ values = domain.get_values() assert isinstance(values, list) ds = domain.size() + assert isinstance(ds, int) w_name = variable.w_name() lval = len(values) - vstruct = (ds, Quadruple(w_name, values, 0, lval)) - variables.append(vstruct) + variables.add(ds, Quadruple(w_name, values, 0, lval)) # was meant to be: #variables.append((domain.size(), # [w_name, values, 0, len(values)])) first_value = values[0] assert isinstance(first_value, W_Root) kwargs.content[variable.w_name()] = first_value - # sort variables to instanciate those with fewer possible values first - variables.sort() + # get sorted variables to instanciate those with fewer possible values first + variables = variables.values() self._assign_values_state = variables return kwargs @@ -130,13 +130,18 @@ # try to instanciate the next variable variables = self._assign_values_state - for _, curr in variables: + for curr in variables: + assert isinstance(curr, Quadruple) w_name = curr.zero dom_values = curr.one dom_index = curr.two dom_len = curr.three + assert isinstance(w_name, W_StringObject) + assert isinstance(dom_values, list) + assert isinstance(dom_index, int) + assert isinstance(dom_len, int) if dom_index < dom_len: - kwargs.content[w_name] = dom_values[curr.two] + kwargs.content[w_name] = dom_values[dom_index] curr.two = dom_index + 1 break else: @@ -227,25 +232,27 @@ def revise(self): _spc = self._space - #ord_vars = BTree() - variables = [] - for variable in self._variables: - assert isinstance(variable, W_Variable) - dom = variable.w_dom + ord_vars = BTree() + for var in self._variables: + assert isinstance(var, W_Variable) + dom = var.w_dom assert isinstance(dom, W_AbstractDomain) - variables.append((dom.size(), variable)) - - variables.sort() - # variable = ord_vars.values() + sz = dom.size() + ord_vars.add(sz, var) + variables = ord_vars.values() # if a domain has a size of 1, # then the value must be removed from the other domains - for _, var in variables: + for var in variables: + assert isinstance(var, W_Variable) dom = var.w_dom + assert isinstance(dom, W_AbstractDomain) if dom.size() == 1: #print "AllDistinct removes values" - for _, _var in variables: + for _var in variables: + assert isinstance(_var, W_Variable) _dom = _var.w_dom + assert isinstance(_dom, W_AbstractDomain) if not _var._same_as(var): try: _dom.remove_value(dom.get_values()[0]) @@ -256,8 +263,10 @@ # if there are less values than variables, the constraint fails values = {} - for _, var in variables: + for var in variables: + assert isinstance(var, W_Variable) dom = var.w_dom + assert isinstance(dom, W_AbstractDomain) for val in dom.w_get_values().wrappeditems: values[val] = 0 @@ -267,8 +276,10 @@ _spc.wrap("ConsistencyFailure")) # the constraint is entailed if all domains have a size of 1 - for _, var in variables: + for var in variables: + assert isinstance(var, W_Variable) dom = var.w_dom + assert isinstance(dom, W_AbstractDomain) if not dom.size() == 1: return False Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/distributor.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/distributor.py Thu Sep 28 13:01:55 2006 @@ -134,7 +134,8 @@ def _do_distribute(self, domain, choice): values = domain.get_values() - nb_elts = max(1, len(values)*1./self._subdomains()) + subdoms = self._subdomains() + nb_elts = max(subdoms, len(values)) / float(subdoms) start, end = (int(math.floor(choice * nb_elts)), int(math.floor((choice + 1) * nb_elts))) domain.remove_values(values[:start]) Added: pypy/dist/pypy/objspace/cclp/constraint/test/test_btree.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/cclp/constraint/test/test_btree.py Thu Sep 28 13:01:55 2006 @@ -0,0 +1,17 @@ +class TestBTree(object): + + def test_everything_at_once(self): + from pypy.objspace.constraint.btree import BTree + b = BTree() + l = [(-1, 'egg'), (-7, 'spam'), (3, 'bacon'), + (99, 'ham'), (77, 'cheese'), (7, 'tomato'), + (5, 'chicken'), (9, 'noodles')] + for k, v in l: b.add(k, v) + assert 77 in b + assert 66 not in b + assert b.values() == ['spam', 'egg', 'bacon', 'chicken', + 'tomato', 'noodles', 'cheese', 'ham'] + assert b.keys() == [-7, -1, 3, 5, 7, 9, 77, 99] + assert b.items() == [(-7, 'spam'), (-1, 'egg'), (3, 'bacon'), + (5, 'chicken'), (7, 'tomato'), (9, 'noodles'), + (77, 'cheese'), (99, 'ham')] Modified: pypy/dist/pypy/objspace/cclp/scheduler.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/scheduler.py (original) +++ pypy/dist/pypy/objspace/cclp/scheduler.py Thu Sep 28 13:01:55 2006 @@ -44,10 +44,6 @@ # for the reset case self._head._next = self._head._prev = self._head - def _set_head(self, thread): - assert isinstance(thread, ClonableCoroutine) - self._head = thread - def _check_initial_conditions(self): try: assert self._head._next == self._head._prev == self._head From mwh at codespeak.net Thu Sep 28 14:15:12 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 28 Sep 2006 14:15:12 +0200 (CEST) Subject: [pypy-svn] r32691 - pypy/dist/pypy/objspace/flow Message-ID: <20060928121512.A852510070@code0.codespeak.net> Author: mwh Date: Thu Sep 28 14:15:11 2006 New Revision: 32691 Modified: pypy/dist/pypy/objspace/flow/model.py Log: there is not always a default in the multi-valued switch case. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Thu Sep 28 14:15:11 2006 @@ -652,8 +652,9 @@ # a multiple-cases switch (or else the False and True # branches are in the wrong order) assert len(block.exits) >= 1 - assert block.exits[-1].exitcase == "default" cases = [Constant(link.exitcase) for link in block.exits] + if 'default' in cases: + assert 'default' == cases[-1] assert len(dict.fromkeys(cases)) == len(cases) allexitcases = {} From mwh at codespeak.net Thu Sep 28 14:23:48 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 28 Sep 2006 14:23:48 +0200 (CEST) Subject: [pypy-svn] r32692 - in pypy/dist/pypy: module/_socket objspace/cclp/constraint translator/c Message-ID: <20060928122348.3648D10070@code0.codespeak.net> Author: mwh Date: Thu Sep 28 14:23:46 2006 New Revision: 32692 Modified: pypy/dist/pypy/module/_socket/rsocket.py pypy/dist/pypy/objspace/cclp/constraint/constraint.py pypy/dist/pypy/translator/c/primitive.py Log: remove four tab characters in three files. Modified: pypy/dist/pypy/module/_socket/rsocket.py ============================================================================== --- pypy/dist/pypy/module/_socket/rsocket.py (original) +++ pypy/dist/pypy/module/_socket/rsocket.py Thu Sep 28 14:23:46 2006 @@ -398,7 +398,7 @@ that the system will allow before refusing new connections.""" if backlog < 1: backlog = 1 - res = _c.socketlisten(self.fd, backlog) + res = _c.socketlisten(self.fd, backlog) if res < 0: raise self.error_handler() Modified: pypy/dist/pypy/objspace/cclp/constraint/constraint.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/constraint.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/constraint.py Thu Sep 28 14:23:46 2006 @@ -111,7 +111,7 @@ assert isinstance(values, list) ds = domain.size() assert isinstance(ds, int) - w_name = variable.w_name() + w_name = variable.w_name() lval = len(values) variables.add(ds, Quadruple(w_name, values, 0, lval)) # was meant to be: Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Thu Sep 28 14:23:46 2006 @@ -21,11 +21,11 @@ cdecl(db.gettype(value.TYPE), ''), structnode.c_struct_field_name(value.fldname)) elif isinstance(value, ItemOffset): - if value.TYPE != Void: + if value.TYPE != Void: return '(sizeof(%s) * %s)'%( cdecl(db.gettype(value.TYPE), ''), value.repeat) else: - return '0' + return '0' elif isinstance(value, ArrayItemsOffset): if isinstance(value.TYPE, FixedSizeArray): return '0' From ac at codespeak.net Thu Sep 28 15:10:29 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 28 Sep 2006 15:10:29 +0200 (CEST) Subject: [pypy-svn] r32693 - pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test Message-ID: <20060928131029.8C98910070@code0.codespeak.net> Author: ac Date: Thu Sep 28 15:10:27 2006 New Revision: 32693 Added: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py - copied, changed from r32692, pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_llimpl.py Log: (pedronis, arre) Start of converting the rgenop tests to use the external API. From auc at codespeak.net Thu Sep 28 16:36:31 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Thu, 28 Sep 2006 16:36:31 +0200 (CEST) Subject: [pypy-svn] r32694 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060928143631.F216A10070@code0.codespeak.net> Author: auc Date: Thu Sep 28 16:36:28 2006 New Revision: 32694 Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py pypy/dist/pypy/objspace/cclp/scheduler.py pypy/dist/pypy/objspace/cclp/space.py pypy/dist/pypy/objspace/cclp/thunk.py Log: another round of transl. fixes (translating logic objspace with backend opts should trigger the failed assert of "../translator/backendopt/inline.py", triggered line 505, in measure_median_execution_cost) Modified: pypy/dist/pypy/objspace/cclp/constraint/distributor.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/distributor.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/distributor.py Thu Sep 28 16:36:28 2006 @@ -138,7 +138,12 @@ nb_elts = max(subdoms, len(values)) / float(subdoms) start, end = (int(math.floor(choice * nb_elts)), int(math.floor((choice + 1) * nb_elts))) + lv = len(values) + assert start >= 0 + assert start <= lv domain.remove_values(values[:start]) + assert end >= 0 + assert end <= lv domain.remove_values(values[end:]) def make_split_distributor(space, w_fanout): Modified: pypy/dist/pypy/objspace/cclp/scheduler.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/scheduler.py (original) +++ pypy/dist/pypy/objspace/cclp/scheduler.py Thu Sep 28 16:36:28 2006 @@ -51,7 +51,7 @@ assert self._head not in self._blocked_on assert self._head not in self._blocked_byneed assert self._head not in self._asking - except: + except Exception: #XXX give sched_info maybe raise OperationError(self.space.w_RuntimeError, self.space.wrap("scheduler is in an incoherent state")) Modified: pypy/dist/pypy/objspace/cclp/space.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/space.py (original) +++ pypy/dist/pypy/objspace/cclp/space.py Thu Sep 28 16:36:28 2006 @@ -35,7 +35,7 @@ assert isinstance(w_n, W_IntObject) n = space.int_w(w_n) cspace = get_current_cspace(space) - if cspace != None: + if cspace is not None: assert isinstance(cspace, W_CSpace) try: return cspace.choose(w_n.intval) Modified: pypy/dist/pypy/objspace/cclp/thunk.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thunk.py (original) +++ pypy/dist/pypy/objspace/cclp/thunk.py Thu Sep 28 16:36:28 2006 @@ -167,6 +167,10 @@ while dist.distributable(): choice = cspace.choose(dist.fanout()) dist.w_distribute(choice) + except ConsistencyError, e: + w("-- DISTRIBUTOR thunk exited because", str(e)) + interp_bind(cspace._choice, self.space.newint(0)) + else: w("-- DISTRIBUTOR thunk exited because a solution was found") #XXX assert that all propagators are entailed sol = cspace._solution @@ -181,13 +185,6 @@ interp_bind(var, dom.get_values()[0]) assert interp_free(cspace._choice) interp_bind(cspace._choice, self.space.newint(1)) - except ConsistencyError, e: - w("-- DISTRIBUTOR thunk exited because", str(e)) - interp_bind(cspace._choice, self.space.newint(0)) - except: - if not we_are_translated(): - import traceback - traceback.print_exc() finally: interp_bind(cspace._finished, self.space.w_True) coro._dead = True From arigo at codespeak.net Thu Sep 28 17:19:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 17:19:07 +0200 (CEST) Subject: [pypy-svn] r32696 - pypy/extradoc/talk/dls2006 Message-ID: <20060928151907.CA35010036@code0.codespeak.net> Author: arigo Date: Thu Sep 28 17:19:05 2006 New Revision: 32696 Added: pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf Log: Adding the PDF of the DLS paper. Added: pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf ============================================================================== Files (empty file) and pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf Thu Sep 28 17:19:05 2006 differ From ac at codespeak.net Thu Sep 28 17:23:09 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 28 Sep 2006 17:23:09 +0200 (CEST) Subject: [pypy-svn] r32697 - pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test Message-ID: <20060928152309.CB4641006F@code0.codespeak.net> Author: ac Date: Thu Sep 28 17:23:09 2006 New Revision: 32697 Removed: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_llimpl.py Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py Log: (arre, pedronis) refactored the old tests to exercize the external API. these new tests now pass again. Modified: pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py Thu Sep 28 17:23:09 2006 @@ -2,46 +2,49 @@ from pypy.jit.codegen.llgraph.llimpl import testgengraph from pypy.rpython.lltypesystem import lltype from pypy.rpython.llinterp import LLInterpreter -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret as _interpret from pypy.rpython.module.support import from_opaque_object from pypy.objspace.flow import model as flowmodel +from pypy.rpython import annlowlevel + +class GenconstPolicy(annlowlevel.MixLevelAnnotatorPolicy): + + def __init__(self): + pass + +genconst_policy = GenconstPolicy() + +def interpret(fn, args): + return _interpret(fn, args, policy=genconst_policy) F1 = lltype.FuncType([lltype.Signed], lltype.Signed) +f1_token = rgenop.sigToken(F1) +signed_tok = rgenop.kindToken(lltype.Signed) + +def runner(build): + def run(x): + fptr = build() + return fptr(x) + return run + def build_square(): """def square(v0): return v0*v0""" - sig_token = rgenop.sigToken(F1) - builder, graph, (gv0,) = rgenop.newgraph(sig_token) + builder, graph, (gv0,) = rgenop.newgraph(f1_token) gv1 = builder.genop2('int_mul', gv0, gv0) - builder.finish_and_return(sig_token, gv1) - gv_square = rgenop.gencallableconst(sig_token, "square", graph) - return gv_square + builder.finish_and_return(f1_token, gv1) + gv_square = rgenop.gencallableconst(f1_token, "square", graph) + square_ptr = gv_square.revealconst(lltype.Ptr(F1)) + return square_ptr + def test_square(): - gv_square = build_square() - square_ptr = gv_square.revealconst(lltype.Ptr(F1)) + square_ptr = build_square() res = testgengraph(square_ptr._obj.graph, [17]) assert res == 289 - -def test_rtype_newblock(): - def emptyblock(): - return newblock() - blockcontainer = interpret(emptyblock, []) - block = from_opaque_object(blockcontainer.obj) - assert isinstance(block, flowmodel.Block) - -def test_rtype_geninputarg(): - def onearg(): - block = newblock() - v0 = geninputarg(block, constTYPE(Signed)) - return v0 - opaquev = interpret(onearg, []) - v = from_opaque_object(opaquev) - assert isinstance(v, flowmodel.Variable) -def test_rtype_build_square(): - blockcontainer = interpret(build_square, []) - res = runblock(blockcontainer, F1, [17]) +def test_interpret_square(): + res = interpret(runner(build_square), [17]) assert res == 289 def build_if(): @@ -52,27 +55,30 @@ else: return v0 """ - block = newblock() - v0 = geninputarg(block, constTYPE(Signed)) - const0 = genconst(0) - v1 = genop(block, 'int_lt', [v0, const0], constTYPE(Bool)) - false_link, true_link = closeblock2(block, v1) - closereturnlink(true_link, const0) - closereturnlink(false_link, v0) - return block + builder, graph, (gv0,) = rgenop.newgraph(f1_token) + + const0 = rgenop.genconst(0) + gv1 = builder.genop2('int_lt', gv0, const0) + false_builder = builder.jump_if_false(gv1) + builder.finish_and_return(f1_token, const0) + false_builder.finish_and_return(f1_token, gv0) + gv_if = rgenop.gencallableconst(f1_token, "if", graph) + if_ptr = gv_if.revealconst(lltype.Ptr(F1)) + return if_ptr def test_if(): - block = build_if() - res = runblock(block, F1, [-1]) + if_ptr = build_if() + if_graph = if_ptr._obj.graph + res = testgengraph(if_graph, [-1]) assert res == 0 - res = runblock(block, F1, [42]) + res = testgengraph(if_graph, [42]) assert res == 42 -def test_rtype_build_if(): - blockcontainer = interpret(build_if, []) - res = runblock(blockcontainer, F1, [-1]) +def test_interpret_if(): + run_if = runner(build_if) + res = interpret(run_if, [-1]) assert res == 0 - res = runblock(blockcontainer, F1, [42]) + res = interpret(run_if, [42]) assert res == 42 def build_loop(): @@ -80,76 +86,62 @@ def f(v0): i = 1 result = 1 - while i <= v0: + while True: result *= i i += 1 + if i > v0: break return result """ - block = newblock() - v0 = geninputarg(block, constTYPE(Signed)) - const1 = genconst(1) - link = closeblock1(block) - loopblock = newblock() - result0 = geninputarg(loopblock, constTYPE(Signed)) - i0 = geninputarg(loopblock, constTYPE(Signed)) - v1 = geninputarg(loopblock, constTYPE(Signed)) - closelink(link, [const1, const1, v0], loopblock) - const1 = genconst(1) - result1 = genop(loopblock, 'int_mul', [result0, i0], constTYPE(Signed)) - i1 = genop(loopblock, 'int_add', [i0, const1], constTYPE(Signed)) - v2 = genop(loopblock, 'int_le', [i1, v1], constTYPE(Bool)) - false_link, true_link = closeblock2(loopblock, v2) - closereturnlink(false_link, result1) - closelink(true_link, [result1, i1, v1], loopblock) - return block + builder, graph, (gv0,) = rgenop.newgraph(f1_token) + const1 = rgenop.genconst(1) + + args_gv = [const1, const1, gv0] + loopblock = builder.enter_next_block([signed_tok, signed_tok, signed_tok], + args_gv) + gv_result0, gv_i0, gv1 = args_gv + gv_result1 = builder.genop2('int_mul', gv_result0, gv_i0) + gv_i1 = builder.genop2('int_add', gv_i0, const1) + gv2 = builder.genop2('int_le', gv_i1, gv1) + loop_builder = builder.jump_if_true(gv2) + builder.finish_and_return(f1_token, gv_result1) + loop_builder.finish_and_goto([gv_result1, gv_i1, gv1], loopblock) + + gv_loop = rgenop.gencallableconst(f1_token, "loop", graph) + loop_ptr = gv_loop.revealconst(lltype.Ptr(F1)) + return loop_ptr def test_loop(): - block = build_loop() - res = runblock(block, F1, [0]) + loop_ptr = build_loop() + loop_graph = loop_ptr._obj.graph + res = testgengraph(loop_graph, [0]) assert res == 1 - res = runblock(block, F1, [1]) + res = testgengraph(loop_graph, [1]) assert res == 1 - res = runblock(block, F1, [7]) + res = testgengraph(loop_graph, [7]) assert res == 5040 -def test_rtype_build_loop(): - blockcontainer = interpret(build_loop, []) - res = runblock(blockcontainer, F1, [0]) +def test_interpret_loop(): + run_loop = runner(build_loop) + res = interpret(run_loop, [0]) assert res == 1 - res = runblock(blockcontainer, F1, [1]) + res = interpret(run_loop, [1]) assert res == 1 - res = runblock(blockcontainer, F1, [7]) + res = interpret(run_loop, [7]) assert res == 5040 -def test_rtype_void_constant_construction(): - def fieldname_foo(): - return constFieldName("foo") - res = interpret(fieldname_foo, []) - c = from_opaque_object(res) - assert isinstance(c, flowmodel.Constant) - assert c.concretetype == lltype.Void - assert c.value == "foo" - - def type_Signed(): - return constTYPE(lltype.Signed) - res = interpret(type_Signed, []) - c = from_opaque_object(res) - assert isinstance(c, flowmodel.Constant) - assert c.concretetype == lltype.Void - assert c.value == lltype.Signed -def test_rtype_revealcosnt(): +def test_interpret_revealcosnt(): def hide_and_reveal(v): - gv = genconst(v) - return revealconst(lltype.Signed, gv) + gv = rgenop.genconst(v) + return gv.revealconst(lltype.Signed) res = interpret(hide_and_reveal, [42]) assert res == 42 S = lltype.GcStruct('s', ('x', lltype.Signed)) S_PTR = lltype.Ptr(S) def hide_and_reveal_p(p): - gv = genconst(p) - return revealconst(S_PTR, gv) - s = malloc(S) + gv = rgenop.genconst(p) + return gv.revealconst(S_PTR) + s = lltype.malloc(S) res = interpret(hide_and_reveal_p, [s]) assert res == s From arigo at codespeak.net Thu Sep 28 17:42:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 17:42:23 +0200 (CEST) Subject: [pypy-svn] r32698 - pypy/dist/pypy/doc Message-ID: <20060928154223.60BFC10060@code0.codespeak.net> Author: arigo Date: Thu Sep 28 17:42:22 2006 New Revision: 32698 Modified: pypy/dist/pypy/doc/news.txt Log: Duesseldorf sprint on the News page. Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Thu Sep 28 17:42:22 2006 @@ -15,6 +15,20 @@ .. _`iCalendar format`: webcal://pypycal.sabi.net///calendars/PyPy.ics .. _eventhistory: eventhistory.html + +Duesseldorf sprint #2, 30th October - 5th November +================================================================== + +The next PyPy sprint will be held in Duesseldorf in Germany, where we +already met in June. This is a "non-core-people" friendly sprint; we +will work on any topic of interest, be it from areas we are currently +focusing on (JIT, optimizations, py.test, build tools...) or from areas +that other people would like to consider (new back-ends, distribution, +security...). Read the `full announcement`_ for more details. + +.. _`full announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006b/announce.html + + Summer of PyPy: Calls for proposals open now! ================================================================== From antocuni at codespeak.net Thu Sep 28 17:43:25 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 Sep 2006 17:43:25 +0200 (CEST) Subject: [pypy-svn] r32699 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20060928154325.A22B810063@code0.codespeak.net> Author: antocuni Date: Thu Sep 28 17:43:24 2006 New Revision: 32699 Modified: pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/test/test_cast.py Log: Added support for cast_uint_to_float. Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Thu Sep 28 17:43:24 2006 @@ -216,6 +216,7 @@ 'cast_int_to_float': 'conv.r8', 'cast_int_to_longlong': 'conv.i8', 'cast_uint_to_int': DoNothing, + 'cast_uint_to_float': [PushAllArgs, 'conv.u8', 'conv.r8'], 'cast_float_to_int': 'conv.i4', 'cast_float_to_uint': 'conv.i4', 'truncate_longlong_to_int': 'conv.i4', Modified: pypy/dist/pypy/translator/cli/test/test_cast.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_cast.py (original) +++ pypy/dist/pypy/translator/cli/test/test_cast.py Thu Sep 28 17:43:24 2006 @@ -44,3 +44,6 @@ def test_float_to_int(): check(to_int, [float], (42.5,)) + +def test_uint_to_float(): + check(to_float, [r_uint], (sys.maxint+1,)) From cfbolz at codespeak.net Thu Sep 28 17:56:17 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 17:56:17 +0200 (CEST) Subject: [pypy-svn] r32700 - pypy/branch/config-in-more-places/pypy/translator/goal Message-ID: <20060928155617.5AB4110070@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 17:56:15 2006 New Revision: 32700 Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py pypy/branch/config-in-more-places/pypy/translator/goal/translate.py Log: various typos. also print the config. Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Thu Sep 28 17:56:15 2006 @@ -108,12 +108,13 @@ config = Config(pypy_optiondescription) opt_parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", add_help_option=False) - to_optparse(config, parser=parser) + to_optparse(config, parser=opt_parser) - translate.log_options(tgt_options, "target PyPy options in effect") - opt_parser().parse_args(args) + tgt_options, _ = opt_parser.parse_args(args) + translate.log_options(tgt_options, "target PyPy options in effect") + translate.log_config(config, "PyPy config object") # expose the following variables to ease debugging global space, entry_point Modified: pypy/branch/config-in-more-places/pypy/translator/goal/translate.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/translator/goal/translate.py (original) +++ pypy/branch/config-in-more-places/pypy/translator/goal/translate.py Thu Sep 28 17:56:15 2006 @@ -267,6 +267,10 @@ optvalue = getattr(options, name) log('%25s: %s' %(name, optvalue)) +def log_config(config, header="config used"): + log('%s:' % header) + log(str(config)) + def main(): targetspec_dic, options, args = parse_options_and_load_target() From arigo at codespeak.net Thu Sep 28 18:06:31 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 18:06:31 +0200 (CEST) Subject: [pypy-svn] r32701 - pypy/dist/pypy/doc Message-ID: <20060928160631.D7F3C10074@code0.codespeak.net> Author: arigo Date: Thu Sep 28 18:06:30 2006 New Revision: 32701 Modified: pypy/dist/pypy/doc/news.txt Log: DLS announcement and link to paper (currently only in news.txt). Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Thu Sep 28 18:06:30 2006 @@ -16,6 +16,24 @@ .. _eventhistory: eventhistory.html +Dynamic Languages Symposium (OOPSLA, 23rd October) +================================================================== + +We will present a paper at the `Dynamic Languages Symposium`_ describing +`PyPy's approach to virtual machine construction`_. The DLS is a +one-day forum within OOPSLA'06 (Portland, Oregon, USA). The paper is a +motivated overview of the annotation/rtyping translation tool-chain, +with experimental results. + +As usual, terminology with PyPy is delicate :-) Indeed, the title is +both correct and misleading - it does not describe "the" PyPy virtual +machine, since we have never hand-written one. This paper focuses on +how we are generating such VMs, not what they do. + +.. _`Dynamic Languages Symposium`: http://www.oopsla.org/2006/submission/tracks/dynamic_languages_symposium.html +.. _`PyPy's approach to virtual machine construction`: http://codespeak.net/svn/pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf + + Duesseldorf sprint #2, 30th October - 5th November ================================================================== From cfbolz at codespeak.net Thu Sep 28 18:09:56 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 18:09:56 +0200 (CEST) Subject: [pypy-svn] r32702 - pypy/branch/config-in-more-places/pypy/translator/goal Message-ID: <20060928160956.6ED7D10074@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 18:09:54 2006 New Revision: 32702 Removed: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypymain.py Log: this was very rarely used, it creates pypy as an extension. a relict from dark ages. From antocuni at codespeak.net Thu Sep 28 18:26:56 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 Sep 2006 18:26:56 +0200 (CEST) Subject: [pypy-svn] r32705 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20060928162656.0F57A10063@code0.codespeak.net> Author: antocuni Date: Thu Sep 28 18:26:55 2006 New Revision: 32705 Modified: pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/test/test_op.py Log: Added support for uint_neg Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Thu Sep 28 18:26:55 2006 @@ -117,7 +117,7 @@ 'int_mod_ovf_zer': _check_zer('rem'), 'uint_is_true': [PushAllArgs, 'ldc.i4.0', 'cgt.un'], - 'uint_neg': None, # What's the meaning? + 'uint_neg': 'neg', 'uint_abs': _abs('unsigned int32'), # TODO: ? 'uint_invert': 'not', Modified: pypy/dist/pypy/translator/cli/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_op.py (original) +++ pypy/dist/pypy/translator/cli/test/test_op.py Thu Sep 28 18:26:55 2006 @@ -57,6 +57,11 @@ return x >> y assert self.interpret(fn, [r_longlong(32), 1]) == 16 + def test_uint_neg(self): + def fn(x): + return -x + check(fn, [r_uint], [r_uint(42)]) + def test_op(): yield check, op_any_ge, [int, int], (42, 42) yield check, op_any_ge, [int, int], (13, 42) From arigo at codespeak.net Thu Sep 28 18:55:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 18:55:37 +0200 (CEST) Subject: [pypy-svn] r32706 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20060928165537.765FD10063@code0.codespeak.net> Author: arigo Date: Thu Sep 28 18:55:35 2006 New Revision: 32706 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: More attempts to sort out the neg-overflow-detection mess. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Thu Sep 28 18:55:35 2006 @@ -2,7 +2,7 @@ from pypy.objspace.std.objspace import * from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.noneobject import W_NoneObject -from pypy.rpython.rarithmetic import LONG_BIT, intmask, r_uint +from pypy.rpython.rarithmetic import LONG_BIT, intmask, r_uint, ovfcheck import math @@ -640,24 +640,39 @@ return digits digits_for_most_neg_long._annspecialcase_ = "specialize:argtype(0)" -def args_from_long(l): - if l > 0: - return digits_from_nonneg_long(l), 1 - elif l == 0: - return [0], 0 +def args_from_rarith_int(x): + if x >= 0: + if x == 0: + return [0], 0 + else: + return digits_from_nonneg_long(x), 1 else: - l = -l - if l >= 0: + try: + y = ovfcheck(-x) + except OverflowError: + y = -1 + # be conservative and check again if the result is >= 0, even + # if no OverflowError was raised (e.g. broken CPython/GCC4.2) + if y >= 0: # normal case - return digits_from_nonneg_long(l), -1 + return digits_from_nonneg_long(y), -1 else: # the most negative integer! hacks needed... - # Note that this case is only reachable when translated - return digits_for_most_neg_long(l), -1 -args_from_long._annspecialcase_ = "specialize:argtype(0)" -# ^^^ specialized by the precise type of 'l', which is typically a r_xxx + return digits_for_most_neg_long(x), -1 +args_from_rarith_int._annspecialcase_ = "specialize:argtype(0)" +# ^^^ specialized by the precise type of 'x', which is typically a r_xxx # instance from rpython.rarithmetic +def args_from_long(x): + "NOT_RPYTHON" + if x >= 0: + if x == 0: + return [0], 0 + else: + return digits_from_nonneg_long(x), 1 + else: + return digits_from_nonneg_long(-long(x)), -1 + def _x_add(a, b): """ Add the absolute values of two long integers. """ size_a = len(a.digits) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Sep 28 18:55:35 2006 @@ -301,8 +301,8 @@ #print 'wrapping', x, '->', w_result return w_result if isinstance(x, base_int): - from pypy.objspace.std.longobject import args_from_long - return W_LongObject(*args_from_long(x)) + from pypy.objspace.std.longobject import args_from_rarith_int + return W_LongObject(*args_from_rarith_int(x)) # _____ below here is where the annotator should not get _____ Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_longobject.py Thu Sep 28 18:55:35 2006 @@ -4,7 +4,7 @@ from pypy.objspace.std import longobject as lobj from pypy.objspace.std.objspace import FailedToImplement from pypy.interpreter.error import OperationError -from pypy.rpython.rarithmetic import r_uint # will go away +from pypy.rpython.rarithmetic import r_uint def gen_signs(l): @@ -32,6 +32,34 @@ assert lobj.args_from_long(-sys.maxint-1) == ( lobj.digits_for_most_neg_long(-sys.maxint-1), -1) + def test_args_from_int(self): + BASE = 1 << lobj.SHIFT + assert lobj.args_from_rarith_int(0) == ([0], 0) + assert lobj.args_from_rarith_int(17) == ([17], 1) + assert lobj.args_from_rarith_int(BASE-1) == ([BASE-1], 1) + assert lobj.args_from_rarith_int(BASE) == ([0, 1], 1) + assert lobj.args_from_rarith_int(BASE**2) == ([0, 0, 1], 1) + assert lobj.args_from_rarith_int(-17) == ([17], -1) + assert lobj.args_from_rarith_int(-(BASE-1)) == ([BASE-1], -1) + assert lobj.args_from_rarith_int(-BASE) == ([0, 1], -1) + assert lobj.args_from_rarith_int(-(BASE**2)) == ([0, 0, 1], -1) + assert lobj.args_from_rarith_int(-sys.maxint-1) == ( + lobj.digits_for_most_neg_long(-sys.maxint-1), -1) + + def test_args_from_uint(self): + BASE = 1 << lobj.SHIFT + assert lobj.args_from_rarith_int(r_uint(0)) == ([0], 0) + assert lobj.args_from_rarith_int(r_uint(17)) == ([17], 1) + assert lobj.args_from_rarith_int(r_uint(BASE-1)) == ([BASE-1], 1) + assert lobj.args_from_rarith_int(r_uint(BASE)) == ([0, 1], 1) + assert lobj.args_from_rarith_int(r_uint(BASE**2)) == ([0, 0, 1], 1) + assert lobj.args_from_rarith_int(r_uint(sys.maxint)) == ( + lobj.args_from_long(sys.maxint)) + assert lobj.args_from_rarith_int(r_uint(sys.maxint+1)) == ( + lobj.args_from_long(sys.maxint+1)) + assert lobj.args_from_rarith_int(r_uint(2*sys.maxint+1)) == ( + lobj.args_from_long(2*sys.maxint+1)) + def test_add(self): x = 123456789123456789000000L y = 123858582373821923936744221L From mwh at codespeak.net Thu Sep 28 19:06:29 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 28 Sep 2006 19:06:29 +0200 (CEST) Subject: [pypy-svn] r32707 - in pypy/dist/pypy: annotation rpython rpython/l3interp rpython/lltypesystem rpython/memory/test translator/c translator/llvm Message-ID: <20060928170629.18B861006F@code0.codespeak.net> Author: mwh Date: Thu Sep 28 19:06:25 2006 New Revision: 32707 Removed: pypy/dist/pypy/rpython/l3interp/ Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/llvm/database.py Log: remove the l3interp. paris was a long time ago.... Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Thu Sep 28 19:06:25 2006 @@ -597,12 +597,6 @@ BUILTIN_ANALYZERS[llmemory.offsetof] = offsetof -from pypy.rpython.l3interp import l3interp -def l3malloc(size): - return SomeAddress() - -BUILTIN_ANALYZERS[l3interp.malloc] = l3malloc - #_________________________________ # external functions Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Sep 28 19:06:25 2006 @@ -669,9 +669,6 @@ def op_yield_current_frame_to_caller(self): raise NotImplementedError("yield_current_frame_to_caller") - def op_call_boehm_gc_alloc(self): - raise NotImplementedError("call_boehm_gc_alloc") - # operations on pyobjects! for opname in lloperation.opimpls.keys(): Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Thu Sep 28 19:06:25 2006 @@ -319,10 +319,6 @@ 'direct_ptradd': LLOp(canfold=True), 'cast_opaque_ptr': LLOp(canfold=True), - # _________ XXX l3interp hacks ___________ - - 'call_boehm_gc_alloc': LLOp(canraise=(MemoryError,)), - # __________ address operations __________ 'raw_malloc': LLOp(canraise=(MemoryError,)), Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Thu Sep 28 19:06:25 2006 @@ -516,9 +516,13 @@ class PyForwardReference(ForwardReference): _gckind = 'cpy' +class FuncForwardReference(ForwardReference): + _gckind = 'prebuilt' + FORWARDREF_BY_FLAVOR = {'raw': ForwardReference, 'gc': GcForwardReference, - 'cpy': PyForwardReference} + 'cpy': PyForwardReference, + 'prebuilt': FuncForwardReference} class Primitive(LowLevelType): @@ -594,7 +598,7 @@ def _needsgc(self): # XXX deprecated interface - return self.TO._gckind != 'raw' + return self.TO._gckind not in ('raw', 'prebuilt') def __str__(self): return '* %s' % (self.TO, ) Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Thu Sep 28 19:06:25 2006 @@ -658,8 +658,8 @@ class TestSemiSpaceGC(TestMarkSweepGC): - def setup_class(cls): - py.test.skip("in-progress") + #def setup_class(cls): + # py.test.skip("in-progress") class gcpolicy(gc.StacklessFrameworkGcPolicy): class transformerclass(gctransform.FrameworkGCTransformer): Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Thu Sep 28 19:06:25 2006 @@ -584,18 +584,6 @@ BUILTIN_TYPER[llmemory.offsetof] = rtype_offsetof -# XXX this next little bit is a monstrous hack. the Real Thing awaits -# some kind of proper GC integration -from pypy.rpython.l3interp import l3interp -#from pypy.rpython.raddress import offset_repr - -def rtype_l3malloc(hop): - v_list = hop.inputargs(lltype.Signed) - return hop.genop("call_boehm_gc_alloc", v_list, - resulttype=llmemory.Address) - -BUILTIN_TYPER[l3interp.malloc] = rtype_l3malloc - # _________________________________________________________________ # non-gc objects Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Thu Sep 28 19:06:25 2006 @@ -36,6 +36,7 @@ self.containerstats = {} self.externalfuncs = {} self.helper2ptr = {} + self.raisingop2direct = True # late_initializations is for when the value you want to # assign to a constant object is something C doesn't think is Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Thu Sep 28 19:06:25 2006 @@ -46,6 +46,10 @@ if db.stacklesstransformer: db.stacklesstransformer.transform_graph(graph) # apply the exception transformation + if self.db.raisingop2direct: + from pypy.translator.backendopt.raisingop2direct_call import raisingop2direct_call + raisingop2direct_call(db.translator, [graph]) + if self.db.exctransformer: self.db.exctransformer.create_exception_handling(self.graph) # apply the gc transformation Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Thu Sep 28 19:06:25 2006 @@ -142,6 +142,8 @@ # actually generating the source. if db is None: db = self.build_database() + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(self.translator, raisingop2direct_call_all=True) for node in db.containerlist: if isinstance(node, FuncNode): for funcgen in node.funcgens: Modified: pypy/dist/pypy/translator/llvm/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm/database.py (original) +++ pypy/dist/pypy/translator/llvm/database.py Thu Sep 28 19:06:25 2006 @@ -560,7 +560,12 @@ elif isinstance(value, llmemory.CompositeOffset): from_, indices, to = self.get_offset(value.offsets[0], indices) for item in value.offsets[1:]: - _, indices, to = self.get_offset(item, indices) + if not isinstance(item, llmemory.GCHeaderOffset): + _, indices, to = self.get_offset(item, indices) + + elif isinstance(value, llmemory.GCHeaderOffset): + from_ = lltype.Ptr(value.gcheaderbuilder.HDR) + to = "BBB" # better not use this! else: raise Exception("unsupported offset") From cfbolz at codespeak.net Thu Sep 28 19:36:15 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 19:36:15 +0200 (CEST) Subject: [pypy-svn] r32708 - in pypy/branch/config-in-more-places/pypy: bin tool Message-ID: <20060928173615.BEABA1006F@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 19:36:13 2006 New Revision: 32708 Modified: pypy/branch/config-in-more-places/pypy/bin/py.py pypy/branch/config-in-more-places/pypy/tool/option.py Log: move make_objspace to tool so it can be used from somewhere else. Modified: pypy/branch/config-in-more-places/pypy/bin/py.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/bin/py.py (original) +++ pypy/branch/config-in-more-places/pypy/bin/py.py Thu Sep 28 19:36:13 2006 @@ -12,7 +12,7 @@ pass from pypy.tool import option -from optparse import make_option +from py.compat.optparse import make_option from pypy.interpreter import main, interactive, error import os, sys import time @@ -67,14 +67,6 @@ return options -def make_objspace(conf): - mod = __import__('pypy.objspace.%s' % conf.objspace.name, - None, None, ['Space']) - Space = mod.Space - #conf.objspace.logbytecodes = True - space = Space(conf) - return space - def main_(argv=None): starttime = time.time() args = option.process_options(get_main_options(), Options, argv[1:]) @@ -84,7 +76,7 @@ # create the object space config = option.make_config(Options) - space = make_objspace(config) + space = option.make_objspace(config) space._starttime = starttime #assert 'pypy.tool.udir' not in sys.modules, ( Modified: pypy/branch/config-in-more-places/pypy/tool/option.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/tool/option.py (original) +++ pypy/branch/config-in-more-places/pypy/tool/option.py Thu Sep 28 19:36:13 2006 @@ -2,7 +2,7 @@ # XXX needs clean-up and reorganization. import os -import optparse +from py.compat import optparse make_option = optparse.make_option class Options: @@ -22,6 +22,7 @@ from pypy.tool import tb_server tb_server.start() + def get_standard_options(): options = [] @@ -121,3 +122,11 @@ setattr(subconf, names[-1], value) return conf +def make_objspace(conf): + mod = __import__('pypy.objspace.%s' % conf.objspace.name, + None, None, ['Space']) + Space = mod.Space + #conf.objspace.logbytecodes = True + space = Space(conf) + return space + From arigo at codespeak.net Thu Sep 28 19:38:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 19:38:32 +0200 (CEST) Subject: [pypy-svn] r32709 - in pypy/branch/jit-promotion/pypy/jit: codegen/i386 timeshifter timeshifter/test Message-ID: <20060928173832.16F831006F@code0.codespeak.net> Author: arigo Date: Thu Sep 28 19:38:29 2006 New Revision: 32709 Modified: pypy/branch/jit-promotion/pypy/jit/codegen/i386/ri386genop.py pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py Log: Typo and a new test in-progress. Now is the time to merge the branch... Modified: pypy/branch/jit-promotion/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/branch/jit-promotion/pypy/jit/codegen/i386/ri386genop.py Thu Sep 28 19:38:29 2006 @@ -436,8 +436,6 @@ return self.returnvar(eax) op_uint_is_true = op_int_is_true - op_uint_neg = op_int_neg - op_uint_abs = identity op_uint_invert = op_int_invert op_uint_add = op_int_add op_uint_sub = op_int_sub Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py Thu Sep 28 19:38:29 2006 @@ -41,3 +41,17 @@ res = self.timeshift(ll_function, [10, 0], [], policy=P_NOVIRTUAL) assert res == ll_function(10, 0) self.check_insns(int_add=10, int_mul=0) + +## def test_method_call(self): +## class Base(object): +## pass +## class Int(Base): +## def __init__(self, n): +## self.n = n +## def double(self): +## return Int(self.n * 2) +## class Str(Base): +## def __init__(self, s): +## self.s = s +## def double(self): +## return Str(self.s + self.s) Modified: pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-promotion/pypy/jit/timeshifter/transform.py Thu Sep 28 19:38:29 2006 @@ -566,8 +566,8 @@ def handle_forget_hint(self, block, i): # a hint for testing only op = block.operations[i] - assert self.binding(op.result).is_green() - assert not self.binding(op.args[0]).is_green() + assert self.hannotator.binding(op.result).is_green() + assert not self.hannotator.binding(op.args[0]).is_green() newop = SpaceOperation('revealconst', [op.args[0]], op.result) block.operations[i] = newop From cfbolz at codespeak.net Thu Sep 28 19:43:20 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 19:43:20 +0200 (CEST) Subject: [pypy-svn] r32710 - pypy/branch/config-in-more-places/pypy/translator/goal Message-ID: <20060928174320.D2FDB1006F@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 19:43:19 2006 New Revision: 32710 Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Log: enable targetpypystandalone to be used with different object spaces. maybe we can get rid of quite some targets that way. Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Thu Sep 28 19:43:19 2006 @@ -10,14 +10,12 @@ multimethod.Installer = multimethod.InstallerVersion2 from pypy.objspace.std.objspace import StdObjSpace -# XXX from pypy.annotation.model import * -# since we are execfile()'ed this would pull some -# weird objects into the globals, which we would try to pickle. from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy from pypy.config.pypyoption import pypy_optiondescription from pypy.config.config import Config, to_optparse +from pypy.tool.option import make_objspace try: @@ -126,14 +124,15 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - config.objspace.nofaking = True config.objspace.compiler = "ast" config.translating = True - space = StdObjSpace(config) + space = make_objspace(config) + + # disable translation of the whole of classobjinterp.py + StdObjSpace.setup_old_style_classes = lambda self: None + # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From arigo at codespeak.net Thu Sep 28 19:44:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 19:44:57 +0200 (CEST) Subject: [pypy-svn] r32711 - in pypy/dist/pypy: rpython rpython/lltypesystem translator/c/src translator/cli translator/llvm Message-ID: <20060928174457.ECFBE1006F@code0.codespeak.net> Author: arigo Date: Thu Sep 28 19:44:54 2006 New Revision: 32711 Removed: pypy/dist/pypy/translator/c/src/mkuint.py Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/translator/c/src/int.h pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/llvm/opwriter.py Log: (pedronis, arigo) - removed uint_abs, uint_neg, ullong_abs, ullong_neg - genc was not supporting all of the llong/ullong operations at all! Fixed, maybe Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Thu Sep 28 19:44:54 2006 @@ -179,8 +179,6 @@ 'int_lshift_ovf_val': LLOp(canraise=(OverflowError, ValueError,)), 'uint_is_true': LLOp(canfold=True), - 'uint_neg': LLOp(canfold=True), - 'uint_abs': LLOp(canfold=True), 'uint_invert': LLOp(canfold=True), 'uint_add': LLOp(canfold=True), @@ -250,8 +248,6 @@ 'llong_xor': LLOp(canfold=True), 'ullong_is_true': LLOp(canfold=True), - 'ullong_neg': LLOp(canfold=True), - 'ullong_abs': LLOp(canfold=True), 'ullong_invert': LLOp(canfold=True), 'ullong_add': LLOp(canfold=True), Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Thu Sep 28 19:44:54 2006 @@ -246,11 +246,10 @@ def rtype_abs(self, hop): self = self.as_int + vlist = hop.inputargs(self) if hop.s_result.unsigned: - vlist = hop.inputargs(self) return vlist[0] else: - vlist = hop.inputargs(self) return hop.genop(self.opprefix + 'abs', vlist, resulttype=self) def rtype_abs_ovf(self, hop): @@ -271,7 +270,12 @@ def rtype_neg(self, hop): self = self.as_int vlist = hop.inputargs(self) - return hop.genop(self.opprefix + 'neg', vlist, resulttype=self) + if hop.s_result.unsigned: + zero = self.lowleveltype._defl() + vlist.insert(0, hop.inputconst(self.lowleveltype, zero)) + return hop.genop(self.opprefix + 'sub', vlist, resulttype=self) + else: + return hop.genop(self.opprefix + 'neg', vlist, resulttype=self) def rtype_neg_ovf(self, hop): self = self.as_int Modified: pypy/dist/pypy/translator/c/src/int.h ============================================================================== --- pypy/dist/pypy/translator/c/src/int.h (original) +++ pypy/dist/pypy/translator/c/src/int.h Thu Sep 28 19:44:54 2006 @@ -8,8 +8,6 @@ #define OP_INT_INVERT(x,r) r = ~((x)) -#define OP_INT_POS(x,r) r = x - #define OP_INT_NEG(x,r) r = -(x) #define OP_INT_NEG_OVF(x,r) \ @@ -18,7 +16,6 @@ else FAIL_OVF("integer negate") #define OP_INT_ABS(x,r) r = (x) >= 0 ? x : -(x) -#define OP_UINT_ABS(x,r) r = (x) #define OP_INT_ABS_OVF(x,r) \ OP_INT_ABS(x,r); \ @@ -34,9 +31,6 @@ #define OP_INT_LT(x,y,r) r = ((x) < (y)) #define OP_INT_GE(x,y,r) r = ((x) >= (y)) -#define OP_INT_CMP(x,y,r) \ - r = (((x) > (y)) - ((x) < (y))) - /* addition, subtraction */ #define OP_INT_ADD(x,y,r) r = (x) + (y) @@ -78,9 +72,13 @@ >= 0 and < LONG_BITS. */ #define OP_INT_RSHIFT(x,y,r) r = Py_ARITHMETIC_RIGHT_SHIFT(long, x, y) #define OP_UINT_RSHIFT(x,y,r) r = (x) >> (y) +#define OP_LLONG_RSHIFT(x,y,r) r = Py_ARITHMETIC_RIGHT_SHIFT(PY_LONG_LONG,x,y) +#define OP_ULLONG_RSHIFT(x,y,r) r = (x) >> (y) #define OP_INT_LSHIFT(x,y,r) r = (x) << (y) #define OP_UINT_LSHIFT(x,y,r) r = (x) << (y) +#define OP_LLONG_LSHIFT(x,y,r) r = (x) << (y) +#define OP_ULLONG_LSHIFT(x,y,r) r = (x) << (y) #define OP_INT_LSHIFT_OVF(x,y,r) \ OP_INT_LSHIFT(x,y,r); \ @@ -92,20 +90,43 @@ #define OP_INT_RSHIFT_VAL(x,y,r) \ if ((y) >= 0) { OP_INT_RSHIFT(x,y,r); } \ else FAIL_VAL("negative shift count") +#define OP_LLONG_RSHIFT_VAL(x,y,r) \ + if ((y) >= 0) { OP_LLONG_RSHIFT(x,y,r); } \ + else FAIL_VAL("negative shift count") #define OP_INT_LSHIFT_VAL(x,y,r) \ if ((y) >= 0) { OP_INT_LSHIFT(x,y,r); } \ else FAIL_VAL("negative shift count") +#define OP_LLONG_LSHIFT_VAL(x,y,r) \ + if ((y) >= 0) { OP_LLONG_LSHIFT(x,y,r); } \ + else FAIL_VAL("negative shift count") #define OP_INT_LSHIFT_OVF_VAL(x,y,r) \ if ((y) >= 0) { OP_INT_LSHIFT_OVF(x,y,r); } \ else FAIL_VAL("negative shift count") +/* pff */ +#define OP_UINT_LSHIFT_VAL(x,y,r) \ + if ((y) >= 0) { OP_UINT_LSHIFT(x,y,r); } \ + else FAIL_VAL("negative shift count") +#define OP_ULLONG_LSHIFT_VAL(x,y,r) \ + if ((y) >= 0) { OP_ULLONG_LSHIFT(x,y,r); } \ + else FAIL_VAL("negative shift count") + +#define OP_UINT_RSHIFT_VAL(x,y,r) \ + if ((y) >= 0) { OP_UINT_RSHIFT(x,y,r); } \ + else FAIL_VAL("negative shift count") +#define OP_ULLONG_RSHIFT_VAL(x,y,r) \ + if ((y) >= 0) { OP_ULLONG_RSHIFT(x,y,r); } \ + else FAIL_VAL("negative shift count") + /* floor division */ #define OP_INT_FLOORDIV(x,y,r) r = op_divmod_adj(x, y, NULL) #define OP_UINT_FLOORDIV(x,y,r) r = (x) / (y) +#define OP_LLONG_FLOORDIV(x,y,r) r = op_llong_divmod_adj(x, y, NULL) +#define OP_ULLONG_FLOORDIV(x,y,r) r = (x) / (y) #define OP_INT_FLOORDIV_OVF(x,y,r) \ if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ @@ -118,6 +139,12 @@ #define OP_UINT_FLOORDIV_ZER(x,y,r) \ if ((y)) { OP_UINT_FLOORDIV(x,y,r); } \ else FAIL_ZER("unsigned integer division") +#define OP_LLONG_FLOORDIV_ZER(x,y,r) \ + if ((y)) { OP_LLONG_FLOORDIV(x,y,r); } \ + else FAIL_ZER("integer division") +#define OP_ULLONG_FLOORDIV_ZER(x,y,r) \ + if ((y)) { OP_ULLONG_FLOORDIV(x,y,r); } \ + else FAIL_ZER("unsigned integer division") #define OP_INT_FLOORDIV_OVF_ZER(x,y,r) \ if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r); } \ @@ -127,6 +154,8 @@ #define OP_INT_MOD(x,y,r) op_divmod_adj(x, y, &r) #define OP_UINT_MOD(x,y,r) r = (x) % (y) +#define OP_LLONG_MOD(x,y,r) op_llong_divmod_adj(x, y, &r) +#define OP_ULLONG_MOD(x,y,r) r = (x) % (y) #define OP_INT_MOD_OVF(x,y,r) \ if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ @@ -139,6 +168,12 @@ #define OP_UINT_MOD_ZER(x,y,r) \ if ((y)) { OP_UINT_MOD(x,y,r); } \ else FAIL_ZER("unsigned integer modulo") +#define OP_LLONG_MOD_ZER(x,y,r) \ + if ((y)) { OP_LLONG_MOD(x,y,r); } \ + else FAIL_ZER("integer modulo") +#define OP_ULLONG_MOD_ZER(x,y,r) \ + if ((y)) { OP_ULLONG_MOD(x,y,r); } \ + else FAIL_ZER("integer modulo") #define OP_INT_MOD_OVF_ZER(x,y,r) \ if ((y)) { OP_INT_MOD_OVF(x,y,r); } \ @@ -225,6 +260,8 @@ /* prototypes */ long op_divmod_adj(long x, long y, long *p_rem); +PY_LONG_LONG op_llong_divmod_adj(PY_LONG_LONG x, PY_LONG_LONG y, + PY_LONG_LONG *p_rem); /* implementations */ @@ -249,63 +286,72 @@ return xdivy; } -#endif /* PYPY_NOT_MAIN_FILE */ +PY_LONG_LONG op_llong_divmod_adj(PY_LONG_LONG x, PY_LONG_LONG y, + PY_LONG_LONG *p_rem) +{ + PY_LONG_LONG xdivy = x / y; + PY_LONG_LONG xmody = x - xdivy * y; + /* If the signs of x and y differ, and the remainder is non-0, + * C89 doesn't define whether xdivy is now the floor or the + * ceiling of the infinitely precise quotient. We want the floor, + * and we have it iff the remainder's sign matches y's. + */ + if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) { + xmody += y; + --xdivy; + assert(xmody && ((y ^ xmody) >= 0)); + } + if (p_rem) + *p_rem = xmody; + return xdivy; +} -/* no editing below this point */ -/* following lines are generated by mkuint.py */ +#endif /* PYPY_NOT_MAIN_FILE */ #define OP_UINT_IS_TRUE OP_INT_IS_TRUE #define OP_UINT_INVERT OP_INT_INVERT -#define OP_UINT_POS OP_INT_POS -#define OP_UINT_NEG OP_INT_NEG -/* skipping OP_UINT_ABS */ +#define OP_UINT_ADD OP_INT_ADD +#define OP_UINT_SUB OP_INT_SUB +#define OP_UINT_MUL OP_INT_MUL +#define OP_UINT_LT OP_INT_LT +#define OP_UINT_LE OP_INT_LE #define OP_UINT_EQ OP_INT_EQ #define OP_UINT_NE OP_INT_NE -#define OP_UINT_LE OP_INT_LE #define OP_UINT_GT OP_INT_GT -#define OP_UINT_LT OP_INT_LT #define OP_UINT_GE OP_INT_GE -#define OP_UINT_CMP OP_INT_CMP -#define OP_UINT_ADD OP_INT_ADD -#define OP_UINT_SUB OP_INT_SUB -#define OP_UINT_MUL OP_INT_MUL -/* skipping OP_UINT_RSHIFT */ -/* skipping OP_UINT_LSHIFT */ -/* skipping OP_UINT_FLOORDIV */ -/* skipping OP_UINT_FLOORDIV_ZER */ -/* skipping OP_UINT_MOD */ -/* skipping OP_UINT_MOD_ZER */ #define OP_UINT_AND OP_INT_AND #define OP_UINT_OR OP_INT_OR #define OP_UINT_XOR OP_INT_XOR -#define OP_ULLONG_MUL OP_INT_MUL -#define OP_ULLONG_GT OP_INT_GT - #define OP_LLONG_IS_TRUE OP_INT_IS_TRUE -#define OP_LLONG_INVERT OP_INT_INVERT - -#define OP_LLONG_POS OP_INT_POS -#define OP_LLONG_NEG OP_INT_NEG +#define OP_LLONG_NEG OP_INT_NEG +#define OP_LLONG_ABS OP_INT_ABS +#define OP_LLONG_INVERT OP_INT_INVERT #define OP_LLONG_ADD OP_INT_ADD #define OP_LLONG_SUB OP_INT_SUB #define OP_LLONG_MUL OP_INT_MUL -#define OP_LLONG_FLOORDIV OP_INT_FLOORDIV - -#define OP_LLONG_EQ OP_INT_EQ -#define OP_LLONG_NE OP_INT_NE #define OP_LLONG_LT OP_INT_LT #define OP_LLONG_LE OP_INT_LE +#define OP_LLONG_EQ OP_INT_EQ +#define OP_LLONG_NE OP_INT_NE #define OP_LLONG_GT OP_INT_GT #define OP_LLONG_GE OP_INT_GE - -#define OP_LLONG_CMP OP_INT_CMP - #define OP_LLONG_AND OP_INT_AND #define OP_LLONG_OR OP_INT_OR #define OP_LLONG_XOR OP_INT_XOR -#define OP_LLONG_ABS OP_INT_ABS -#define OP_LLONG_RSHIFT OP_INT_RSHIFT -#define OP_LLONG_LSHIFT OP_INT_LSHIFT +#define OP_ULLONG_IS_TRUE OP_LLONG_IS_TRUE +#define OP_ULLONG_INVERT OP_LLONG_INVERT +#define OP_ULLONG_ADD OP_LLONG_ADD +#define OP_ULLONG_SUB OP_LLONG_SUB +#define OP_ULLONG_MUL OP_LLONG_MUL +#define OP_ULLONG_LT OP_LLONG_LT +#define OP_ULLONG_LE OP_LLONG_LE +#define OP_ULLONG_EQ OP_LLONG_EQ +#define OP_ULLONG_NE OP_LLONG_NE +#define OP_ULLONG_GT OP_LLONG_GT +#define OP_ULLONG_GE OP_LLONG_GE +#define OP_ULLONG_AND OP_LLONG_AND +#define OP_ULLONG_OR OP_LLONG_OR +#define OP_ULLONG_XOR OP_LLONG_XOR Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Thu Sep 28 19:44:54 2006 @@ -117,8 +117,6 @@ 'int_mod_ovf_zer': _check_zer('rem'), 'uint_is_true': [PushAllArgs, 'ldc.i4.0', 'cgt.un'], - 'uint_neg': 'neg', - 'uint_abs': _abs('unsigned int32'), # TODO: ? 'uint_invert': 'not', 'uint_add': 'add', @@ -183,8 +181,6 @@ 'llong_xor': 'xor', 'ullong_is_true': [PushAllArgs, 'ldc.i8 0', 'cgt.un'], - 'ullong_neg': None, - 'ullong_abs': _abs('unsigned int64'), 'ullong_invert': 'not', 'ullong_add': 'add', Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Thu Sep 28 19:44:54 2006 @@ -193,10 +193,6 @@ def int_neg(self, opr): self._generic_neg(opr, "0") - # this is really generated, don't know why - # XXX rxe: Surely that cant be right? - uint_neg = int_neg - llong_neg = int_neg def float_neg(self, opr): From cfbolz at codespeak.net Thu Sep 28 20:01:27 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 20:01:27 +0200 (CEST) Subject: [pypy-svn] r32712 - pypy/branch/config-in-more-places/pypy/tool Message-ID: <20060928180127.33D001006F@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 20:01:25 2006 New Revision: 32712 Modified: pypy/branch/config-in-more-places/pypy/tool/option.py Log: small cleanups Modified: pypy/branch/config-in-more-places/pypy/tool/option.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/tool/option.py (original) +++ pypy/branch/config-in-more-places/pypy/tool/option.py Thu Sep 28 20:01:25 2006 @@ -6,7 +6,6 @@ make_option = optparse.make_option class Options: - showwarning = 0 objspace = "std" oldstyle = 0 uselibfile = 0 @@ -46,9 +45,6 @@ '--nofaking', action="store_true", dest="nofaking", help="avoid faking of modules or objects")) options.append(make_option( - '-w', action="store_true", dest="showwarning", - help="enable warnings (disabled by default)")) - options.append(make_option( '-H', action="callback", callback=run_tb_server, help="use web browser for traceback info")) @@ -61,11 +57,6 @@ '--parser', action="store",type="string", dest="parser", default=None, help="select the parser module to use", metavar="[pypy|cpython]")) -## for this to work the option module need to be loaded before the grammar! -## options.append(make_option( -## '--version', action="store",type="string", dest="version", -## help="select the Python version to emulate", -## metavar="[native|2.3|2.4]")) return options From cfbolz at codespeak.net Thu Sep 28 20:05:42 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 20:05:42 +0200 (CEST) Subject: [pypy-svn] r32713 - pypy/branch/config-in-more-places/pypy/interpreter Message-ID: <20060928180542.604881006F@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 20:05:41 2006 New Revision: 32713 Modified: pypy/branch/config-in-more-places/pypy/interpreter/interactive.py Log: remove some code that was last edited in revision 2689 and can therefore probably be considered outdated. Modified: pypy/branch/config-in-more-places/pypy/interpreter/interactive.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/interpreter/interactive.py (original) +++ pypy/branch/config-in-more-places/pypy/interpreter/interactive.py Thu Sep 28 20:05:41 2006 @@ -225,16 +225,3 @@ class IncompleteInput(Exception): pass -if __name__ == '__main__': - try: - import readline - except ImportError: - pass - - from pypy.tool import option - from pypy.tool import testit - args = option.process_options(option.get_standard_options(), - option.Options) - objspace = option.objspace() - con = PyPyConsole(objspace) - con.interact() From cfbolz at codespeak.net Thu Sep 28 20:08:06 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Sep 2006 20:08:06 +0200 (CEST) Subject: [pypy-svn] r32714 - pypy/branch/config-in-more-places/pypy/bin Message-ID: <20060928180806.2D1191006F@code0.codespeak.net> Author: cfbolz Date: Thu Sep 28 20:08:05 2006 New Revision: 32714 Modified: pypy/branch/config-in-more-places/pypy/bin/py.py Log: remove some commented out code Modified: pypy/branch/config-in-more-places/pypy/bin/py.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/bin/py.py (original) +++ pypy/branch/config-in-more-places/pypy/bin/py.py Thu Sep 28 20:08:05 2006 @@ -139,66 +139,6 @@ return exit_status -##def main_(argv=None): -## starttime = time.time() -## from pypy.tool import tb_server -## args = option.process_options(get_main_options(), Options, argv[1:]) -## space = None -## exit_status = 1 # until proven otherwise -## # XXX should review what CPython's policy is for -## # the exit status code -## try: -## space = option.objspace() -## space._starttime = starttime -## assert 'pypy.tool.udir' not in sys.modules, ( -## "running py.py should not import pypy.tool.udir, which is\n" -## "only for testing or translating purposes.") -## go_interactive = Options.interactive -## if Options.verbose: -## error.RECORD_INTERPLEVEL_TRACEBACK = True -## banner = '' -## space.setitem(space.sys.w_dict,space.wrap('executable'),space.wrap(argv[0])) -## if Options.command: -## args = ['-c'] + Options.command[1:] -## for arg in args: -## space.call_method(space.sys.get('argv'), 'append', space.wrap(arg)) -## try: -## if Options.command: -## main.run_string(Options.command[0], '', space) -## elif args: -## main.run_file(args[0], space) -## else: -## space.call_method(space.sys.get('argv'), 'append', space.wrap('')) -## go_interactive = 1 -## banner = None -## exit_status = 0 -## except error.OperationError, operationerr: -## if Options.verbose: -## operationerr.print_detailed_traceback(space) -## else: -## operationerr.print_application_traceback(space) -## if go_interactive: -## con = interactive.PyPyConsole(space, verbose=Options.verbose, completer=Options.completer) -## if banner == '': -## banner = '%s / %s'%(con.__class__.__name__, -## repr(space)) -## con.interact(banner) -## except: -## exc_type, value, tb = sys.exc_info() -## sys.last_type = exc_type -## sys.last_value = value -## sys.last_traceback = tb -## if issubclass(exc_type, SystemExit): -## pass # don't print tracebacks for SystemExit -## elif isinstance(value, error.OperationError): -## value.print_detailed_traceback(space=space) -## else: -## sys.excepthook(exc_type, value, tb) -## tb_server.wait_until_interrupt() -## exit_status = 1 - -## tb_server.stop() -## return exit_status if __name__ == '__main__': try: From arigo at codespeak.net Thu Sep 28 20:10:24 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 20:10:24 +0200 (CEST) Subject: [pypy-svn] r32715 - in pypy/dist/pypy: annotation jit/codegen jit/codegen/i386 jit/codegen/llgraph jit/codegen/llgraph/test jit/hintannotator jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem tool Message-ID: <20060928181024.7243910070@code0.codespeak.net> Author: arigo Date: Thu Sep 28 20:10:20 2006 New Revision: 32715 Added: pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py - copied unchanged from r32711, pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py pypy/dist/pypy/jit/timeshifter/test/test_promotion.py - copied unchanged from r32711, pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py Removed: pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/jit/codegen/i386/ri386genop.py pypy/dist/pypy/jit/codegen/llgraph/llimpl.py pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/model.py pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/timeshifter/rcontainer.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/rvalue.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/jit/timeshifter/transform.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/tool/sourcetools.py Log: (pedronis, arre, arigo) Merge the jit-promotion branch: svn merge http://codespeak.net/svn/pypy/dist at 32682 http://codespeak.net/svn/pypy/branch/jit-promotion It adds "promotion": with x = hint(x, promote=True) we can force a red variable to become green. This is implemented by pausing the compilation and resuming it only when we get a run-time value arriving. The "pause" contains run-time code that is a "flexible switch": a switch where new cases can be added dynamically. The default case is the one that calls back the compiler. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Thu Sep 28 20:10:20 2006 @@ -722,7 +722,8 @@ try: resultcell = consider_meth(*argcells) except Exception: - raise_nicer_exception(op) + graph = self.bookkeeper.position_key[0] + raise_nicer_exception(op, str(graph)) if resultcell is None: resultcell = annmodel.s_ImpossibleValue # no return value elif resultcell == annmodel.s_ImpossibleValue: Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Thu Sep 28 20:10:20 2006 @@ -436,8 +436,6 @@ return self.returnvar(eax) op_uint_is_true = op_int_is_true - op_uint_neg = op_int_neg - op_uint_abs = identity op_uint_invert = op_int_invert op_uint_add = op_int_add op_uint_sub = op_int_sub Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Thu Sep 28 20:10:20 2006 @@ -23,16 +23,41 @@ c = from_opaque_object(gv_type) return isinstance(c.value, lltype.Ptr) -def initblock(opaqueptr): - init_opaque_object(opaqueptr, flowmodel.Block([])) - def newblock(): - blockcontainer = lltype.malloc(BLOCKCONTAINERTYPE) - initblock(blockcontainer.obj) - return blockcontainer + block = flowmodel.Block([]) + return to_opaque_object(block) + +def newgraph(gv_FUNCTYPE): + FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value + inputargs = [] + erasedinputargs = [] + for ARG in FUNCTYPE.ARGS: + v = flowmodel.Variable() + v.concretetype = ARG + inputargs.append(v) + v = flowmodel.Variable() + v.concretetype = lltype.erasedType(ARG) + erasedinputargs.append(v) + startblock = flowmodel.Block(inputargs) + return_var = flowmodel.Variable() + return_var.concretetype = FUNCTYPE.RESULT + graph = flowmodel.FunctionGraph("in_progress", startblock, return_var) + v1 = flowmodel.Variable() + v1.concretetype = lltype.erasedType(FUNCTYPE.RESULT) + graph.prereturnblock = flowmodel.Block([v1]) + casting_link(graph.prereturnblock, [v1], graph.returnblock) + substartblock = flowmodel.Block(erasedinputargs) + casting_link(graph.startblock, inputargs, substartblock) + return to_opaque_object(graph) + +def getstartblock(graph): + graph = from_opaque_object(graph) + [link] = graph.startblock.exits + substartblock = link.target + return to_opaque_object(substartblock) -def geninputarg(blockcontainer, gv_CONCRETE_TYPE): - block = from_opaque_object(blockcontainer.obj) +def geninputarg(block, gv_CONCRETE_TYPE): + block = from_opaque_object(block) assert not block.operations, "block already contains operations" assert block.exits == [], "block already closed" CONCRETE_TYPE = from_opaque_object(gv_CONCRETE_TYPE).value @@ -41,6 +66,11 @@ block.inputargs.append(v) return to_opaque_object(v) +def getinputarg(block, i): + block = from_opaque_object(block) + v = block.inputargs[i] + return to_opaque_object(v) + def _inputvars(vars): newvars = [] if not isinstance(vars, list): @@ -67,12 +97,12 @@ res.append(v) return res -def cast(blockcontainer, gv_TYPE, gv_var): +def cast(block, gv_TYPE, gv_var): TYPE = from_opaque_object(gv_TYPE).value v = from_opaque_object(gv_var) if TYPE != v.concretetype: assert v.concretetype == lltype.erasedType(TYPE) - block = from_opaque_object(blockcontainer.obj) + block = from_opaque_object(block) v2 = flowmodel.Variable() v2.concretetype = TYPE op = flowmodel.SpaceOperation('cast_pointer', [v], v2) @@ -90,12 +120,12 @@ return v2 return v -def genop(blockcontainer, opname, vars_gv, gv_RESULT_TYPE): +def genop(block, opname, vars_gv, gv_RESULT_TYPE): # 'opname' is a constant string # gv_RESULT_TYPE comes from constTYPE if not isinstance(opname, str): opname = LLSupport.from_rstr(opname) - block = from_opaque_object(blockcontainer.obj) + block = from_opaque_object(block) assert block.exits == [], "block already closed" opvars = _inputvars(vars_gv) if gv_RESULT_TYPE is guess: @@ -125,14 +155,15 @@ result = op.fold(*examples) return lltype.typeOf(result) -def gencallableconst(name, targetcontainer, gv_FUNCTYPE): +def gencallableconst(name, graph, gv_FUNCTYPE): # 'name' is just a way to track things if not isinstance(name, str): name = LLSupport.from_rstr(name) - target = from_opaque_object(targetcontainer.obj) + graph = from_opaque_object(graph) + graph.name = name FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value fptr = lltype.functionptr(FUNCTYPE, name, - graph=_buildgraph(target, FUNCTYPE)) + graph=_buildgraph(graph, FUNCTYPE)) return genconst(fptr) def genconst(llvalue): @@ -181,14 +212,14 @@ c.concretetype = lltype.Void return to_opaque_object(c) -def closeblock1(blockcontainer): - block = from_opaque_object(blockcontainer.obj) +def closeblock1(block): + block = from_opaque_object(block) link = flowmodel.Link([], None) block.closeblock(link) return to_opaque_object(link) -def closeblock2(blockcontainer, exitswitch): - block = from_opaque_object(blockcontainer.obj) +def closeblock2(block, exitswitch): + block = from_opaque_object(block) exitswitch = from_opaque_object(exitswitch) assert isinstance(exitswitch, flowmodel.Variable) block.exitswitch = exitswitch @@ -202,6 +233,29 @@ return pseudotuple(to_opaque_object(false_link), to_opaque_object(true_link)) +def closeblockswitch(block, exitswitch): + block = from_opaque_object(block) + exitswitch = from_opaque_object(exitswitch) + assert isinstance(exitswitch, flowmodel.Variable) + block.exitswitch = exitswitch + default_link = flowmodel.Link([], None) + default_link.exitcase = "default" + default_link.llexitcase = None + block.closeblock(default_link) + return to_opaque_object(default_link) + +def add_case(block, exitcase): + block = from_opaque_object(block) + exitcase = from_opaque_object(exitcase) + assert isinstance(exitcase, flowmodel.Constant) + assert isinstance(block.exitswitch, flowmodel.Variable) + case_link = flowmodel.Link([], None) + case_link.exitcase = exitcase.value + case_link.llexitcase = exitcase.value + exits = block.exits[:-1] + (case_link,) + block.exits[-1:] + block.recloseblock(*exits) + return to_opaque_object(case_link) + class pseudotuple(object): # something that looks both like a hl and a ll tuple def __init__(self, *items): @@ -233,84 +287,55 @@ else: raise TypeError -def closelink(link, vars, targetblockcontainer): - link = from_opaque_object(link) - targetblock = from_opaque_object(targetblockcontainer.obj) - vars = _inputvars(vars) - _closelink(link, vars, targetblock) +def closelink(link, vars, targetblock): + try: + link = from_opaque_object(link) + targetblock = from_opaque_object(targetblock) + vars = _inputvars(vars) + _closelink(link, vars, targetblock) + except Exception, e: + import sys; tb = sys.exc_info()[2] + import pdb; pdb.post_mortem(tb) + raise -def closereturnlink(link, returnvar): +def closereturnlink(link, returnvar, graph): returnvar = from_opaque_object(returnvar) link = from_opaque_object(link) - v = flowmodel.Variable() - v.concretetype = returnvar.concretetype - pseudoreturnblock = flowmodel.Block([v]) - pseudoreturnblock.operations = () - _closelink(link, [returnvar], pseudoreturnblock) - -def _patchgraph(graph, RESULT): - returntype = None - links = [] - for link in graph.iterlinks(): - if link.target.operations == (): - assert len(link.args) == 1 # for now - if returntype is None: - returntype = link.target.inputargs[0].concretetype - else: - assert returntype == link.target.inputargs[0].concretetype - links.append(link) - if returntype is None: - returntype = lltype.Void - graph.returnblock.inputargs[0].concretetype = RESULT - targetblock = casting_bridge([returntype], [RESULT], graph.returnblock) - for link in links: - link.target = targetblock + graph = from_opaque_object(graph) + _closelink(link, [returnvar], graph.prereturnblock) + +def casting_link(source, sourcevars, target): + assert len(sourcevars) == len(target.inputargs) + linkargs = [] + for v, target_v in zip(sourcevars, target.inputargs): + if v.concretetype == target_v.concretetype: + linkargs.append(v) + else: + erasedv = flowmodel.Variable() + erasedv.concretetype = target_v.concretetype + source.operations.append(flowmodel.SpaceOperation('cast_pointer', + [v], + erasedv)) + linkargs.append(erasedv) + source.closeblock(flowmodel.Link(linkargs, target)) + +# ____________________________________________________________ class PseudoRTyper(object): def __init__(self): from pypy.rpython.typesystem import LowLevelTypeSystem self.type_system = LowLevelTypeSystem.instance -def casting_bridge(FROMS, TOS, target): - if FROMS != TOS: - operations = [] - inputargs = [] - linkargs = [] - for FROM, TO in zip(FROMS, TOS): - v = flowmodel.Variable() - v.concretetype = FROM - inputargs.append(v) - if FROM == TO: - linkargs.append(v) - else: - erasedv = flowmodel.Variable() - erasedv.concretetype = TO - operations.append(flowmodel.SpaceOperation('cast_pointer', - [v], - erasedv)) - linkargs.append(erasedv) - bridgeblock = flowmodel.Block(inputargs) - bridgeblock.operations = operations - bridge = flowmodel.Link(linkargs, target) - bridgeblock.closeblock(bridge) - return bridgeblock - else: - return target - -def _buildgraph(block, FUNCTYPE): - ARGS = [v.concretetype for v in block.inputargs] - startblock =casting_bridge(FUNCTYPE.ARGS, ARGS, block) - graph = flowmodel.FunctionGraph('generated', startblock) - _patchgraph(graph, FUNCTYPE.RESULT) +def _buildgraph(graph, FUNCTYPE): flowmodel.checkgraph(graph) eliminate_empty_blocks(graph) join_blocks(graph) graph.rgenop = True return graph -def buildgraph(blockcontainer, FUNCTYPE): - block = from_opaque_object(blockcontainer.obj) - return _buildgraph(block, FUNCTYPE) +def buildgraph(graph, FUNCTYPE): + graph = from_opaque_object(graph) + return _buildgraph(graph, FUNCTYPE) def testgengraph(gengraph, args, viewbefore=False, executor=LLInterpreter): if viewbefore: @@ -318,32 +343,40 @@ llinterp = executor(PseudoRTyper()) return llinterp.eval_graph(gengraph, args) -def runblock(blockcontainer, FUNCTYPE, args, +def runblock(graph, FUNCTYPE, args, viewbefore=False, executor=LLInterpreter): - graph = buildgraph(blockcontainer, FUNCTYPE) + graph = buildgraph(graph, FUNCTYPE) return testgengraph(graph, args, viewbefore, executor) +def show_incremental_progress(graph): + from pypy import conftest + if conftest.option.view: + graph = from_opaque_object(graph) + graph.show() + # ____________________________________________________________ # RTyping of the above functions -from pypy.rpython.extfunctable import declaretype, declareptrtype, declare +from pypy.rpython.extfunctable import declareptrtype -blocktypeinfo = declaretype(flowmodel.Block, "Block") +blocktypeinfo = declareptrtype(flowmodel.Block, "Block") consttypeinfo = declareptrtype(flowmodel.Constant, "ConstOrVar") vartypeinfo = declareptrtype(flowmodel.Variable, "ConstOrVar") vartypeinfo.set_lltype(consttypeinfo.get_lltype()) # force same lltype linktypeinfo = declareptrtype(flowmodel.Link, "Link") +graphtypeinfo = declareptrtype(flowmodel.FunctionGraph, "FunctionGraph") CONSTORVAR = lltype.Ptr(consttypeinfo.get_lltype()) -BLOCKCONTAINERTYPE = blocktypeinfo.get_lltype() -BLOCK = lltype.Ptr(BLOCKCONTAINERTYPE) +BLOCK = lltype.Ptr(blocktypeinfo.get_lltype()) LINK = lltype.Ptr(linktypeinfo.get_lltype()) +GRAPH = lltype.Ptr(graphtypeinfo.get_lltype()) # support constants and types nullvar = lltype.nullptr(CONSTORVAR.TO) nullblock = lltype.nullptr(BLOCK.TO) nulllink = lltype.nullptr(LINK.TO) +nullgraph = lltype.nullptr(GRAPH.TO) gv_Void = constTYPE(lltype.Void) dummy_placeholder = placeholder(None) @@ -384,9 +417,14 @@ s_ConstOrVar = annmodel.SomePtr(CONSTORVAR)#annmodel.SomeExternalObject(flowmodel.Variable) s_Link = annmodel.SomePtr(LINK)#annmodel.SomeExternalObject(flowmodel.Link) s_LinkPair = annmodel.SomeTuple([s_Link, s_Link]) +s_Block = annmodel.SomePtr(BLOCK) +s_Graph = annmodel.SomePtr(GRAPH) -setannotation(initblock, None) +setannotation(newblock, s_Block) +setannotation(newgraph, s_Graph) +setannotation(getstartblock, s_Block) setannotation(geninputarg, s_ConstOrVar) +setannotation(getinputarg, s_ConstOrVar) setannotation(genop, s_ConstOrVar) setannotation(gencallableconst, s_ConstOrVar) setannotation(genconst, s_ConstOrVar) @@ -396,6 +434,8 @@ setannotation(isconst, annmodel.SomeBool()) setannotation(closeblock1, s_Link) setannotation(closeblock2, s_LinkPair) +setannotation(closeblockswitch, s_Link) +setannotation(add_case, s_Link) setannotation(closelink, None) setannotation(closereturnlink, None) @@ -405,3 +445,5 @@ setannotation(constFieldName, s_ConstOrVar, specialize_as_constant=True) setannotation(constTYPE, s_ConstOrVar, specialize_as_constant=True) #setannotation(placeholder, s_ConstOrVar, specialize_as_constant=True) + +setannotation(show_incremental_progress, None) Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Thu Sep 28 20:10:20 2006 @@ -1,7 +1,7 @@ from pypy.rpython.objectmodel import specialize from pypy.rpython.lltypesystem import lltype from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator -from pypy.jit.codegen.model import GenVar, GenConst +from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.llgraph import llimpl from pypy.rpython.lltypesystem.rclass import fishllattr @@ -30,14 +30,29 @@ class LLBlock(CodeGenBlock): - def __init__(self, b): + def __init__(self, b, g): self.b = b + self.g = g + +class LLFlexSwitch(CodeGenSwitch): + + def __init__(self, b, g): + self.b = b + self.g = g + + def add_case(self, gv_case): + l_case = llimpl.add_case(self.b, gv_case.v) + builder = LLBuilder(self.g) + builder.lnk = l_case + return builder + class LLBuilder(CodeGenerator): lnk = llimpl.nulllink - def __init__(self): + def __init__(self, g): self.rgenop = rgenop + self.g = g @specialize.arg(1) def genop1(self, opname, gv_arg): @@ -114,7 +129,7 @@ llimpl.closelink(lnk, args_gv, self.b) for i in range(len(args_gv)): args_gv[i] = newb_args_gv[i] - return LLBlock(self.b) + return LLBlock(self.b, self.g) def finish_and_goto(self, args_gv, targetblock): lnk = self.lnk or llimpl.closeblock1(self.b) @@ -122,15 +137,15 @@ llimpl.closelink(lnk, args_gv, targetblock.b) def finish_and_return(self, sigtoken, gv_returnvar): + gv_returnvar = gv_returnvar or gv_dummy_placeholder lnk = self.lnk or llimpl.closeblock1(self.b) self.lnk = llimpl.nulllink - llimpl.closereturnlink(lnk, - (gv_returnvar or gv_dummy_placeholder).v) + llimpl.closereturnlink(lnk, gv_returnvar.v, self.g) def jump_if_true(self, gv_cond): l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) self.b = llimpl.nullblock - later_builder = LLBuilder() + later_builder = LLBuilder(self.g) later_builder.lnk = l_true self.lnk = l_false return later_builder @@ -138,24 +153,36 @@ def jump_if_false(self, gv_cond): l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v) self.b = llimpl.nullblock - later_builder = LLBuilder() + later_builder = LLBuilder(self.g) later_builder.lnk = l_false self.lnk = l_true return later_builder + def flexswitch(self, gv_switchvar): + l_default = llimpl.closeblockswitch(self.b, gv_switchvar.v) + flexswitch = LLFlexSwitch(self.b, self.g) + self.b = llimpl.nullblock + self.lnk = l_default + return flexswitch + + def show_incremental_progress(self): + llimpl.show_incremental_progress(self.g) + class RGenOp(AbstractRGenOp): gv_Void = gv_Void def newgraph(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE)): - builder = LLBuilder() - inputargs_gv = builder._newblock(ARGS_gv) - return builder, LLBlock(builder.b), inputargs_gv - - def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, - entrypoint): - return LLConst(llimpl.gencallableconst(name, entrypoint.b, + graph = llimpl.newgraph(gv_FUNCTYPE.v) + builder = LLBuilder(graph) + builder.b = llimpl.getstartblock(graph) + inputargs_gv = [LLVar(llimpl.getinputarg(builder.b, i)) + for i in range(len(ARGS_gv))] + return builder, graph, inputargs_gv + + def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, graph): + return LLConst(llimpl.gencallableconst(name, graph, gv_FUNCTYPE.v)) @staticmethod @@ -201,6 +228,15 @@ constPrebuiltGlobal = genconst + def replay(self, block, kinds): + builder = LLBuilder(block.g) + args_gv = builder._newblock(kinds) + return builder, args_gv + + def stop_replay(self, endblock, kinds): + return [LLVar(llimpl.getinputarg(endblock.b, i)) + for i in range(len(kinds))] + # not RPython, just for debugging. Specific to llgraph. @staticmethod def reveal(gv): @@ -210,15 +246,6 @@ v = fishllattr(gv, 'v') return llimpl.reveal(v) - # Builds a real flow.model.FunctionGraph. Specific to llgraph. - @staticmethod - def buildgraph(block, FUNCTYPE): - if hasattr(block, 'b'): - b = block.b - else: - b = fishllattr(block, 'b') - return llimpl.buildgraph(b, FUNCTYPE) - def _freeze_(self): return True # no real point in using a full class in llgraph Modified: pypy/dist/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/dist/pypy/jit/codegen/model.py Thu Sep 28 20:10:20 2006 @@ -23,3 +23,7 @@ class AbstractRGenOp(object): pass + + +class CodeGenSwitch(object): + pass Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Thu Sep 28 20:10:20 2006 @@ -258,6 +258,10 @@ # turn a variable to a constant origin = getbookkeeper().myorigin() return SomeLLAbstractConstant(hs_v1.concretetype, {origin: True}) + if hs_flags.const.get('promote', False): + hs_concrete = SomeLLAbstractConstant(hs_v1.concretetype, {}) + hs_concrete.eager_concrete = True + return hs_concrete def getfield(hs_v1, hs_fieldname): S = hs_v1.concretetype.TO @@ -311,8 +315,6 @@ return hs_c1 def hint(hs_c1, hs_flags): - if hs_flags.const.get('variable', False): # only for testing purposes!!! - return SomeLLAbstractVariable(hs_c1.concretetype) if hs_flags.const.get('concrete', False): for o in hs_c1.origins: o.set_fixed() @@ -322,6 +324,7 @@ if hs_flags.const.get('forget', False): assert isinstance(hs_c1, SomeLLAbstractConstant) return reorigin(hs_c1) + return SomeLLAbstractValue.hint(hs_c1, hs_flags) def direct_call(hs_f1, *args_hs): bookkeeper = getbookkeeper() Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Thu Sep 28 20:10:20 2006 @@ -1,5 +1,6 @@ import operator from pypy.rpython.lltypesystem import lltype +from pypy.rpython.annlowlevel import cachedtype from pypy.jit.timeshifter import rvalue class AbstractContainer(object): @@ -14,27 +15,8 @@ def op_getsubstruct(self, jitstate, fielddesc): raise NotImplementedError - # ____________________________________________________________ -class cachedtype(type): - """Metaclass for classes that should only have one instance per - tuple of arguments given to the constructor.""" - - def __init__(selfcls, name, bases, dict): - super(cachedtype, selfcls).__init__(name, bases, dict) - selfcls._instancecache = {} - - def __call__(selfcls, *args): - d = selfcls._instancecache - try: - return d[args] - except KeyError: - instance = d[args] = selfcls.__new__(selfcls, *args) - instance.__init__(*args) - return instance - - class StructTypeDesc(object): __metaclass__ = cachedtype firstsubstructdesc = None Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Thu Sep 28 20:10:20 2006 @@ -1,8 +1,12 @@ import operator, weakref +from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype, lloperation, llmemory from pypy.jit.hintannotator.model import originalconcretetype from pypy.jit.timeshifter import rvalue from pypy.rpython.unroll import unrolling_iterable +from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr +from pypy.rpython.annlowlevel import cast_base_ptr_to_instance FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops()) @@ -184,7 +188,7 @@ incoming[i].genvar = linkargs[i] return newblock -def start_new_block(states_dic, jitstate, key): +def start_new_block(states_dic, jitstate, key, global_resumer): memo = rvalue.freeze_memo() frozen = jitstate.freeze(memo) memo = rvalue.exactmatch_memo() @@ -193,11 +197,17 @@ assert res, "exactmatch() failed" newblock = enter_next_block(jitstate, outgoingvarboxes) states_dic[key] = frozen, newblock + if global_resumer: + greens_gv = jitstate.greens + rgenop = jitstate.curbuilder.rgenop + jitstate.promotion_path = PromotionPathRoot(greens_gv, rgenop, + frozen, newblock, + global_resumer) start_new_block._annspecialcase_ = "specialize:arglltype(2)" -def retrieve_jitstate_for_merge(states_dic, jitstate, key): +def retrieve_jitstate_for_merge(states_dic, jitstate, key, global_resumer): if key not in states_dic: - start_new_block(states_dic, jitstate, key) + start_new_block(states_dic, jitstate, key, global_resumer) return False # continue frozen, oldblock = states_dic[key] @@ -219,7 +229,7 @@ box.forcevar(jitstate.curbuilder, replace_memo) if replace_memo.boxes: jitstate.replace(replace_memo) - start_new_block(states_dic, jitstate, key) + start_new_block(states_dic, jitstate, key, global_resumer) return False # continue retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)" @@ -231,8 +241,15 @@ def split(jitstate, switchredbox, resumepoint, *greens_gv): exitgvar = switchredbox.getgenvar(jitstate.curbuilder) - later_builder = jitstate.curbuilder.jump_if_false(exitgvar) - jitstate.split(later_builder, resumepoint, list(greens_gv)) + if exitgvar.is_const: + return exitgvar.revealconst(lltype.Bool) + else: + if jitstate.resuming is None: + later_builder = jitstate.curbuilder.jump_if_false(exitgvar) + jitstate.split(later_builder, resumepoint, list(greens_gv)) + return True + else: + return jitstate.resuming.path.pop() def collect_split(jitstate_chain, resumepoint, *greens_gv): greens_gv = list(greens_gv) @@ -304,6 +321,145 @@ ##def ll_gvar_from_constant(jitstate, ll_value): ## return jitstate.curbuilder.rgenop.genconst(ll_value) + + +class ResumingInfo(object): + def __init__(self, promotion_point, gv_value, path): + self.promotion_point = promotion_point + self.gv_value = gv_value + self.path = path + +class PromotionPoint(object): + def __init__(self, flexswitch, switchblock, promotion_path): + assert promotion_path is not None + self.flexswitch = flexswitch + self.switchblock = switchblock + self.promotion_path = promotion_path + +class AbstractPromotionPath(object): + pass + +class PromotionPathRoot(AbstractPromotionPath): + def __init__(self, greens_gv, rgenop, frozen, portalblock, global_resumer): + self.greens_gv = greens_gv + self.rgenop = rgenop + self.frozen = frozen + self.portalblock = portalblock + self.global_resumer = global_resumer + + def follow_path(self, path): + return self + + def continue_compilation(self, resuminginfo): + incoming = [] + memo = rvalue.unfreeze_memo() + jitstate = self.frozen.unfreeze(incoming, memo) + kinds = [box.kind for box in incoming] + builder, vars_gv = self.rgenop.replay(self.portalblock, kinds) + for i in range(len(incoming)): + incoming[i].genvar = vars_gv[i] + jitstate.curbuilder = builder + jitstate.greens = self.greens_gv + jitstate.resuming = resuminginfo + assert jitstate.frame.backframe is None + self.global_resumer(jitstate) + builder.show_incremental_progress() + +class PromotionPathNode(AbstractPromotionPath): + def __init__(self, next): + self.next = next + def follow_path(self, path): + path.append(self.direct) + return self.next.follow_path(path) + +class PromotionPathDirect(PromotionPathNode): + direct = True + +class PromotionPathIndirect(PromotionPathNode): + direct = False + +def ll_continue_compilation(promotion_point_ptr, value): + try: + promotion_point = cast_base_ptr_to_instance(PromotionPoint, + promotion_point_ptr) + path = [] + root = promotion_point.promotion_path.follow_path(path) + gv_value = root.rgenop.genconst(value) + resuminginfo = ResumingInfo(promotion_point, gv_value, path) + root.continue_compilation(resuminginfo) + except Exception, e: + lloperation.llop.debug_fatalerror(lltype.Void, + "compilation-time error", e) + +class PromotionDesc: + __metatype__ = cachedtype + + def __init__(self, ERASED, hrtyper): +## (s_PromotionPoint, +## r_PromotionPoint) = hrtyper.s_r_instanceof(PromotionPoint) + fnptr = hrtyper.annhelper.delayedfunction( + ll_continue_compilation, + [annmodel.SomePtr(base_ptr_lltype()), + annmodel.lltype_to_annotation(ERASED)], + annmodel.s_None, needtype=True) + RGenOp = hrtyper.RGenOp + self.gv_continue_compilation = RGenOp.constPrebuiltGlobal(fnptr) + self.sigtoken = RGenOp.sigToken(lltype.typeOf(fnptr).TO) +## self.PROMOTION_POINT = r_PromotionPoint.lowleveltype + + def _freeze_(self): + return True + +def ll_promote(jitstate, box, promotiondesc): + builder = jitstate.curbuilder + gv_switchvar = box.getgenvar(builder) + if gv_switchvar.is_const: + return False + else: + incoming = [] + memo = rvalue.enter_block_memo() + jitstate.enter_block(incoming, memo) + switchblock = enter_next_block(jitstate, incoming) + + if jitstate.resuming is None: + gv_switchvar = box.genvar + flexswitch = builder.flexswitch(gv_switchvar) + # default case of the switch: + enter_block(jitstate) + pm = PromotionPoint(flexswitch, switchblock, + jitstate.promotion_path) + ll_pm = cast_instance_to_base_ptr(pm) + gv_pm = builder.rgenop.genconst(ll_pm) + gv_switchvar = box.genvar + builder.genop_call(promotiondesc.sigtoken, + promotiondesc.gv_continue_compilation, + [gv_pm, gv_switchvar]) + linkargs = [] + for box in incoming: + linkargs.append(box.getgenvar(builder)) + builder.finish_and_goto(linkargs, switchblock) + return True + else: + assert jitstate.promotion_path is None + resuming = jitstate.resuming + assert len(resuming.path) == 0 + pm = resuming.promotion_point + + kinds = [box.kind for box in incoming] + vars_gv = jitstate.curbuilder.rgenop.stop_replay(pm.switchblock, + kinds) + for i in range(len(incoming)): + incoming[i].genvar = vars_gv[i] + box.genvar = resuming.gv_value + + newbuilder = pm.flexswitch.add_case(resuming.gv_value) + + jitstate.resuming = None + jitstate.promotion_path = pm.promotion_path + jitstate.curbuilder = newbuilder + enter_block(jitstate) + return False + # ____________________________________________________________ class BaseDispatchQueue(object): @@ -346,6 +502,18 @@ assert vframe.backframe is None return fullmatch + def unfreeze(self, incomingvarboxes, memo): + local_boxes = [] + for fzbox in self.fz_local_boxes: + local_boxes.append(fzbox.unfreeze(incomingvarboxes, memo)) + if self.fz_backframe is not None: + backframe = self.fz_backframe.unfreeze(incomingvarboxes, memo) + else: + backframe = None + vframe = VirtualFrame(backframe, BaseDispatchQueue()) + vframe.local_boxes = local_boxes + return vframe + class FrozenJITState(object): #fz_frame = ... set by freeze() @@ -368,6 +536,12 @@ fullmatch = False return fullmatch + def unfreeze(self, incomingvarboxes, memo): + frame = self.fz_frame .unfreeze(incomingvarboxes, memo) + exc_type_box = self.fz_exc_type_box .unfreeze(incomingvarboxes, memo) + exc_value_box = self.fz_exc_value_box.unfreeze(incomingvarboxes, memo) + return JITState(None, frame, exc_type_box, exc_value_box) + class VirtualFrame(object): @@ -410,15 +584,17 @@ class JITState(object): returnbox = None next = None # for linked lists + resuming = None # or a ResumingInfo def __init__(self, builder, frame, exc_type_box, exc_value_box, - resumepoint=-1, newgreens=[]): + resumepoint=-1, newgreens=[], promotion_path=None): self.curbuilder = builder self.frame = frame self.exc_type_box = exc_type_box self.exc_value_box = exc_value_box self.resumepoint = resumepoint self.greens = newgreens + self.promotion_path = promotion_path def split(self, newbuilder, newresumepoint, newgreens): memo = rvalue.copy_memo() @@ -427,7 +603,9 @@ self.exc_type_box .copy(memo), self.exc_value_box.copy(memo), newresumepoint, - newgreens) + newgreens, + PromotionPathIndirect(self.promotion_path)) + self.promotion_path = PromotionPathDirect(self.promotion_path) # add the later_jitstate to the chain of pending-for-dispatch_next() dispatch_queue = self.frame.dispatch_queue later_jitstate.next = dispatch_queue.split_chain @@ -456,6 +634,9 @@ enter_graph._annspecialcase_ = 'specialize:arg(1)' # XXX is that too many specializations? ^^^ +class CompilationInterrupted(Exception): + pass + def merge_returning_jitstates(jitstate): return_chain = jitstate.frame.dispatch_queue.return_chain return_cache = {} @@ -463,17 +644,18 @@ while return_chain is not None: jitstate = return_chain return_chain = return_chain.next - res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + res = retrieve_jitstate_for_merge(return_cache, jitstate, (), None) if res is False: # not finished jitstate.next = still_pending still_pending = jitstate - assert still_pending is not None + if still_pending is None: + raise CompilationInterrupted most_general_jitstate = still_pending still_pending = still_pending.next while still_pending is not None: jitstate = still_pending still_pending = still_pending.next - res = retrieve_jitstate_for_merge(return_cache, jitstate, ()) + res = retrieve_jitstate_for_merge(return_cache, jitstate, (), None) assert res is True # finished return most_general_jitstate Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 28 20:10:20 2006 @@ -191,6 +191,14 @@ # the graph is transformed already return self.annotator.bookkeeper.tsgraphsigs[tsgraph] + def get_residual_functype(self, tsgraph): + ha = self.annotator + args_hs, hs_res = self.get_sig_hs(ha.translator.graphs[0]) + RESTYPE = originalconcretetype(hs_res) + ARGS = [originalconcretetype(hs_arg) for hs_arg in args_hs + if not hs_arg.is_green()] + return lltype.FuncType(ARGS, RESTYPE) + def make_new_lloplist(self, block): return HintLowLevelOpList(self) @@ -230,8 +238,11 @@ try: return self.dispatchsubclasses[mergepointfamily] except KeyError: - attrnames = mergepointfamily.getattrnames() - subclass = rtimeshift.build_dispatch_subclass(attrnames) + if mergepointfamily.is_global: + subclass = rtimeshift.BaseDispatchQueue + else: + attrnames = mergepointfamily.getattrnames() + subclass = rtimeshift.build_dispatch_subclass(attrnames) self.dispatchsubclasses[mergepointfamily] = subclass return subclass @@ -357,24 +368,6 @@ [c_opdesc, v_jitstate] + args_v, ts.s_RedBox) - def translate_op_hint(self, hop): - # don't try to generate hint operations, just discard them - hints = hop.args_v[-1].value - if hints.get('forget', False): - T = originalconcretetype(hop.args_s[0]) - v_redbox = hop.inputarg(self.getredrepr(T), arg=0) - assert isinstance(hop.r_result, GreenRepr) - ts = self - c_T = hop.inputconst(lltype.Void, T) - s_T = ts.rtyper.annotator.bookkeeper.immutablevalue(T) - s_res = annmodel.lltype_to_annotation(T) - return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue, - [ts.s_RedBox, s_T], - [v_redbox, c_T], - s_res) - - return hop.inputarg(hop.r_result, arg=0) - def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc pass @@ -717,8 +710,9 @@ args_s += [self.s_ConstOrVar] * len(greens_v) args_v = [v_jitstate, v_switch, c_resumepoint] args_v += greens_v - hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v, - annmodel.s_None) + return hop.llops.genmixlevelhelpercall(rtimeshift.split, + args_s, args_v, + annmodel.SomeBool()) def translate_op_collect_split(self, hop): GREENS = [v.concretetype for v in hop.args_v[1:]] @@ -738,17 +732,25 @@ args_s, args_v, annmodel.s_None) - def translate_op_merge_point(self, hop): + def translate_op_merge_point(self, hop, global_resumer=None): mpfamily = hop.args_v[0].value attrname = hop.args_v[1].value DispatchQueueSubclass = self.get_dispatch_subclass(mpfamily) - def merge_point(jitstate, *key): - dispatch_queue = jitstate.frame.dispatch_queue - assert isinstance(dispatch_queue, DispatchQueueSubclass) - states_dic = getattr(dispatch_queue, attrname) - return rtimeshift.retrieve_jitstate_for_merge(states_dic, - jitstate, key) + if mpfamily.is_global: + states_dic = {} + def merge_point(jitstate, *key): + return rtimeshift.retrieve_jitstate_for_merge(states_dic, + jitstate, key, + global_resumer) + else: + def merge_point(jitstate, *key): + dispatch_queue = jitstate.frame.dispatch_queue + assert isinstance(dispatch_queue, DispatchQueueSubclass) + states_dic = getattr(dispatch_queue, attrname) + return rtimeshift.retrieve_jitstate_for_merge(states_dic, + jitstate, key, + global_resumer) greens_v = [] greens_s = [] @@ -767,6 +769,37 @@ [v_jitstate ] + greens_v, annmodel.SomeBool()) + def translate_op_global_merge_point(self, hop): + mpfamily = hop.args_v[0].value + attrname = hop.args_v[1].value + N = mpfamily.resumepoint_after_mergepoint[attrname] + tsgraph = mpfamily.tsgraph + ts_fnptr = self.gettscallable(tsgraph) + TS_FUNC = lltype.typeOf(ts_fnptr) + dummy_args = [ARG._defl() for ARG in TS_FUNC.TO.ARGS[1:]] + dummy_args = tuple(dummy_args) + JITSTATE = self.r_JITState.lowleveltype + RESIDUAL_FUNCTYPE = self.get_residual_functype(tsgraph) + residualSigToken = self.RGenOp.sigToken(RESIDUAL_FUNCTYPE) + ll_finish_jitstate = self.ll_finish_jitstate + + args_s = [self.s_JITState] + [annmodel.lltype_to_annotation(ARG) + for ARG in TS_FUNC.TO.ARGS[1:]] + s_res = self.s_JITState + tsfn = annlowlevel.PseudoHighLevelCallable(ts_fnptr, args_s, s_res) + + def call_for_global_resuming(jitstate): + jitstate.resumepoint = N + try: + finaljitstate = tsfn(jitstate, *dummy_args) + except rtimeshift.CompilationInterrupted: + pass + else: + ll_finish_jitstate(finaljitstate, residualSigToken) + + return self.translate_op_merge_point(hop, + global_resumer = call_for_global_resuming) + def translate_op_save_return(self, hop): v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.save_return, @@ -781,11 +814,29 @@ [v_jitstate ], self.s_JITState) hop.llops.setjitstate(v_newjs) + + def translate_op_getresumepoint(self, hop): + v_jitstate = hop.llops.getjitstate() return hop.llops.genmixlevelhelpercall(rtimeshift.getresumepoint, [self.s_JITState], - [v_newjs ], + [v_jitstate ], annmodel.SomeInteger()) + def translate_op_promote(self, hop): + TYPE = originalconcretetype(hop.args_s[0]) + r_arg = self.getredrepr(TYPE) + [v_box] = hop.inputargs(r_arg) + r_result = self.getgreenrepr(TYPE) + ERASED = annmodel.annotation_to_lltype(r_result.erased_annotation()) + desc = rtimeshift.PromotionDesc(ERASED, self) + s_desc = self.rtyper.annotator.bookkeeper.immutablevalue(desc) + c_desc = hop.inputconst(lltype.Void, desc) + v_jitstate = hop.llops.getjitstate() + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_promote, + [self.s_JITState, self.s_RedBox, s_desc], + [v_jitstate , v_box , c_desc], + annmodel.SomeBool()) + # handling of the various kinds of calls def translate_op_oopspec_call(self, hop): Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Thu Sep 28 20:10:20 2006 @@ -19,6 +19,9 @@ def copy_memo(): return Memo() +def unfreeze_memo(): + return Memo() + class RedBox(object): __slots__ = ['kind', 'genvar'] @@ -135,9 +138,9 @@ return memo[self] except KeyError: if self.is_constant(): - result = FrozenIntConst(self.genvar) + result = FrozenIntConst(self.kind, self.genvar) else: - result = FrozenIntVar() + result = FrozenIntVar(self.kind) memo[self] = result return result @@ -159,9 +162,9 @@ return memo[self] except KeyError: if self.is_constant(): - result = FrozenDoubleConst(self.genvar) + result = FrozenDoubleConst(self.kind, self.genvar) else: - result = FrozenDoubleVar() + result = FrozenDoubleVar(self.kind) memo[self] = result return result @@ -205,14 +208,14 @@ return boxmemo[self] except KeyError: if self.content: - result = FrozenPtrVirtual() + result = FrozenPtrVirtual(self.kind) boxmemo[self] = result result.fz_content = self.content.freeze(memo) else: if self.is_constant(): - result = FrozenPtrConst(self.genvar) + result = FrozenPtrConst(self.kind, self.genvar) else: - result = FrozenPtrVar() + result = FrozenPtrVar(self.kind) boxmemo[self] = result return result @@ -234,11 +237,14 @@ class FrozenValue(object): """An abstract value frozen in a saved state. """ + def __init__(self, kind): + self.kind = kind class FrozenIntConst(FrozenValue): - def __init__(self, gv_const): + def __init__(self, kind, gv_const): + self.kind = kind self.gv_const = gv_const def exactmatch(self, box, outgoingvarboxes, memo): @@ -250,6 +256,10 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + # XXX could return directly the original IntRedBox + return IntRedBox(self.kind, self.gv_const) + class FrozenIntVar(FrozenValue): @@ -265,10 +275,21 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + memo = memo.boxes + if self not in memo: + newbox = IntRedBox(self.kind, None) + incomingvarboxes.append(newbox) + memo[self] = newbox + return newbox + else: + return memo[self] + class FrozenDoubleConst(FrozenValue): - def __init__(self, gv_const): + def __init__(self, kind, gv_const): + self.kind = kind self.gv_const = gv_const def exactmatch(self, box, outgoingvarboxes, memo): @@ -280,6 +301,9 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + return DoubleRedBox(self.kind, self.gv_const) + class FrozenDoubleVar(FrozenValue): @@ -295,10 +319,21 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + memo = memo.boxes + if self not in memo: + newbox = DoubleRedBox(self.kind, None) + incomingvarboxes.append(newbox) + memo[self] = newbox + return newbox + else: + return memo[self] + class FrozenPtrConst(FrozenValue): - def __init__(self, gv_const): + def __init__(self, kind, gv_const): + self.kind = kind self.gv_const = gv_const def exactmatch(self, box, outgoingvarboxes, memo): @@ -310,6 +345,9 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + return PtrRedBox(self.kind, self.gv_const) + class FrozenPtrVar(FrozenValue): @@ -325,6 +363,16 @@ outgoingvarboxes.append(box) return False + def unfreeze(self, incomingvarboxes, memo): + memo = memo.boxes + if self not in memo: + newbox = PtrRedBox(self.kind, None) + incomingvarboxes.append(newbox) + memo[self] = newbox + return newbox + else: + return memo[self] + class FrozenPtrVirtual(FrozenValue): @@ -336,3 +384,7 @@ else: return self.fz_content.exactmatch(box.content, outgoingvarboxes, memo) + + def unfreeze(self, incomingvarboxes, memo): + #return self.fz_content.unfreeze(self.kind, incomingvarboxes, memo) + raise NotImplementedError Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 28 20:10:20 2006 @@ -99,8 +99,6 @@ fresh_jitstate = hrtyper.ll_fresh_jitstate finish_jitstate = hrtyper.ll_finish_jitstate - args_hs, hs_res = hrtyper.get_sig_hs(ha.translator.graphs[0]) - RESTYPE = originalconcretetype(hs_res) t = rtyper.annotator.translator for graph in ha.translator.graphs: checkgraph(graph) @@ -119,11 +117,10 @@ assert len(graph1.getargs()) == 1 + len(values) graph1varargs = graph1.getargs()[1:] timeshifted_entrypoint_args_s = [] - residual_argtypes = [] argcolors = [] generate_code_args_s = [] - for v, hs_arg, llvalue in zip(graph1varargs, args_hs, values): + for v, llvalue in zip(graph1varargs, values): s_var = annmodel.ll_to_annotation(llvalue) r = hrtyper.bindingrepr(v) residual_v = r.residual_values(llvalue) @@ -133,8 +130,6 @@ else: color = "red" assert residual_v == [llvalue], "XXX for now" - ARGTYPE = originalconcretetype(hs_arg) - residual_argtypes.append(ARGTYPE) timeshifted_entrypoint_args_s.append(hrtyper.s_RedBox) generate_code_args_s.append(annmodel.SomeBool()) argcolors.append(color) @@ -147,7 +142,7 @@ [hrtyper.s_JITState] + timeshifted_entrypoint_args_s, hrtyper.s_JITState) - FUNC = lltype.FuncType(residual_argtypes, RESTYPE) + FUNC = hrtyper.get_residual_functype(ha.translator.graphs[0]) argcolors = unrolling_iterable(argcolors) self.argcolors = argcolors @@ -180,9 +175,13 @@ timeshifted_entrypoint_args += (box,) top_jitstate = fresh_jitstate(builder) - top_jitstate = timeshifted_entrypoint(top_jitstate, + try: + top_jitstate = timeshifted_entrypoint(top_jitstate, *timeshifted_entrypoint_args) - finish_jitstate(top_jitstate, sigtoken) + except rtimeshift.CompilationInterrupted: + pass + else: + finish_jitstate(top_jitstate, sigtoken) gv_generated = rgenop.gencallableconst(sigtoken, "generated", entrypoint) @@ -272,9 +271,10 @@ # now try to run the residual graph generated by the builder residual_graph = ll_generated._obj.graph residual_graph.exceptiontransformed = self.hrtyper.exc_data_ptr + self.ll_generated = ll_generated + self.residual_graph = residual_graph if conftest.option.view: residual_graph.show() - self.insns = summary(residual_graph) if 'check_raises' not in kwds: res = llinterp.eval_graph(residual_graph, residualargs) @@ -314,6 +314,7 @@ return self.timeshift(ll_function, values, opt_consts, *args, **kwds) def check_insns(self, expected=None, **counts): + self.insns = summary(self.residual_graph) if expected is not None: assert self.insns == expected for opname, count in counts.items(): Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Thu Sep 28 20:10:20 2006 @@ -13,8 +13,11 @@ class MergePointFamily(object): - def __init__(self): + def __init__(self, tsgraph, is_global=False): + self.tsgraph = tsgraph + self.is_global = is_global self.count = 0 + self.resumepoint_after_mergepoint = {} def add(self): result = self.count self.count += 1 @@ -30,27 +33,32 @@ self.hannotator = hannotator self.graph = graph self.graphcolor = self.graph_calling_color(graph) + self.global_merge_points = self.graph_global_mps(self.graph) self.resumepoints = {} - self.mergepointfamily = MergePointFamily() + self.mergepoint_set = {} # set of blocks + self.mergepointfamily = MergePointFamily(graph, + self.global_merge_points) self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily) self.tsgraphs_seen = [] def transform(self): - mergepoints = list(self.enumerate_merge_points()) + self.compute_merge_points() self.insert_save_return() self.insert_splits() - for block in mergepoints: - self.insert_merge(block) self.split_after_calls() - self.insert_dispatcher() + self.handle_hints() + self.insert_merge_points() self.insert_enter_graph() + self.insert_dispatcher() self.insert_leave_graph() - def enumerate_merge_points(self): + def compute_merge_points(self): entrymap = mkentrymap(self.graph) for block, links in entrymap.items(): if len(links) > 1 and block is not self.graph.returnblock: - yield block + self.mergepoint_set[block] = True + if self.global_merge_points: + self.mergepoint_set[self.graph.startblock] = True def graph_calling_color(self, tsgraph): args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph] @@ -61,6 +69,12 @@ else: return 'red' + def graph_global_mps(self, tsgraph): + try: + return tsgraph.func._global_merge_points_ + except AttributeError: + return False + def timeshifted_graph_of(self, graph, args_v): bk = self.hannotator.bookkeeper args_hs = [self.hannotator.binding(v) for v in args_v] @@ -147,6 +161,13 @@ reds.append(v) return reds, greens + def before_start_block(self): + entryblock = self.new_block_before(self.graph.startblock) + entryblock.isstartblock = True + self.graph.startblock.isstartblock = False + self.graph.startblock = entryblock + return entryblock + def before_return_block(self): block = self.graph.returnblock block.operations = [] @@ -171,6 +192,7 @@ self.insert_split_handling(block) def insert_split_handling(self, block): + # lots of clever in-line logic commented out v_redswitch = block.exitswitch link_f, link_t = block.exits if link_f.exitcase: @@ -178,35 +200,42 @@ assert link_f.exitcase is False assert link_t.exitcase is True - constant_block = Block([]) - nonconstant_block = Block([]) +## constant_block = Block([]) +## nonconstant_block = Block([]) - v_flag = self.genop(block, 'is_constant', [v_redswitch], - resulttype = lltype.Bool) - self.genswitch(block, v_flag, true = constant_block, - false = nonconstant_block) - - v_greenswitch = self.genop(constant_block, 'revealconst', - [v_redswitch], - resulttype = lltype.Bool) - constant_block.exitswitch = v_greenswitch - constant_block.closeblock(link_f, link_t) +## v_flag = self.genop(block, 'is_constant', [v_redswitch], +## resulttype = lltype.Bool) +## self.genswitch(block, v_flag, true = constant_block, +## false = nonconstant_block) + +## v_greenswitch = self.genop(constant_block, 'revealconst', +## [v_redswitch], +## resulttype = lltype.Bool) +## constant_block.exitswitch = v_greenswitch +## constant_block.closeblock(link_f, link_t) reds, greens = self.sort_by_color(link_f.args, link_f.target.inputargs) - self.genop(nonconstant_block, 'save_locals', reds) + self.genop(block, 'save_locals', reds) resumepoint = self.get_resume_point(link_f.target) c_resumepoint = inputconst(lltype.Signed, resumepoint) - self.genop(nonconstant_block, 'split', - [v_redswitch, c_resumepoint] + greens) + v_flag = self.genop(block, 'split', + [v_redswitch, c_resumepoint] + greens, + resulttype = lltype.Bool) + + block.exitswitch = v_flag + true_block = Block([]) + true_link = Link([], true_block) + true_link.exitcase = True + true_link.llexitcase = True + block.recloseblock(link_f, true_link) reds, greens = self.sort_by_color(link_t.args) - self.genop(nonconstant_block, 'save_locals', reds) - self.genop(nonconstant_block, 'enter_block', []) - nonconstant_block.closeblock(Link(link_t.args, link_t.target)) - - SSA_to_SSI({block : True, # reachable from outside - constant_block : False, - nonconstant_block: False}, self.hannotator) + self.genop(true_block, 'save_locals', reds) + self.genop(true_block, 'enter_block', []) + true_block.closeblock(Link(link_t.args, link_t.target)) + + SSA_to_SSI({block : True, # reachable from outside + true_block: False}, self.hannotator) def get_resume_point_link(self, block): try: @@ -239,6 +268,21 @@ def get_resume_point(self, block): return self.get_resume_point_link(block).exitcase + def go_to_if(self, block, target, v_finished_flag): + block.exitswitch = v_finished_flag + [link_f] = block.exits + link_t = Link([self.c_dummy], target) + link_f.exitcase = False + link_t.exitcase = True + block.recloseblock(link_f, link_t) + + def go_to_dispatcher_if(self, block, v_finished_flag): + self.go_to_if(block, self.graph.returnblock, v_finished_flag) + + def insert_merge_points(self): + for block in self.mergepoint_set: + self.insert_merge(block) + def insert_merge(self, block): reds, greens = self.sort_by_color(block.inputargs) nextblock = self.naive_split_block(block, 0) @@ -246,15 +290,15 @@ self.genop(block, 'save_locals', reds) mp = self.mergepointfamily.add() c_mp = inputconst(lltype.Void, mp) - v_finished_flag = self.genop(block, 'merge_point', + if self.global_merge_points: + self.genop(block, 'save_greens', greens) + prefix = 'global_' + else: + prefix = '' + v_finished_flag = self.genop(block, '%smerge_point' % (prefix,), [self.c_mpfamily, c_mp] + greens, resulttype = lltype.Bool) - block.exitswitch = v_finished_flag - [link_f] = block.exits - link_t = Link([self.c_dummy], self.graph.returnblock) - link_f.exitcase = False - link_t.exitcase = True - block.recloseblock(link_f, link_t) + self.go_to_dispatcher_if(block, v_finished_flag) restoreops = [] mapping = {} @@ -269,10 +313,26 @@ SSA_to_SSI({block : True, # reachable from outside nextblock: False}, self.hannotator) + if self.global_merge_points: + N = self.get_resume_point(nextblock) + self.mergepointfamily.resumepoint_after_mergepoint[mp] = N + def insert_dispatcher(self): - if self.resumepoints: + if self.global_merge_points or self.resumepoints: block = self.before_return_block() - v_switchcase = self.genop(block, 'dispatch_next', [], + self.genop(block, 'dispatch_next', []) + if self.global_merge_points: + block = self.before_return_block() + entryblock = self.before_start_block() + v_rp = self.genop(entryblock, 'getresumepoint', [], + resulttype = lltype.Signed) + c_zero = inputconst(lltype.Signed, 0) + v_abnormal_entry = self.genop(entryblock, 'int_ge', + [v_rp, c_zero], + resulttype = lltype.Bool) + self.go_to_if(entryblock, block, v_abnormal_entry) + + v_switchcase = self.genop(block, 'getresumepoint', [], resulttype = lltype.Signed) block.exitswitch = v_switchcase defaultlink = block.exits[0] @@ -297,11 +357,7 @@ self.genop(block, 'save_return', []) def insert_enter_graph(self): - entryblock = self.new_block_before(self.graph.startblock) - entryblock.isstartblock = True - self.graph.startblock.isstartblock = False - self.graph.startblock = entryblock - + entryblock = self.before_start_block() self.genop(entryblock, 'enter_graph', [self.c_mpfamily]) def insert_leave_graph(self): @@ -363,6 +419,11 @@ def make_call(self, block, op, save_locals_vars, color='red'): self.genop(block, 'save_locals', save_locals_vars) targets = dict(self.graphs_from(op)) + for tsgraph in targets.values(): + if self.graph_global_mps(tsgraph): + # make sure jitstate.resumepoint is set to zero + self.genop(block, 'resetresumepoint', []) + break if len(targets) == 1: [tsgraph] = targets.values() c_tsgraph = inputconst(lltype.Void, tsgraph) @@ -475,5 +536,53 @@ link.args = [] link.target = self.get_resume_point_link(nextblock).target - self.insert_merge(nextblock) # to merge some of the possibly many - # return jitstates + self.mergepoint_set[nextblock] = True # to merge some of the possibly + # many return jitstates + + # __________ hints __________ + + def handle_hints(self): + for block in list(self.graph.iterblocks()): + for i in range(len(block.operations)-1, -1, -1): + op = block.operations[i] + if op.opname == 'hint': + hints = op.args[1].value + for key, value in hints.items(): + if value == True: + methname = 'handle_%s_hint' % (key,) + if hasattr(self, methname): + handler = getattr(self, methname) + break + else: + handler = self.handle_default_hint + handler(block, i) + + def handle_default_hint(self, block, i): + # just discard the hint by default + op = block.operations[i] + newop = SpaceOperation('same_as', [op.args[0]], op.result) + block.operations[i] = newop + + def handle_forget_hint(self, block, i): + # a hint for testing only + op = block.operations[i] + assert self.hannotator.binding(op.result).is_green() + assert not self.hannotator.binding(op.args[0]).is_green() + newop = SpaceOperation('revealconst', [op.args[0]], op.result) + block.operations[i] = newop + + def handle_promote_hint(self, block, i): + op = block.operations[i] + v_promote = op.args[0] + newop = SpaceOperation('revealconst', [v_promote], op.result) + block.operations[i] = newop + + link = support.split_block_with_keepalive(block, i, + annotator=self.hannotator) + nextblock = link.target + + reds, greens = self.sort_by_color(link.args) + self.genop(block, 'save_locals', reds) + v_finished_flag = self.genop(block, 'promote', [v_promote], + resulttype = lltype.Bool) + self.go_to_dispatcher_if(block, v_finished_flag) Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Thu Sep 28 20:10:20 2006 @@ -347,6 +347,7 @@ return annmodel.SomePtr(F) def specialize_call(self, hop): + hop.exception_cannot_occur() return hop.args_r[1].get_unique_llfn() # ____________________________________________________________ @@ -372,6 +373,7 @@ def specialize_call(self, hop): v_arg = hop.inputarg(hop.args_r[1], arg=1) assert isinstance(v_arg.concretetype, lltype.Ptr) + hop.exception_cannot_occur() return hop.genop('cast_pointer', [v_arg], resulttype = hop.r_result.lowleveltype) @@ -391,6 +393,7 @@ def specialize_call(self, hop): v_arg = hop.inputarg(hop.args_r[1], arg=1) assert isinstance(v_arg.concretetype, lltype.Ptr) + hop.exception_cannot_occur() return hop.genop('cast_pointer', [v_arg], resulttype = hop.r_result.lowleveltype) @@ -409,11 +412,7 @@ ## s_Instance, r_Instance = pol.annhelper.s_r_instanceof(s_Class.const) ## return annmodel.SomePtr(r_Instance.lowleveltype) -## def specialize_call(self, hop): -## v_arg = hop.inputarg(hop.args_r[1], arg=1) -## assert isinstance(v_arg.concretetype, lltype.Ptr) -## return hop.genop('cast_pointer', [v_arg], -## resulttype = hop.r_result.lowleveltype) +## ... # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Sep 28 20:10:20 2006 @@ -27,6 +27,10 @@ extra = '' return '' % (type_name(etype), extra) +class LLFatalError(Exception): + def __str__(self): + return ': '.join([str(x) for x in self.args]) + def type_name(etype): if isinstance(lltype.typeOf(etype), lltype.Ptr): return ''.join(etype.name).rstrip('\x00') @@ -442,6 +446,14 @@ # do nothing, this is useful in compiled code pass + def op_debug_fatalerror(self, ll_msg, ll_exc=None): + msg = ''.join(ll_msg.chars) + if ll_exc is None: + raise LLFatalError(msg) + else: + ll_exc_type = lltype.cast_pointer(rclass.OBJECTPTR, ll_exc).typeptr + raise LLFatalError(msg, LLException(ll_exc_type, ll_exc)) + def op_keepalive(self, value): pass Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Thu Sep 28 20:10:20 2006 @@ -394,6 +394,7 @@ 'debug_pdb': LLOp(), 'debug_log_exc': LLOp(), 'debug_assert': LLOp(canfold=True), + 'debug_fatalerror': LLOp(), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/tool/sourcetools.py ============================================================================== --- pypy/dist/pypy/tool/sourcetools.py (original) +++ pypy/dist/pypy/tool/sourcetools.py Thu Sep 28 20:10:20 2006 @@ -109,6 +109,8 @@ src = inspect.getsource(object) except IOError: return None + except IndentationError: + return None if hasattr(name, "__sourceargs__"): return src % name.__sourceargs__ return src From arigo at codespeak.net Thu Sep 28 20:10:46 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Sep 2006 20:10:46 +0200 (CEST) Subject: [pypy-svn] r32716 - pypy/branch/jit-promotion Message-ID: <20060928181046.6726710070@code0.codespeak.net> Author: arigo Date: Thu Sep 28 20:10:45 2006 New Revision: 32716 Removed: pypy/branch/jit-promotion/ Log: Kill merged branch. From cfbolz at codespeak.net Fri Sep 29 11:08:08 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 11:08:08 +0200 (CEST) Subject: [pypy-svn] r32728 - pypy/branch/config-in-more-places/pypy/config/test Message-ID: <20060929090808.0E50D10036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 11:08:07 2006 New Revision: 32728 Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py pypy/branch/config-in-more-places/pypy/config/test/test_pypyoption.py Log: oops. update tests to comply with the fact that you need a doc for OptionDescriptions too. Modified: pypy/branch/config-in-more-places/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_config.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_config.py Fri Sep 29 11:08:07 2006 @@ -13,9 +13,9 @@ wantref_option = BoolOption('wantref', 'Test requires', default=False, requires=[('gc.name', 'ref')]) - gcgroup = OptionDescription('gc', [gcoption, gcdummy, floatoption]) - descr = OptionDescription('pypy', [gcgroup, booloption, objspaceoption, - wantref_option, intoption]) + gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) + descr = OptionDescription('pypy', '', [gcgroup, booloption, objspaceoption, + wantref_option, intoption]) return descr def test_base_config(): @@ -57,8 +57,8 @@ from pypy.translator.interactive import Translation gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') - gcgroup = OptionDescription('gc', [gcoption]) - descr = OptionDescription('pypy', [gcgroup]) + gcgroup = OptionDescription('gc', '', [gcoption]) + descr = OptionDescription('pypy', '', [gcgroup]) config = Config(descr) def f(x): @@ -102,8 +102,8 @@ def test_to_optparse(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref', cmdline='--gc -g') - gcgroup = OptionDescription('gc', [gcoption]) - descr = OptionDescription('pypy', [gcgroup]) + gcgroup = OptionDescription('gc', '', [gcoption]) + descr = OptionDescription('pypy', '', [gcgroup]) config = Config(descr) parser = to_optparse(config, ['gc.name']) @@ -122,7 +122,7 @@ intoption = IntOption('int', 'Int option test', cmdline='--int -i') floatoption = FloatOption('float', 'Float option test', cmdline='--float -f') - descr = OptionDescription('test', [intoption, floatoption]) + descr = OptionDescription('test', '', [intoption, floatoption]) config = Config(descr) parser = to_optparse(config, ['int', 'float']) @@ -137,7 +137,7 @@ def test_to_optparse_bool(): booloption = BoolOption('bool', 'Boolean option test', default=False, cmdline='--bool -b') - descr = OptionDescription('test', [booloption]) + descr = OptionDescription('test', '', [booloption]) config = Config(descr) parser = to_optparse(config, ['bool']) @@ -154,7 +154,7 @@ "(options, args) = parser.parse_args(args=['-bfoo'])") def test_optparse_boolgroup(): - group = OptionDescription("test", [ + group = OptionDescription("test", '', [ BoolOption("smallint", "use tagged integers", default=False), BoolOption("strjoin", "use strings optimized for addition", @@ -164,7 +164,7 @@ BoolOption("strdict", "use dictionaries optimized for string keys", default=False), ], cmdline="--test") - descr = OptionDescription("all", [group]) + descr = OptionDescription("all", '', [group]) config = Config(descr) parser = to_optparse(config, ['test']) (options, args) = parser.parse_args( @@ -195,8 +195,8 @@ def test_optparse_path_options(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') - gcgroup = OptionDescription('gc', [gcoption]) - descr = OptionDescription('pypy', [gcgroup]) + gcgroup = OptionDescription('gc', '', [gcoption]) + descr = OptionDescription('pypy', '', [gcgroup]) config = Config(descr) parser = to_optparse(config, ['gc.name']) @@ -218,7 +218,7 @@ def test_none(): dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None) dummy2 = BoolOption('dummy2', 'doc dummy', default=False, cmdline='--dummy') - group = OptionDescription('group', [dummy1, dummy2]) + group = OptionDescription('group', '', [dummy1, dummy2]) config = Config(group) parser = to_optparse(config) @@ -226,9 +226,9 @@ "(options, args) = parser.parse_args(args=['--dummy1'])") def test_requirements_from_top(): - descr = OptionDescription("test", [ + descr = OptionDescription("test", '', [ BoolOption("toplevel", "", default=False), - OptionDescription("sub", [ + OptionDescription("sub", '', [ BoolOption("opt", "", default=False, requires=[("toplevel", True)]) ]) @@ -238,9 +238,9 @@ assert config.toplevel def test_requirements_for_choice(): - descr = OptionDescription("test", [ + descr = OptionDescription("test", '', [ BoolOption("toplevel", "", default=False), - OptionDescription("s", [ + OptionDescription("s", '', [ ChoiceOption("type_system", "", ["ll", "oo"], "ll"), ChoiceOption("backend", "", ["c", "llvm", "cli"], "llvm", Modified: pypy/branch/config-in-more-places/pypy/config/test/test_pypyoption.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/test/test_pypyoption.py (original) +++ pypy/branch/config-in-more-places/pypy/config/test/test_pypyoption.py Fri Sep 29 11:08:07 2006 @@ -16,3 +16,11 @@ assert not conf.objspace.std.withprebuiltint conf.objspace.std.withprebuiltint = True assert not conf.objspace.std.withsmallint + +def test_objspace_incopatibilities(): + conf = Config(pypy_optiondescription) + conf.objspace.name = "thunk" + assert not conf.objspace.geninterp + conf = Config(pypy_optiondescription) + conf.objspace.name = "logic" + assert not conf.objspace.geninterp From cfbolz at codespeak.net Fri Sep 29 11:09:05 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 11:09:05 +0200 (CEST) Subject: [pypy-svn] r32729 - pypy/branch/config-in-more-places/pypy/config Message-ID: <20060929090905.4C41F10036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 11:09:04 2006 New Revision: 32729 Modified: pypy/branch/config-in-more-places/pypy/config/pypyoption.py Log: add commandline arguments similar to the previous ones to the PyPy options. Modified: pypy/branch/config-in-more-places/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/config/pypyoption.py (original) +++ pypy/branch/config-in-more-places/pypy/config/pypyoption.py Fri Sep 29 11:09:04 2006 @@ -17,13 +17,19 @@ OptionDescription("objspace", "Object Space Option", [ ChoiceOption("name", "Object Space name", ["std", "flow", "logic", "thunk", "cpy"], "std", + requires = { + "thunk": [("objspace.geninterp", False)], + "logic": [("objspace.geninterp", False)], + }, cmdline='--objspace -o'), ChoiceOption("parser", "parser", - ["pypy", "cpython"], "pypy"), + ["pypy", "cpython"], "pypy", + cmdline='--parser'), ChoiceOption("compiler", "compiler", - ["cpython", "ast"], "ast"), + ["cpython", "ast"], "ast", + cmdline='--compiler'), BoolOption("nofaking", "disallow faking in the object space", default=False, @@ -31,10 +37,12 @@ ("objspace.uselibfile", True), ("objspace.usemodules.posix", True), ("objspace.usemodules.time", True), - ("objspace.usemodules.errno", True)]), + ("objspace.usemodules.errno", True)], + cmdline='--nofaking'), BoolOption("uselibfile", "use the applevel file implementation", - default=False), + default=False, + cmdline='--uselibfile'), OptionDescription("usemodules", "Which Modules should be used", [ BoolOption(modname, "use module %s" % (modname, ), From cfbolz at codespeak.net Fri Sep 29 11:10:07 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 11:10:07 +0200 (CEST) Subject: [pypy-svn] r32730 - in pypy/branch/config-in-more-places/pypy: bin tool Message-ID: <20060929091007.3D89910036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 11:10:05 2006 New Revision: 32730 Modified: pypy/branch/config-in-more-places/pypy/bin/py.py pypy/branch/config-in-more-places/pypy/tool/option.py Log: clean up option handling of py.py to use the config too. now you can start py.py and specify that you want strdicts, for example. Modified: pypy/branch/config-in-more-places/pypy/bin/py.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/bin/py.py (original) +++ pypy/branch/config-in-more-places/pypy/bin/py.py Fri Sep 29 11:10:05 2006 @@ -26,8 +26,9 @@ module_args = [] def get_main_options(): - options = option.get_standard_options() + config, parser = option.get_standard_options() + options = [] options.append(make_option( '-v', action='store_true', dest='verbose', help='show verbose interpreter-level traceback')) @@ -63,19 +64,19 @@ callback=runmodule_callback, type="string", help="library module to be run as a script (terminates option list)")) - + parser.add_options(options) - return options + return config, parser def main_(argv=None): - starttime = time.time() - args = option.process_options(get_main_options(), Options, argv[1:]) + starttime = time.time() + config, parser = get_main_options() + args = option.process_options(parser, Options, argv[1:]) if Options.verbose: error.RECORD_INTERPLEVEL_TRACEBACK = True # create the object space - config = option.make_config(Options) space = option.make_objspace(config) space._starttime = starttime Modified: pypy/branch/config-in-more-places/pypy/tool/option.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/tool/option.py (original) +++ pypy/branch/config-in-more-places/pypy/tool/option.py Fri Sep 29 11:10:05 2006 @@ -2,6 +2,8 @@ # XXX needs clean-up and reorganization. import os +from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.config import Config, to_optparse from py.compat import optparse make_option = optparse.make_option @@ -14,7 +16,7 @@ compiler = "ast" # "ast" uses interpreter/pyparser & interpreter/astcompiler.py # "cpython" uses cpython parser and cpython c-level compiler - usemodules = [] + usemodules = [] version = "2.5a" # "native" / "2.3" / "2.4" / "2.5a" def run_tb_server(option, opt, value, parser): @@ -23,48 +25,17 @@ def get_standard_options(): - options = [] - - def usemodules_callback(option, opt, value, parser): - parser.values.usemodules.append(value) - - options.append(make_option( - '-o', '--objspace', action="store", type="string", dest="objspace", - help="object space to run PyPy on.")) - options.append(make_option( - '--usemodules', action="callback", metavar='NAME', - callback=usemodules_callback, type="string", - help="(mixed) modules to use.")) - options.append(make_option( - '--oldstyle', action="store_true", dest="oldstyle", - help="enable oldstyle classes as default metaclass (std objspace only)")) - options.append(make_option( - '--uselibfile', action="store_true", dest="uselibfile", - help="enable our custom file implementation")) - options.append(make_option( - '--nofaking', action="store_true", dest="nofaking", - help="avoid faking of modules or objects")) - options.append(make_option( + config = Config(pypy_optiondescription) + parser = to_optparse(config) + parser.add_option( '-H', action="callback", callback=run_tb_server, - help="use web browser for traceback info")) - options.append(make_option( - '--compiler', action="store", type="string", dest="compiler", - default=None, - help="""select compiling approach. see pypy/doc/README.compiling""", - metavar="[ast|cpython]")) - options.append(make_option( - '--parser', action="store",type="string", dest="parser", default=None, - help="select the parser module to use", - metavar="[pypy|cpython]")) - - return options + help="use web browser for traceback info") + return config, parser -def process_options(optionlist, input_options, argv=None): +def process_options(op, input_options, argv=None): global Options Options = input_options - op = optparse.OptionParser() - op.add_options(optionlist) op.disable_interspersed_args() options, args = op.parse_args(argv, input_options) return args From cfbolz at codespeak.net Fri Sep 29 11:15:03 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 11:15:03 +0200 (CEST) Subject: [pypy-svn] r32731 - pypy/branch/config-in-more-places/pypy/translator/goal Message-ID: <20060929091503.E40B410036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 11:15:02 2006 New Revision: 32731 Removed: pypy/branch/config-in-more-places/pypy/translator/goal/targetthunkstandalone.py Log: thunkstandalone is no longer needed. you can now use -o thunk when translating with targetpypystandalone. From cfbolz at codespeak.net Fri Sep 29 11:28:32 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 11:28:32 +0200 (CEST) Subject: [pypy-svn] r32732 - pypy/branch/config-in-more-places/pypy/tool/build Message-ID: <20060929092832.5B58D10036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 11:28:31 2006 New Revision: 32732 Modified: pypy/branch/config-in-more-places/pypy/tool/build/systemoption.py Log: oops, another one hiding Modified: pypy/branch/config-in-more-places/pypy/tool/build/systemoption.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/tool/build/systemoption.py (original) +++ pypy/branch/config-in-more-places/pypy/tool/build/systemoption.py Fri Sep 29 11:28:31 2006 @@ -3,7 +3,7 @@ from pypy.config.config import ChoiceOption, to_optparse, Config import sys -system_optiondescription = OptionDescription('system', [ +system_optiondescription = OptionDescription('system', '', [ ChoiceOption('maxint', 'maximum int value in bytes (32/64)', ['32', '64'], sys.maxint, '-i --maxint'), ChoiceOption('byteorder', 'endianness, byte order (little/big)', From antocuni at codespeak.net Fri Sep 29 11:38:42 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Sep 2006 11:38:42 +0200 (CEST) Subject: [pypy-svn] r32733 - pypy/dist/pypy/translator/cli/test Message-ID: <20060929093842.99FA510036@code0.codespeak.net> Author: antocuni Date: Fri Sep 29 11:38:41 2006 New Revision: 32733 Modified: pypy/dist/pypy/translator/cli/test/test_op.py Log: This should be a more valuable test. Modified: pypy/dist/pypy/translator/cli/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_op.py (original) +++ pypy/dist/pypy/translator/cli/test/test_op.py Fri Sep 29 11:38:41 2006 @@ -60,7 +60,7 @@ def test_uint_neg(self): def fn(x): return -x - check(fn, [r_uint], [r_uint(42)]) + check(fn, [r_uint], [r_uint(sys.maxint+1)]) def test_op(): yield check, op_any_ge, [int, int], (42, 42) From arigo at codespeak.net Fri Sep 29 12:14:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Sep 2006 12:14:00 +0200 (CEST) Subject: [pypy-svn] r32734 - in pypy/dist/pypy: annotation objspace/std/test rpython Message-ID: <20060929101400.5883E10036@code0.codespeak.net> Author: arigo Date: Fri Sep 29 12:13:55 2006 New Revision: 32734 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/objspace/std/test/test_longobject.py pypy/dist/pypy/rpython/rarithmetic.py Log: A temporary hack to fix the longobject translatability bug. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Fri Sep 29 12:13:55 2006 @@ -272,7 +272,13 @@ if int1.is_immutable_constant() and int2.is_immutable_constant(): r = immutablevalue(operation(int1.const, int2.const)) else: - r = SomeBool() + # XXX VERY temporary hack + if (opname == 'ge' and int2.is_immutable_constant() and + int2.const == 0 and + not rarithmetic.signedtype(int1.knowntype)): + r = immutablevalue(True) + else: + r = SomeBool() knowntypedata = {} # XXX HACK HACK HACK # propagate nonneg information between the two arguments Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_longobject.py Fri Sep 29 12:13:55 2006 @@ -468,3 +468,16 @@ n = -sys.maxint-1 assert long(n) == n assert str(long(n)) == str(n) + + +class TestTranslatable: + + def test_args_from_rarith_int(self): + from pypy.rpython.test.test_llinterp import interpret + def fn(): + return (lobj.args_from_rarith_int(0), + lobj.args_from_rarith_int(17), + lobj.args_from_rarith_int(-17), + lobj.args_from_rarith_int(r_uint(0)), + lobj.args_from_rarith_int(r_uint(17))) + interpret(fn, []) Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Fri Sep 29 12:13:55 2006 @@ -95,6 +95,12 @@ return other_type return build_int(None, self_type.SIGNED and other_type.SIGNED, max(self_type.BITS, other_type.BITS)) +def signedtype(t): + if t in (bool, int, long): + return True + else: + return t.SIGNED + def normalizedinttype(t): if t is int: return int From cfbolz at codespeak.net Fri Sep 29 14:08:00 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 14:08:00 +0200 (CEST) Subject: [pypy-svn] r32735 - pypy/branch/config-in-more-places/pypy/translator/goal Message-ID: <20060929120800.6C44410036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 14:07:54 2006 New Revision: 32735 Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Log: expose the --thread option again (which I think is equivalent to --usemodules=thread, but anyway) Modified: pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/config-in-more-places/pypy/translator/goal/targetpypystandalone.py Fri Sep 29 14:07:54 2006 @@ -71,25 +71,20 @@ take_options = True -#def opt_parser(): -# import py -# defl = {'thread': False, 'usemodules': ''} -# parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", -# add_help_option=False) -# parser.set_defaults(**defl) -# parser.add_option("--thread", action="store_true", dest="thread", -# help="enable threading") -# parser.add_option("--usemodules", action="store", type="string", -# dest="usemodules", help=("list of mixed modules to " -# "include, comma-separated")) -# return parser - -def print_help(): +def opt_parser_config(): + parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", + add_help_option=False) + parser.set_defaults(thread=False) + parser.add_option("--thread", action="store_true", dest="thread", + help="enable threading") config = Config(pypy_optiondescription) opt_parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", add_help_option=False) - to_optparse(config, parser=opt_parser) - opt_parser.print_help() + to_optparse(config, parser=parser) + return config, parser + +def print_help(): + opt_parser_config()[1].print_help() def call_finish(space): space.finish() @@ -103,16 +98,10 @@ driver.exe_name = 'pypy-%(backend)s' options = driver.options - config = Config(pypy_optiondescription) - opt_parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", - add_help_option=False) - to_optparse(config, parser=opt_parser) - + config, opt_parser = opt_parser_config() tgt_options, _ = opt_parser.parse_args(args) - translate.log_options(tgt_options, "target PyPy options in effect") - translate.log_config(config, "PyPy config object") # expose the following variables to ease debugging global space, entry_point @@ -124,9 +113,22 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr + if tgt_options.thread: + config.objspace.usemodules.thread = True + elif config.objspace.usemodules.thread: + tgt_options.thread = True + + if options.stackless: + config.objspace.usemodules._stackless = True + elif config.objspace.usemodules._stackless: + options.stackless = True + config.objspace.nofaking = True config.objspace.compiler = "ast" config.translating = True + + translate.log_options(tgt_options, "target PyPy options in effect") + translate.log_config(config, "PyPy config object") space = make_objspace(config) From cfbolz at codespeak.net Fri Sep 29 14:16:06 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 14:16:06 +0200 (CEST) Subject: [pypy-svn] r32737 - pypy/dist/pypy/objspace/std Message-ID: <20060929121606.F215510036@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 14:16:06 2006 New Revision: 32737 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: make binary bitwise operations of longs marginally faster. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Fri Sep 29 14:16:06 2006 @@ -1629,6 +1629,7 @@ if negz == 0: return z return invert__Long(space, z) +_bitwise._annspecialcase_ = "specialize:arg(2)" def _AsLong(v): """ From antocuni at codespeak.net Fri Sep 29 15:18:32 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Sep 2006 15:18:32 +0200 (CEST) Subject: [pypy-svn] r32739 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20060929131832.322F010036@code0.codespeak.net> Author: antocuni Date: Fri Sep 29 15:18:31 2006 New Revision: 32739 Modified: pypy/dist/pypy/translator/cli/database.py pypy/dist/pypy/translator/cli/test/compile.py Log: Added support for lazy-initialized constants. Tests seem to pass, not sure it's completely bug-free. Modified: pypy/dist/pypy/translator/cli/database.py ============================================================================== --- pypy/dist/pypy/translator/cli/database.py (original) +++ pypy/dist/pypy/translator/cli/database.py Fri Sep 29 15:18:31 2006 @@ -23,6 +23,7 @@ DEBUG_CONST_INIT = False DEBUG_CONST_INIT_VERBOSE = False MAX_CONST_PER_STEP = 100 +LAZYNESS = True CONST_NAMESPACE = 'pypy.runtime' CONST_CLASS = 'Constants' @@ -205,35 +206,56 @@ assert not const.is_null() ilasm.field(const.name, const.get_type(), static=True) - # this point we have collected all constant we - # need. Instantiate&initialize them. - self.step = 0 - for i, const in enumerate(const_list): - if i % MAX_CONST_PER_STEP == 0: - self.__new_step(ilasm) - type_ = const.get_type() - const.instantiate(ilasm) - ilasm.store_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name) - - for i, const in enumerate(const_list): - if i % MAX_CONST_PER_STEP == 0: - self.__new_step(ilasm) - ilasm.stderr('CONST: initializing #%d' % i, DEBUG_CONST_INIT_VERBOSE) - type_ = const.get_type() - ilasm.load_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name) - const.init(ilasm) - self.__end_step(ilasm) # close the pending step - - ilasm.begin_function('.cctor', [], 'void', False, 'static', - 'specialname', 'rtspecialname', 'default') - ilasm.stderr('CONST: initialization starts', DEBUG_CONST_INIT) - for i in range(self.step): - ilasm.stderr('CONST: step %d of %d' % (i, self.step), DEBUG_CONST_INIT) - step_name = 'step%d' % i - ilasm.call('void %s.%s::%s()' % (CONST_NAMESPACE, CONST_CLASS, step_name)) - ilasm.stderr('CONST: initialization completed', DEBUG_CONST_INIT) - ilasm.ret() - ilasm.end_function() + if LAZYNESS: + for const in const_list: + getter_name = 'get_%s' % const.name + type_ = const.get_type() + ilasm.begin_function(getter_name, [], type_, False, 'static') + ilasm.load_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name) + # if it's already initialized, just return it + ilasm.opcode('dup') + ilasm.opcode('brfalse', 'initialize') + ilasm.opcode('ret') + # else, initialize! + ilasm.label('initialize') + ilasm.opcode('pop') # discard the null value we know is on the stack + const.instantiate(ilasm) + ilasm.opcode('dup') # two dups because const.init pops the value at the end + ilasm.opcode('dup') + ilasm.store_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name) + const.init(ilasm) + ilasm.opcode('ret') + ilasm.end_function() + else: + # this point we have collected all constant we + # need. Instantiate&initialize them. + self.step = 0 + for i, const in enumerate(const_list): + if i % MAX_CONST_PER_STEP == 0: + self.__new_step(ilasm) + type_ = const.get_type() + const.instantiate(ilasm) + ilasm.store_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name) + + for i, const in enumerate(const_list): + if i % MAX_CONST_PER_STEP == 0: + self.__new_step(ilasm) + ilasm.stderr('CONST: initializing #%d' % i, DEBUG_CONST_INIT_VERBOSE) + type_ = const.get_type() + ilasm.load_static_constant(type_, CONST_NAMESPACE, CONST_CLASS, const.name) + const.init(ilasm) + self.__end_step(ilasm) # close the pending step + + ilasm.begin_function('.cctor', [], 'void', False, 'static', + 'specialname', 'rtspecialname', 'default') + ilasm.stderr('CONST: initialization starts', DEBUG_CONST_INIT) + for i in range(self.step): + ilasm.stderr('CONST: step %d of %d' % (i, self.step), DEBUG_CONST_INIT) + step_name = 'step%d' % i + ilasm.call('void %s.%s::%s()' % (CONST_NAMESPACE, CONST_CLASS, step_name)) + ilasm.stderr('CONST: initialization completed', DEBUG_CONST_INIT) + ilasm.ret() + ilasm.end_function() ilasm.end_class() ilasm.end_namespace() @@ -347,9 +369,14 @@ Load the constant onto the stack. """ cts = CTS(self.db) - full_name = '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, self.name) cts_static_type = self.get_type() - ilasm.opcode('ldsfld %s %s' % (cts_static_type, full_name)) + if LAZYNESS: + getter_name = '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, 'get_%s' % self.name) + ilasm.call('%s %s()' % (cts_static_type, getter_name)) + else: + full_name = '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, self.name) + ilasm.opcode('ldsfld %s %s' % (cts_static_type, full_name)) + if cts_static_type != cts.lltype_to_cts(EXPECTED_TYPE): ilasm.opcode('castclass', cts.lltype_to_cts(EXPECTED_TYPE, include_class=False)) Modified: pypy/dist/pypy/translator/cli/test/compile.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/compile.py (original) +++ pypy/dist/pypy/translator/cli/test/compile.py Fri Sep 29 15:18:31 2006 @@ -31,12 +31,13 @@ def foo(a, b): pass +mylist = [1,2,3] + def bar(x, y): if x: - return 1 + return mylist else: - return None - + return [] f = compile_function(bar, [int, int]) From arigo at codespeak.net Fri Sep 29 15:23:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Sep 2006 15:23:02 +0200 (CEST) Subject: [pypy-svn] r32740 - in pypy/dist/pypy/tool/algo: . test Message-ID: <20060929132302.3374F10036@code0.codespeak.net> Author: arigo Date: Fri Sep 29 15:23:00 2006 New Revision: 32740 Modified: pypy/dist/pypy/tool/algo/sparsemat.py pypy/dist/pypy/tool/algo/test/test_sparsemat.py Log: Bug bug! The code was carefully picking the *worst* possible choice among the possible operations at every step of the algorithm. It leads to numerical instability. A largish example shows this. Modified: pypy/dist/pypy/tool/algo/sparsemat.py ============================================================================== --- pypy/dist/pypy/tool/algo/sparsemat.py (original) +++ pypy/dist/pypy/tool/algo/sparsemat.py Fri Sep 29 15:23:00 2006 @@ -1,6 +1,6 @@ from __future__ import division -EPSILON = 1E-6 +EPSILON = 1E-12 class SparseMatrix: @@ -42,17 +42,17 @@ currentcolumn = columns[ncol] lst = [(abs(a), i) for (i, a) in currentcolumn.items() if i in lines_left] - _, nrow = min(lst) # ValueError -> no solution + _, nrow = max(lst) # ValueError -> no solution nrows.append(nrow) del lines_left[nrow] line1 = lines[nrow] - mina = line1[ncol] + maxa = line1[ncol] for _, i in lst: if i != nrow: line2 = lines[i] a = line2.pop(ncol) #del currentcolumn[i] -- but currentcolumn no longer used - factor = a / mina + factor = a / maxa vector[i] -= factor*vector[nrow] for col in line1: if col > ncol: @@ -60,7 +60,8 @@ if abs(value) > EPSILON: line2[col] = columns[col][i] = value else: - del line2[col] + if col in line2: + del line2[col] del columns[col][i] solution = [None] * len(vector) for i in range(len(vector)-1, -1, -1): Modified: pypy/dist/pypy/tool/algo/test/test_sparsemat.py ============================================================================== --- pypy/dist/pypy/tool/algo/test/test_sparsemat.py (original) +++ pypy/dist/pypy/tool/algo/test/test_sparsemat.py Fri Sep 29 15:23:00 2006 @@ -21,3 +21,911 @@ M[2,1] = M[2,3] = -0.5 res = M.solve([6, 3, 6, 0]) assert res == [14, 8, 10, 0] + +def test_big_example(): + M = SparseMatrix(754) + M.lines = [ + {0: 1, 1: -0.5, 752: -0.5}, + {1: 1, 2: -0.5, 4: -0.5}, + {2: 1, 3: -1.0}, + {3: 1}, + {4: 1, 5: -0.5, 750: -0.5}, + {5: 1, 6: -0.5, 7: -0.5}, + {3: -1.0, 6: 1}, + {8: -0.5, 748: -0.5, 7: 1}, + {8: 1, 9: -0.5, 10: -0.5}, + {9: 1, 3: -1.0}, + {10: 1, 11: -0.5, 747: -0.5}, + {11: 1, 12: -1.0}, + {12: 1, 13: -1.0}, + {745: -0.5, 13: 1, 14: -0.5}, + {16: -0.5, 14: 1, 15: -0.5}, + {3: -1.0, 15: 1}, + {16: 1, 17: -0.5, 744: -0.5}, + {17: 1, 18: -1.0}, + {576: -0.5, 18: 1, 19: -0.5}, + {19: 1, 20: -0.5, 574: -0.5}, + {20: 1, 21: -0.5, 22: -0.5}, + {3: -1.0, 21: 1}, + {573: -0.5, 22: 1, 23: -0.5}, + {24: -1.0, 23: 1}, + {24: 1, 25: -1.0}, + {25: 1, 26: -0.5, 571: -0.5}, + {26: 1, 27: -0.5, 28: -0.5}, + {3: -1.0, 27: 1}, + {570: -0.5, 28: 1, 29: -0.5}, + {29: 1, 30: -1.0}, + {567: -0.5, 30: 1, 31: -0.5}, + {32: -0.5, 565: -0.5, 31: 1}, + {32: 1, 33: -0.5, 34: -0.5}, + {33: 1, 3: -1.0}, + {34: 1, 35: -0.5, 564: -0.5}, + {35: 1, 36: -1.0}, + {563: -0.5, 36: 1, 37: -0.5}, + {561: -0.5, 37: 1, 38: -0.5}, + {40: -0.5, 38: 1, 39: -0.5}, + {3: -1.0, 39: 1}, + {40: 1, 41: -0.5, 560: -0.5}, + {41: 1, 42: -1.0}, + {42: 1, 43: -0.5, 559: -0.5}, + {43: 1, 44: -1.0}, + {44: 1, 45: -0.5, 557: -0.5}, + {45: 1, 46: -0.29999999999999999, 47: -0.69999999999999996}, + {3: -1.0, 46: 1}, + {48: -0.5, 555: -0.5, 47: 1}, + {48: 1, 49: -0.29999999999999999, 50: -0.69999999999999996}, + {49: 1, 3: -1.0}, + {553: -0.5, 50: 1, 51: -0.5}, + {51: 1, 52: -0.29999999999999999, 53: -0.69999999999999996}, + {3: -1.0, 52: 1}, + {53: 1, 54: -0.5, 551: -0.5}, + {56: -0.69999999999999996, 54: 1, 55: -0.29999999999999999}, + {3: -1.0, 55: 1}, + {56: 1, 57: -0.5, 550: -0.5}, + {57: 1, 58: -1.0}, + {58: 1, 59: -0.29999999999999999, 63: -0.69999999999999996}, + {59: 1, 60: -0.5, 61: -0.5}, + {3: -1.0, 60: 1}, + {61: 1, 62: -1.0}, + {62: 1}, + {64: -0.5, 548: -0.5, 63: 1}, + {64: 1, 65: -0.29999999999999999, 66: -0.69999999999999996}, + {65: 1, 3: -1.0}, + {66: 1, 67: -0.5, 546: -0.5}, + {67: 1, 68: -0.29999999999999999, 69: -0.69999999999999996}, + {3: -1.0, 68: 1}, + {544: -0.5, 69: 1, 70: -0.5}, + {72: -0.69999999999999996, 70: 1, 71: -0.29999999999999999}, + {3: -1.0, 71: 1}, + {72: 1, 73: -0.5, 542: -0.5}, + {73: 1, 74: -0.29999999999999999, 75: -0.69999999999999996}, + {74: 1, 3: -1.0}, + {540: -0.5, 75: 1, 76: -0.5}, + {76: 1, 77: -0.29999999999999999, 78: -0.69999999999999996}, + {3: -1.0, 77: 1}, + {538: -0.5, 78: 1, 79: -0.5}, + {80: -0.29999999999999999, 81: -0.69999999999999996, 79: 1}, + {80: 1, 3: -1.0}, + {81: 1, 82: -0.5, 537: -0.5}, + {82: 1, 83: -1.0}, + {522: -0.5, 83: 1, 84: -0.5}, + {520: -0.5, 84: 1, 85: -0.5}, + {85: 1, 86: -0.29999999999999999, 87: -0.69999999999999996}, + {3: -1.0, 86: 1}, + {88: -0.5, 518: -0.5, 87: 1}, + {88: 1, 89: -0.29999999999999999, 90: -0.69999999999999996}, + {89: 1, 3: -1.0}, + {90: 1, 91: -0.5, 516: -0.5}, + {91: 1, 92: -0.29999999999999999, 93: -0.69999999999999996}, + {3: -1.0, 92: 1}, + {514: -0.5, 93: 1, 94: -0.5}, + {96: -0.69999999999999996, 94: 1, 95: -0.29999999999999999}, + {3: -1.0, 95: 1}, + {96: 1, 97: -0.5, 512: -0.5}, + {97: 1, 98: -0.29999999999999999, 99: -0.69999999999999996}, + {98: 1, 3: -1.0}, + {99: 1, 100: -0.5, 510: -0.5}, + {100: 1, 101: -0.29999999999999999, 102: -0.69999999999999996}, + {3: -1.0, 101: 1}, + {508: -0.5, 102: 1, 103: -0.5}, + {104: -0.29999999999999999, 105: -0.69999999999999996, 103: 1}, + {104: 1, 3: -1.0}, + {105: 1, 106: -0.5, 506: -0.5}, + {106: 1, 107: -0.29999999999999999, 108: -0.69999999999999996}, + {3: -1.0, 107: 1}, + {504: -0.5, 108: 1, 109: -0.5}, + {109: 1, 110: -0.29999999999999999, 111: -0.69999999999999996}, + {3: -1.0, 110: 1}, + {112: -0.5, 502: -0.5, 111: 1}, + {112: 1, 113: -0.29999999999999999, 114: -0.69999999999999996}, + {113: 1, 3: -1.0}, + {114: 1, 115: -0.5, 500: -0.5}, + {115: 1, 116: -0.29999999999999999, 117: -0.69999999999999996}, + {3: -1.0, 116: 1}, + {498: -0.5, 117: 1, 118: -0.5}, + {120: -0.69999999999999996, 118: 1, 119: -0.29999999999999999}, + {3: -1.0, 119: 1}, + {120: 1, 121: -0.5, 496: -0.5}, + {121: 1, 122: -0.29999999999999999, 123: -0.69999999999999996}, + {122: 1, 3: -1.0}, + {123: 1, 124: -0.5, 494: -0.5}, + {124: 1, 125: -0.29999999999999999, 126: -0.69999999999999996}, + {3: -1.0, 125: 1}, + {492: -0.5, 126: 1, 127: -0.5}, + {128: -0.29999999999999999, 129: -0.69999999999999996, 127: 1}, + {128: 1, 3: -1.0}, + {129: 1, 130: -0.5, 490: -0.5}, + {130: 1, 131: -0.29999999999999999, 132: -0.69999999999999996}, + {3: -1.0, 131: 1}, + {488: -0.5, 132: 1, 133: -0.5}, + {133: 1, 134: -0.29999999999999999, 135: -0.69999999999999996}, + {3: -1.0, 134: 1}, + {136: -0.5, 486: -0.5, 135: 1}, + {136: 1, 137: -0.29999999999999999, 138: -0.69999999999999996}, + {137: 1, 3: -1.0}, + {138: 1, 139: -0.5, 484: -0.5}, + {139: 1, 140: -0.29999999999999999, 141: -0.69999999999999996}, + {3: -1.0, 140: 1}, + {483: -0.5, 141: 1, 142: -0.5}, + {142: 1, 143: -1.0}, + {144: -0.5, 460: -0.5, 143: 1}, + {144: 1, 145: -0.5, 481: -0.5}, + {145: 1, 146: -0.29999999999999999, 147: -0.69999999999999996}, + {146: 1, 3: -1.0}, + {147: 1, 148: -0.5, 479: -0.5}, + {148: 1, 149: -0.29999999999999999, 150: -0.69999999999999996}, + {3: -1.0, 149: 1}, + {477: -0.5, 150: 1, 151: -0.5}, + {152: -0.29999999999999999, 153: -0.69999999999999996, 151: 1}, + {152: 1, 3: -1.0}, + {153: 1, 154: -0.5, 476: -0.5}, + {154: 1, 155: -1.0}, + {460: -0.5, 155: 1, 156: -0.5}, + {458: -0.5, 156: 1, 157: -0.5}, + {157: 1, 158: -0.29999999999999999, 159: -0.69999999999999996}, + {3: -1.0, 158: 1}, + {160: -0.5, 456: -0.5, 159: 1}, + {160: 1, 161: -0.29999999999999999, 162: -0.69999999999999996}, + {161: 1, 3: -1.0}, + {162: 1, 163: -0.5, 454: -0.5}, + {163: 1, 164: -0.29999999999999999, 165: -0.69999999999999996}, + {3: -1.0, 164: 1}, + {452: -0.5, 165: 1, 166: -0.5}, + {168: -0.69999999999999996, 166: 1, 167: -0.29999999999999999}, + {3: -1.0, 167: 1}, + {168: 1, 169: -0.5, 451: -0.5}, + {169: 1, 170: -1.0}, + {170: 1, 171: -0.5, 435: -0.5}, + {433: -0.5, 171: 1, 172: -0.5}, + {172: 1, 173: -0.29999999999999999, 174: -0.69999999999999996}, + {3: -1.0, 173: 1}, + {431: -0.5, 174: 1, 175: -0.5}, + {176: -0.29999999999999999, 177: -0.69999999999999996, 175: 1}, + {176: 1, 3: -1.0}, + {177: 1, 178: -0.5, 429: -0.5}, + {178: 1, 179: -0.29999999999999999, 180: -0.69999999999999996}, + {3: -1.0, 179: 1}, + {428: -0.5, 180: 1, 181: -0.5}, + {181: 1, 182: -1.0}, + {204: -0.5, 182: 1, 183: -0.5}, + {184: -0.5, 202: -0.5, 183: 1}, + {184: 1, 185: -0.29999999999999999, 186: -0.69999999999999996}, + {185: 1, 3: -1.0}, + {200: -0.5, 186: 1, 187: -0.5}, + {187: 1, 188: -0.29999999999999999, 189: -0.69999999999999996}, + {3: -1.0, 188: 1}, + {198: -0.5, 189: 1, 190: -0.5}, + {192: -0.69999999999999996, 190: 1, 191: -0.29999999999999999}, + {3: -1.0, 191: 1}, + {192: 1, 193: -0.5, 196: -0.5}, + {193: 1, 194: -0.29999999999999999, 195: -0.69999999999999996}, + {194: 1, 3: -1.0}, + {195: 1, 44: -1.0}, + {193: -0.5, 196: 1, 197: -0.5}, + {193: -1.0, 197: 1}, + {190: -0.5, 198: 1, 199: -0.5}, + {190: -1.0, 199: 1}, + {200: 1, 201: -0.5, 187: -0.5}, + {201: 1, 187: -1.0}, + {184: -0.5, 202: 1, 203: -0.5}, + {184: -1.0, 203: 1}, + {426: -0.5, 204: 1, 205: -0.5}, + {205: 1, 206: -0.29999999999999999, 207: -0.69999999999999996}, + {3: -1.0, 206: 1}, + {208: -0.5, 424: -0.5, 207: 1}, + {208: 1, 209: -0.29999999999999999, 210: -0.69999999999999996}, + {209: 1, 3: -1.0}, + {210: 1, 211: -0.5, 422: -0.5}, + {211: 1, 212: -0.29999999999999999, 213: -0.69999999999999996}, + {3: -1.0, 212: 1}, + {213: 1, 214: -0.5, 421: -0.5}, + {214: 1, 215: -1.0}, + {216: -0.5, 183: -0.5, 215: 1}, + {216: 1, 217: -0.5, 419: -0.5}, + {217: 1, 218: -0.29999999999999999, 219: -0.69999999999999996}, + {218: 1, 3: -1.0}, + {417: -0.5, 219: 1, 220: -0.5}, + {220: 1, 221: -0.29999999999999999, 222: -0.69999999999999996}, + {3: -1.0, 221: 1}, + {415: -0.5, 222: 1, 223: -0.5}, + {224: -0.29999999999999999, 225: -0.69999999999999996, 223: 1}, + {224: 1, 3: -1.0}, + {225: 1, 226: -0.5, 413: -0.5}, + {226: 1, 227: -0.29999999999999999, 228: -0.69999999999999996}, + {3: -1.0, 227: 1}, + {411: -0.5, 228: 1, 229: -0.5}, + {229: 1, 230: -0.29999999999999999, 231: -0.69999999999999996}, + {3: -1.0, 230: 1}, + {232: -0.5, 409: -0.5, 231: 1}, + {232: 1, 233: -0.29999999999999999, 234: -0.69999999999999996}, + {233: 1, 3: -1.0}, + {234: 1, 235: -0.5, 407: -0.5}, + {235: 1, 236: -0.29999999999999999, 237: -0.69999999999999996}, + {3: -1.0, 236: 1}, + {237: 1, 238: -0.5, 405: -0.5}, + {240: -0.69999999999999996, 238: 1, 239: -0.29999999999999999}, + {3: -1.0, 239: 1}, + {240: 1, 241: -0.5, 403: -0.5}, + {241: 1, 242: -0.29999999999999999, 243: -0.69999999999999996}, + {242: 1, 3: -1.0}, + {401: -0.5, 243: 1, 244: -0.5}, + {244: 1, 245: -0.29999999999999999, 246: -0.69999999999999996}, + {3: -1.0, 245: 1}, + {399: -0.5, 246: 1, 247: -0.5}, + {248: -0.29999999999999999, 249: -0.69999999999999996, 247: 1}, + {248: 1, 3: -1.0}, + {249: 1, 250: -0.5, 397: -0.5}, + {250: 1, 251: -0.29999999999999999, 252: -0.69999999999999996}, + {3: -1.0, 251: 1}, + {395: -0.5, 252: 1, 253: -0.5}, + {253: 1, 254: -0.29999999999999999, 255: -0.69999999999999996}, + {3: -1.0, 254: 1}, + {256: -0.5, 393: -0.5, 255: 1}, + {256: 1, 257: -0.29999999999999999, 258: -0.69999999999999996}, + {257: 1, 3: -1.0}, + {258: 1, 259: -0.5, 391: -0.5}, + {259: 1, 260: -0.29999999999999999, 261: -0.69999999999999996}, + {3: -1.0, 260: 1}, + {261: 1, 262: -0.5, 389: -0.5}, + {264: -0.69999999999999996, 262: 1, 263: -0.29999999999999999}, + {3: -1.0, 263: 1}, + {264: 1, 265: -0.5, 387: -0.5}, + {265: 1, 266: -0.29999999999999999, 267: -0.69999999999999996}, + {266: 1, 3: -1.0}, + {385: -0.5, 267: 1, 268: -0.5}, + {268: 1, 269: -0.29999999999999999, 270: -0.69999999999999996}, + {3: -1.0, 269: 1}, + {383: -0.5, 270: 1, 271: -0.5}, + {272: -0.29999999999999999, 273: -0.69999999999999996, 271: 1}, + {272: 1, 3: -1.0}, + {273: 1, 274: -0.5, 382: -0.5}, + {274: 1, 275: -1.0}, + {297: -0.5, 275: 1, 276: -0.5}, + {276: 1, 277: -0.5, 295: -0.5}, + {277: 1, 278: -0.29999999999999999, 279: -0.69999999999999996}, + {3: -1.0, 278: 1}, + {280: -0.5, 293: -0.5, 279: 1}, + {280: 1, 281: -0.29999999999999999, 282: -0.69999999999999996}, + {281: 1, 3: -1.0}, + {291: -0.5, 282: 1, 283: -0.5}, + {283: 1, 284: -0.29999999999999999, 285: -0.69999999999999996}, + {3: -1.0, 284: 1}, + {289: -0.5, 285: 1, 286: -0.5}, + {288: -0.69999999999999996, 286: 1, 287: -0.29999999999999999}, + {3: -1.0, 287: 1}, + {288: 1, 183: -1.0}, + {289: 1, 290: -0.5, 286: -0.5}, + {290: 1, 286: -1.0}, + {283: -0.5, 291: 1, 292: -0.5}, + {283: -1.0, 292: 1}, + {280: -0.5, 293: 1, 294: -0.5}, + {280: -1.0, 294: 1}, + {296: -0.5, 277: -0.5, 295: 1}, + {296: 1, 277: -1.0}, + {297: 1, 298: -0.5, 380: -0.5}, + {298: 1, 299: -0.29999999999999999, 300: -0.69999999999999996}, + {3: -1.0, 299: 1}, + {378: -0.5, 300: 1, 301: -0.5}, + {301: 1, 302: -0.29999999999999999, 303: -0.69999999999999996}, + {3: -1.0, 302: 1}, + {304: -0.5, 376: -0.5, 303: 1}, + {304: 1, 305: -0.29999999999999999, 306: -0.69999999999999996}, + {305: 1, 3: -1.0}, + {306: 1, 307: -0.5, 375: -0.5}, + {307: 1, 308: -1.0}, + {276: -0.5, 308: 1, 309: -0.5}, + {309: 1, 310: -0.5, 373: -0.5}, + {312: -0.69999999999999996, 310: 1, 311: -0.29999999999999999}, + {3: -1.0, 311: 1}, + {312: 1, 313: -0.5, 371: -0.5}, + {313: 1, 314: -0.29999999999999999, 315: -0.69999999999999996}, + {314: 1, 3: -1.0}, + {369: -0.5, 315: 1, 316: -0.5}, + {316: 1, 317: -0.29999999999999999, 318: -0.69999999999999996}, + {3: -1.0, 317: 1}, + {367: -0.5, 318: 1, 319: -0.5}, + {320: -0.29999999999999999, 321: -0.69999999999999996, 319: 1}, + {320: 1, 3: -1.0}, + {321: 1, 322: -0.5, 365: -0.5}, + {322: 1, 323: -0.29999999999999999, 324: -0.69999999999999996}, + {3: -1.0, 323: 1}, + {363: -0.5, 324: 1, 325: -0.5}, + {325: 1, 326: -0.29999999999999999, 327: -0.69999999999999996}, + {3: -1.0, 326: 1}, + {328: -0.5, 361: -0.5, 327: 1}, + {328: 1, 329: -0.29999999999999999, 330: -0.69999999999999996}, + {329: 1, 3: -1.0}, + {330: 1, 331: -0.5, 359: -0.5}, + {331: 1, 332: -0.29999999999999999, 333: -0.69999999999999996}, + {3: -1.0, 332: 1}, + {333: 1, 334: -0.5, 357: -0.5}, + {336: -0.69999999999999996, 334: 1, 335: -0.29999999999999999}, + {3: -1.0, 335: 1}, + {336: 1, 337: -0.5, 355: -0.5}, + {337: 1, 338: -0.29999999999999999, 339: -0.69999999999999996}, + {338: 1, 3: -1.0}, + {353: -0.5, 339: 1, 340: -0.5}, + {340: 1, 341: -0.29999999999999999, 342: -0.69999999999999996}, + {3: -1.0, 341: 1}, + {351: -0.5, 342: 1, 343: -0.5}, + {344: -0.29999999999999999, 345: -0.69999999999999996, 343: 1}, + {344: 1, 3: -1.0}, + {345: 1, 346: -0.5, 349: -0.5}, + {346: 1, 347: -0.29999999999999999, 348: -0.69999999999999996}, + {3: -1.0, 347: 1}, + {44: -1.0, 348: 1}, + {346: -0.5, 349: 1, 350: -0.5}, + {346: -1.0, 350: 1}, + {352: -0.5, 343: -0.5, 351: 1}, + {352: 1, 343: -1.0}, + {353: 1, 354: -0.5, 340: -0.5}, + {354: 1, 340: -1.0}, + {337: -0.5, 355: 1, 356: -0.5}, + {337: -1.0, 356: 1}, + {358: -0.5, 357: 1, 334: -0.5}, + {334: -1.0, 358: 1}, + {360: -0.5, 331: -0.5, 359: 1}, + {360: 1, 331: -1.0}, + {328: -0.5, 361: 1, 362: -0.5}, + {328: -1.0, 362: 1}, + {363: 1, 364: -0.5, 325: -0.5}, + {364: 1, 325: -1.0}, + {322: -0.5, 365: 1, 366: -0.5}, + {322: -1.0, 366: 1}, + {368: -0.5, 319: -0.5, 367: 1}, + {368: 1, 319: -1.0}, + {369: 1, 370: -0.5, 316: -0.5}, + {370: 1, 316: -1.0}, + {313: -0.5, 371: 1, 372: -0.5}, + {313: -1.0, 372: 1}, + {374: -0.5, 373: 1, 310: -0.5}, + {310: -1.0, 374: 1}, + {308: -1.0, 375: 1}, + {376: 1, 304: -0.5, 377: -0.5}, + {304: -1.0, 377: 1}, + {378: 1, 379: -0.5, 301: -0.5}, + {379: 1, 301: -1.0}, + {298: -0.5, 380: 1, 381: -0.5}, + {298: -1.0, 381: 1}, + {275: -1.0, 382: 1}, + {384: -0.5, 271: -0.5, 383: 1}, + {384: 1, 271: -1.0}, + {385: 1, 386: -0.5, 268: -0.5}, + {386: 1, 268: -1.0}, + {265: -0.5, 387: 1, 388: -0.5}, + {265: -1.0, 388: 1}, + {389: 1, 262: -0.5, 390: -0.5}, + {262: -1.0, 390: 1}, + {392: -0.5, 259: -0.5, 391: 1}, + {392: 1, 259: -1.0}, + {256: -0.5, 393: 1, 394: -0.5}, + {256: -1.0, 394: 1}, + {395: 1, 396: -0.5, 253: -0.5}, + {396: 1, 253: -1.0}, + {250: -0.5, 397: 1, 398: -0.5}, + {250: -1.0, 398: 1}, + {400: -0.5, 247: -0.5, 399: 1}, + {400: 1, 247: -1.0}, + {401: 1, 402: -0.5, 244: -0.5}, + {402: 1, 244: -1.0}, + {241: -0.5, 403: 1, 404: -0.5}, + {241: -1.0, 404: 1}, + {405: 1, 238: -0.5, 406: -0.5}, + {238: -1.0, 406: 1}, + {408: -0.5, 235: -0.5, 407: 1}, + {408: 1, 235: -1.0}, + {232: -0.5, 409: 1, 410: -0.5}, + {232: -1.0, 410: 1}, + {411: 1, 412: -0.5, 229: -0.5}, + {412: 1, 229: -1.0}, + {226: -0.5, 413: 1, 414: -0.5}, + {226: -1.0, 414: 1}, + {416: -0.5, 223: -0.5, 415: 1}, + {416: 1, 223: -1.0}, + {417: 1, 418: -0.5, 220: -0.5}, + {418: 1, 220: -1.0}, + {217: -0.5, 419: 1, 420: -0.5}, + {217: -1.0, 420: 1}, + {421: 1, 215: -1.0}, + {211: -0.5, 422: 1, 423: -0.5}, + {211: -1.0, 423: 1}, + {424: 1, 208: -0.5, 425: -0.5}, + {208: -1.0, 425: 1}, + {426: 1, 427: -0.5, 205: -0.5}, + {427: 1, 205: -1.0}, + {428: 1, 182: -1.0}, + {178: -0.5, 429: 1, 430: -0.5}, + {178: -1.0, 430: 1}, + {432: -0.5, 175: -0.5, 431: 1}, + {432: 1, 175: -1.0}, + {433: 1, 434: -0.5, 172: -0.5}, + {434: 1, 172: -1.0}, + {449: -0.5, 435: 1, 436: -0.5}, + {436: 1, 437: -0.29999999999999999, 438: -0.69999999999999996}, + {3: -1.0, 437: 1}, + {447: -0.5, 438: 1, 439: -0.5}, + {440: -0.29999999999999999, 441: -0.69999999999999996, 439: 1}, + {440: 1, 3: -1.0}, + {441: 1, 442: -0.5, 445: -0.5}, + {442: 1, 443: -0.29999999999999999, 444: -0.69999999999999996}, + {3: -1.0, 443: 1}, + {171: -1.0, 444: 1}, + {442: -0.5, 445: 1, 446: -0.5}, + {442: -1.0, 446: 1}, + {448: -0.5, 439: -0.5, 447: 1}, + {448: 1, 439: -1.0}, + {449: 1, 450: -0.5, 436: -0.5}, + {450: 1, 436: -1.0}, + {170: -1.0, 451: 1}, + {452: 1, 453: -0.5, 166: -0.5}, + {453: 1, 166: -1.0}, + {163: -0.5, 454: 1, 455: -0.5}, + {163: -1.0, 455: 1}, + {456: 1, 160: -0.5, 457: -0.5}, + {160: -1.0, 457: 1}, + {458: 1, 459: -0.5, 157: -0.5}, + {459: 1, 157: -1.0}, + {474: -0.5, 460: 1, 461: -0.5}, + {461: 1, 462: -0.29999999999999999, 463: -0.69999999999999996}, + {3: -1.0, 462: 1}, + {464: -0.5, 472: -0.5, 463: 1}, + {464: 1, 465: -0.29999999999999999, 466: -0.69999999999999996}, + {465: 1, 3: -1.0}, + {466: 1, 467: -0.5, 470: -0.5}, + {467: 1, 468: -0.29999999999999999, 469: -0.69999999999999996}, + {3: -1.0, 468: 1}, + {44: -1.0, 469: 1}, + {467: -0.5, 470: 1, 471: -0.5}, + {467: -1.0, 471: 1}, + {472: 1, 464: -0.5, 473: -0.5}, + {464: -1.0, 473: 1}, + {474: 1, 475: -0.5, 461: -0.5}, + {475: 1, 461: -1.0}, + {155: -1.0, 476: 1}, + {477: 1, 478: -0.5, 151: -0.5}, + {478: 1, 151: -1.0}, + {480: -0.5, 148: -0.5, 479: 1}, + {480: 1, 148: -1.0}, + {481: 1, 482: -0.5, 145: -0.5}, + {145: -1.0, 482: 1}, + {483: 1, 143: -1.0}, + {139: -0.5, 484: 1, 485: -0.5}, + {139: -1.0, 485: 1}, + {136: -0.5, 486: 1, 487: -0.5}, + {136: -1.0, 487: 1}, + {488: 1, 489: -0.5, 133: -0.5}, + {489: 1, 133: -1.0}, + {490: 1, 491: -0.5, 130: -0.5}, + {130: -1.0, 491: 1}, + {492: 1, 493: -0.5, 127: -0.5}, + {493: 1, 127: -1.0}, + {124: -0.5, 494: 1, 495: -0.5}, + {124: -1.0, 495: 1}, + {496: 1, 121: -0.5, 497: -0.5}, + {497: 1, 121: -1.0}, + {498: 1, 499: -0.5, 118: -0.5}, + {499: 1, 118: -1.0}, + {115: -0.5, 500: 1, 501: -0.5}, + {115: -1.0, 501: 1}, + {112: -0.5, 502: 1, 503: -0.5}, + {112: -1.0, 503: 1}, + {504: 1, 505: -0.5, 109: -0.5}, + {505: 1, 109: -1.0}, + {506: 1, 507: -0.5, 106: -0.5}, + {106: -1.0, 507: 1}, + {508: 1, 509: -0.5, 103: -0.5}, + {509: 1, 103: -1.0}, + {100: -0.5, 510: 1, 511: -0.5}, + {100: -1.0, 511: 1}, + {512: 1, 97: -0.5, 513: -0.5}, + {513: 1, 97: -1.0}, + {514: 1, 515: -0.5, 94: -0.5}, + {515: 1, 94: -1.0}, + {91: -0.5, 516: 1, 517: -0.5}, + {91: -1.0, 517: 1}, + {88: -0.5, 518: 1, 519: -0.5}, + {88: -1.0, 519: 1}, + {520: 1, 521: -0.5, 85: -0.5}, + {521: 1, 85: -1.0}, + {522: 1, 523: -0.5, 535: -0.5}, + {523: 1, 524: -0.29999999999999999, 525: -0.69999999999999996}, + {3: -1.0, 524: 1}, + {534: -0.5, 525: 1, 526: -0.5}, + {526: 1, 527: -1.0}, + {528: -0.69999999999999996, 59: -0.29999999999999999, 527: 1}, + {528: 1, 529: -0.5, 532: -0.5}, + {529: 1, 530: -0.29999999999999999, 531: -0.69999999999999996}, + {530: 1, 3: -1.0}, + {531: 1, 84: -1.0}, + {529: -0.5, 532: 1, 533: -0.5}, + {529: -1.0, 533: 1}, + {534: 1, 527: -1.0}, + {536: -0.5, 523: -0.5, 535: 1}, + {536: 1, 523: -1.0}, + {537: 1, 83: -1.0}, + {538: 1, 539: -0.5, 79: -0.5}, + {539: 1, 79: -1.0}, + {76: -0.5, 540: 1, 541: -0.5}, + {76: -1.0, 541: 1}, + {73: -0.5, 542: 1, 543: -0.5}, + {73: -1.0, 543: 1}, + {544: 1, 545: -0.5, 70: -0.5}, + {545: 1, 70: -1.0}, + {547: -0.5, 546: 1, 67: -0.5}, + {67: -1.0, 547: 1}, + {64: -0.5, 548: 1, 549: -0.5}, + {64: -1.0, 549: 1}, + {58: -1.0, 550: 1}, + {552: -0.5, 54: -0.5, 551: 1}, + {552: 1, 54: -1.0}, + {553: 1, 554: -0.5, 51: -0.5}, + {554: 1, 51: -1.0}, + {48: -0.5, 555: 1, 556: -0.5}, + {48: -1.0, 556: 1}, + {557: 1, 558: -0.5, 45: -0.5}, + {45: -1.0, 558: 1}, + {44: -1.0, 559: 1}, + {560: 1, 42: -1.0}, + {561: 1, 562: -0.5, 38: -0.5}, + {562: 1, 38: -1.0}, + {563: 1, 44: -1.0}, + {36: -1.0, 564: 1}, + {32: -0.5, 565: 1, 566: -0.5}, + {32: -1.0, 566: 1}, + {568: -0.5, 569: -0.5, 567: 1}, + {568: 1, 3: -1.0}, + {569: 1, 62: -1.0}, + {570: 1, 30: -1.0}, + {26: -0.5, 571: 1, 572: -0.5}, + {26: -1.0, 572: 1}, + {24: -1.0, 573: 1}, + {20: -0.5, 574: 1, 575: -0.5}, + {20: -1.0, 575: 1}, + {576: 1, 577: -0.5, 742: -0.5}, + {577: 1, 578: -0.5, 579: -0.5}, + {578: 1, 3: -1.0}, + {740: -0.5, 579: 1, 580: -0.5}, + {580: 1, 581: -0.5, 582: -0.5}, + {3: -1.0, 581: 1}, + {738: -0.5, 582: 1, 583: -0.5}, + {584: -0.5, 585: -0.5, 583: 1}, + {584: 1, 3: -1.0}, + {585: 1, 586: -0.5, 737: -0.5}, + {586: 1, 587: -1.0}, + {25: -0.5, 587: 1, 588: -0.5}, + {588: 1, 589: -0.5, 735: -0.5}, + {589: 1, 590: -0.5, 591: -0.5}, + {3: -1.0, 590: 1}, + {592: -0.5, 733: -0.5, 591: 1}, + {592: 1, 593: -0.5, 594: -0.5}, + {593: 1, 3: -1.0}, + {594: 1, 595: -0.5, 731: -0.5}, + {595: 1, 596: -0.5, 597: -0.5}, + {3: -1.0, 596: 1}, + {729: -0.5, 597: 1, 598: -0.5}, + {600: -0.5, 598: 1, 599: -0.5}, + {3: -1.0, 599: 1}, + {600: 1, 601: -0.5, 727: -0.5}, + {601: 1, 602: -0.5, 603: -0.5}, + {602: 1, 3: -1.0}, + {603: 1, 604: -0.5, 725: -0.5}, + {604: 1, 605: -0.5, 606: -0.5}, + {3: -1.0, 605: 1}, + {723: -0.5, 606: 1, 607: -0.5}, + {608: -0.5, 609: -0.5, 607: 1}, + {608: 1, 3: -1.0}, + {609: 1, 610: -0.5, 721: -0.5}, + {610: 1, 611: -0.5, 612: -0.5}, + {3: -1.0, 611: 1}, + {612: 1, 613: -0.5, 719: -0.5}, + {613: 1, 614: -0.5, 615: -0.5}, + {3: -1.0, 614: 1}, + {616: -0.5, 717: -0.5, 615: 1}, + {616: 1, 617: -0.5, 618: -0.5}, + {617: 1, 3: -1.0}, + {618: 1, 619: -0.5, 715: -0.5}, + {619: 1, 620: -0.5, 621: -0.5}, + {3: -1.0, 620: 1}, + {713: -0.5, 621: 1, 622: -0.5}, + {624: -0.5, 622: 1, 623: -0.5}, + {3: -1.0, 623: 1}, + {624: 1, 625: -0.5, 711: -0.5}, + {625: 1, 626: -0.5, 627: -0.5}, + {626: 1, 3: -1.0}, + {627: 1, 628: -0.5, 710: -0.5}, + {628: 1, 629: -1.0}, + {629: 1, 630: -0.5, 670: -0.5}, + {668: -0.5, 630: 1, 631: -0.5}, + {632: -0.5, 633: -0.5, 631: 1}, + {632: 1, 3: -1.0}, + {633: 1, 634: -0.5, 667: -0.5}, + {634: 1, 635: -1.0}, + {656: -0.5, 635: 1, 636: -0.5}, + {636: 1, 637: -0.5, 654: -0.5}, + {637: 1, 638: -0.5, 639: -0.5}, + {3: -1.0, 638: 1}, + {640: -0.5, 653: -0.5, 639: 1}, + {640: 1, 641: -1.0}, + {641: 1, 642: -0.5, 25: -0.5}, + {642: 1, 643: -0.5, 651: -0.5}, + {643: 1, 644: -0.5, 645: -0.5}, + {3: -1.0, 644: 1}, + {649: -0.5, 645: 1, 646: -0.5}, + {648: -0.5, 646: 1, 647: -0.5}, + {3: -1.0, 647: 1}, + {648: 1, 25: -1.0}, + {649: 1, 650: -0.5, 646: -0.5}, + {650: 1, 646: -1.0}, + {652: -0.5, 651: 1, 643: -0.5}, + {643: -1.0, 652: 1}, + {641: -1.0, 653: 1}, + {637: -0.5, 654: 1, 655: -0.5}, + {637: -1.0, 655: 1}, + {656: 1, 657: -0.5, 665: -0.5}, + {657: 1, 658: -0.5, 659: -0.5}, + {658: 1, 3: -1.0}, + {659: 1, 660: -0.5, 663: -0.5}, + {660: 1, 661: -0.5, 662: -0.5}, + {3: -1.0, 661: 1}, + {25: -1.0, 662: 1}, + {664: -0.5, 660: -0.5, 663: 1}, + {664: 1, 660: -1.0}, + {665: 1, 666: -0.5, 657: -0.5}, + {657: -1.0, 666: 1}, + {635: -1.0, 667: 1}, + {668: 1, 669: -0.5, 631: -0.5}, + {669: 1, 631: -1.0}, + {708: -0.5, 670: 1, 671: -0.5}, + {672: -0.5, 673: -0.5, 671: 1}, + {672: 1, 3: -1.0}, + {673: 1, 674: -0.5, 707: -0.5}, + {674: 1, 675: -1.0}, + {696: -0.5, 675: 1, 676: -0.5}, + {676: 1, 677: -0.5, 694: -0.5}, + {677: 1, 678: -0.5, 679: -0.5}, + {3: -1.0, 678: 1}, + {680: -0.5, 693: -0.5, 679: 1}, + {680: 1, 681: -1.0}, + {681: 1, 682: -0.5, 25: -0.5}, + {682: 1, 683: -0.5, 691: -0.5}, + {683: 1, 684: -0.5, 685: -0.5}, + {3: -1.0, 684: 1}, + {689: -0.5, 685: 1, 686: -0.5}, + {688: -0.5, 686: 1, 687: -0.5}, + {3: -1.0, 687: 1}, + {688: 1, 25: -1.0}, + {689: 1, 690: -0.5, 686: -0.5}, + {690: 1, 686: -1.0}, + {691: 1, 692: -0.5, 683: -0.5}, + {683: -1.0, 692: 1}, + {681: -1.0, 693: 1}, + {677: -0.5, 694: 1, 695: -0.5}, + {677: -1.0, 695: 1}, + {696: 1, 697: -0.5, 705: -0.5}, + {697: 1, 698: -0.5, 699: -0.5}, + {698: 1, 3: -1.0}, + {699: 1, 700: -0.5, 703: -0.5}, + {700: 1, 701: -0.5, 702: -0.5}, + {3: -1.0, 701: 1}, + {25: -1.0, 702: 1}, + {704: -0.5, 700: -0.5, 703: 1}, + {704: 1, 700: -1.0}, + {705: 1, 706: -0.5, 697: -0.5}, + {697: -1.0, 706: 1}, + {707: 1, 675: -1.0}, + {708: 1, 709: -0.5, 671: -0.5}, + {709: 1, 671: -1.0}, + {629: -1.0, 710: 1}, + {712: -0.5, 625: -0.5, 711: 1}, + {712: 1, 625: -1.0}, + {713: 1, 714: -0.5, 622: -0.5}, + {714: 1, 622: -1.0}, + {619: -0.5, 715: 1, 716: -0.5}, + {619: -1.0, 716: 1}, + {616: -0.5, 717: 1, 718: -0.5}, + {616: -1.0, 718: 1}, + {720: -0.5, 613: -0.5, 719: 1}, + {720: 1, 613: -1.0}, + {721: 1, 610: -0.5, 722: -0.5}, + {722: 1, 610: -1.0}, + {723: 1, 724: -0.5, 607: -0.5}, + {724: 1, 607: -1.0}, + {604: -0.5, 725: 1, 726: -0.5}, + {604: -1.0, 726: 1}, + {728: -0.5, 601: -0.5, 727: 1}, + {728: 1, 601: -1.0}, + {729: 1, 730: -0.5, 598: -0.5}, + {730: 1, 598: -1.0}, + {595: -0.5, 731: 1, 732: -0.5}, + {595: -1.0, 732: 1}, + {592: -0.5, 733: 1, 734: -0.5}, + {592: -1.0, 734: 1}, + {736: -0.5, 589: -0.5, 735: 1}, + {736: 1, 589: -1.0}, + {737: 1, 587: -1.0}, + {738: 1, 739: -0.5, 583: -0.5}, + {739: 1, 583: -1.0}, + {580: -0.5, 740: 1, 741: -0.5}, + {580: -1.0, 741: 1}, + {577: -0.5, 742: 1, 743: -0.5}, + {577: -1.0, 743: 1}, + {744: 1, 18: -1.0}, + {745: 1, 746: -0.5, 14: -0.5}, + {746: 1, 14: -1.0}, + {747: 1, 12: -1.0}, + {8: -0.5, 748: 1, 749: -0.5}, + {8: -1.0, 749: 1}, + {5: -0.5, 750: 1, 751: -0.5}, + {5: -1.0, 751: 1}, + {752: 1, 1: -0.5, 753: -0.5}, + {753: 1, 1: -1.0}] + + v = [2, 1, 1, 0, 9.5, 1, 1, 17.5, 1, 1, 10.5, 3.5, 3, 15.5, 1, 1, + 10.5, 3.5, 3, 5.5, 1, 1, 10.5, 3.5, 3, 5.5, 1, 1, 10.5, 3.5, + 3, 5.5, 1, 1, 10.5, 3.5, 3, 5.5, 1, 1, 10.5, 3.5, 3, 10, 2, 1, + 1, 13.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 10.5, 3.5, 3, 13, 1, 5, + 0, 2, 1, 1, 13.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, + 1, 1, 10.5, 3.5, 3, 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, + 14.0, 1, 1, 17.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, + 1, 1, 9.5, 1, 1, 14.0, 1, 1, 17.0, 1, 1, 9.5, 1, 1, 14.0, 1, + 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 10.5, 3.5, 3, + 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 10.5, 3.5, 3, 2, 1, 1, 13.0, + 1, 1, 9.5, 1, 1, 14.0, 1, 1, 10.5, 3.5, 3, 2, 1, 1, 9.5, 1, 1, + 14.0, 1, 1, 10.5, 3.5, 3, 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, + 1, 1, 19.5, 4, 1, 4, 1, 4, 1, 4, 1, 2, 1, 1, 9.5, 1, 1, 14.0, + 1, 1, 10.5, 3.5, 3, 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, + 14.0, 1, 1, 17.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, + 1, 1, 9.5, 1, 1, 14.0, 1, 1, 17.0, 1, 1, 9.5, 1, 1, 14.0, 1, + 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 10.5, 3.5, 3, + 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 19.5, 4, 1, 4, 1, + 4, 1, 4, 1, 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 10.5, 3.5, 3, 2, + 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, + 14.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 28.5, + 1, 1, 9.5, 1, 1, 12.0, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, + 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 3, 4, 1, 4, 1, 4, 1, 3, + 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, + 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 3, 4, 1, 4, + 1, 4, 1, 3, 4, 1, 4, 1, 4, 1, 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, + 18.5, 4, 1, 4, 1, 4, 1, 3, 4, 1, 4, 1, 4, 1, 4, 1, 2, 1, 1, 28.5, + 1, 1, 9.5, 1, 1, 12.0, 4, 1, 4, 1, 4, 1, 3, 4, 1, 4, 1, 4, 1, + 3, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, + 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 2, 1, 1, + 10.5, 3.5, 3, 2, 1, 1, 18.5, 4, 1, 3, 4, 1, 3, 4, 1, 4, 1, 4, + 1, 4, 1, 4, 1, 4, 1, 3, 4, 1, 4, 1, 4, 1, 4, 1, 10, 3, 4, 1, + 10, 3, 4, 1, 25, 1, 5, 3, 4, 1, 3, 4, 1, 2, 1, 1, 9.5, 1, 1, + 14.0, 1, 1, 10.5, 3.5, 3, 2, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 17.0, + 1, 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 14.0, 1, 1, 17.0, 1, + 1, 9.5, 1, 1, 14.0, 1, 1, 9.5, 1, 1, 17.5, 1, 1, 10.5, 3.5, 3, + 5.5, 1, 1, 10.5, 3.5, 3, 5.5, 1, 1, 10.5, 3.5, 3, 2, 1, 1, 9.5, + 1, 1, 12.0, 4, 1, 4, 1, 3, 4, 1, 2, 1, 1, 9.5, 1, 1, 12.0, 4, + 1, 4, 1, 3, 4, 1, 5.5, 1, 1, 10.5, 3.5, 3, 5.5, 1, 1, 10.5, 3.5, + 3, 2, 1, 1, 9.5, 1, 1, 12.0, 4, 1, 4, 1, 3, 4, 1, 2, 1, 1, 9.5, + 1, 1, 12.0, 4, 1, 4, 1, 3, 4, 1, 3, 4, 1, 4, 1, 4, 1, 4, 1, 4, + 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 3, 4, 1, 4, + 1, 4, 1, 3, 4, 1, 3, 4, 1, 4, 1, 4, 1] + + expected = [25.033, 20.783, 1.0, 0.0, 38.565, 26.815, 1.0, 50.631, + 30.881, 1.0, 58.762, 48.512, 45.012, 42.012, 24.262, 1.0, + 45.523, 35.273, 31.773, 35.124, 27.374, 1.0, 51.747, 41.497, + 37.997, 34.997, 27.247, 1.0, 51.494, 41.244, 37.744, 41.489, + 33.739, 1.0, 64.477, 54.227, 50.727, 43.568, 35.818, 1.0, + 68.636, 58.386, 54.886, 51.886, 41.886, 37.636, 1.0, 51.909, + 36.659, 1.0, 50.512, 38.762, 1.0, 53.518, 37.268, 1.0, + 51.383, 41.133, 37.633, 16.0, 1.0, 5.0, 0.0, 42.618, 38.368, + 1.0, 52.954, 37.704, 1.0, 52.006, 40.256, 1.0, 55.652, + 39.402, 1.0, 54.431, 42.681, 1.0, 59.116, 42.866, 1.0, + 59.38, 49.13, 45.63, 41.369, 37.119, 1.0, 51.171, 39.421, + 1.0, 54.458, 38.208, 1.0, 52.726, 40.976, 1.0, 56.68, + 40.43, 1.0, 55.899, 36.649, 1.0, 50.499, 38.749, 1.0, + 53.499, 37.249, 1.0, 51.355, 39.605, 1.0, 54.722, 38.472, + 1.0, 53.103, 41.353, 1.0, 57.219, 40.969, 1.0, 56.669, + 37.419, 1.0, 51.599, 39.849, 1.0, 55.07, 38.82, 1.0, 53.6, + 41.85, 1.0, 57.929, 41.679, 1.0, 57.684, 45.934, 1.0, + 63.762, 47.512, 1.0, 66.018, 55.768, 52.268, 45.673, 41.423, + 1.0, 57.319, 45.569, 1.0, 63.241, 46.991, 1.0, 65.273, + 55.023, 51.523, 44.184, 39.934, 1.0, 55.191, 39.941, 1.0, + 55.202, 43.452, 1.0, 60.217, 43.967, 1.0, 60.952, 50.702, + 47.202, 43.764, 39.514, 1.0, 54.591, 42.841, 1.0, 59.344, + 43.094, 1.0, 59.706, 49.456, 45.956, 42.499, 38.249, 1.0, + 52.785, 41.035, 1.0, 56.764, 40.514, 1.0, 56.02, 44.27, + 1.0, 61.386, 48.77, 45.27, 45.014, 41.514, 45.535, 42.035, + 42.749, 39.249, 43.412, 39.162, 1.0, 54.089, 42.339, 1.0, + 58.627, 42.377, 1.0, 58.681, 48.431, 44.931, 41.362, 37.112, + 1.0, 51.16, 39.41, 1.0, 54.443, 38.193, 1.0, 52.705, 40.955, + 1.0, 56.65, 40.4, 1.0, 55.857, 36.607, 1.0, 50.438, 38.688, + 1.0, 53.412, 37.162, 1.0, 51.231, 39.481, 1.0, 54.545, + 38.295, 1.0, 52.849, 41.099, 1.0, 56.856, 40.606, 1.0, + 56.152, 36.902, 1.0, 50.86, 39.11, 1.0, 54.014, 37.764, + 1.0, 52.091, 40.341, 1.0, 55.773, 39.523, 1.0, 54.604, + 42.854, 1.0, 59.363, 43.113, 1.0, 59.733, 49.483, 45.983, + 42.647, 38.397, 1.0, 52.995, 41.245, 1.0, 57.065, 40.815, + 1.0, 56.45, 44.7, 1.0, 61.999, 49.2, 45.7, 45.315, 41.815, + 45.745, 42.245, 42.897, 39.397, 43.32, 39.07, 1.0, 53.957, + 42.207, 1.0, 58.439, 42.189, 1.0, 58.412, 48.162, 44.662, + 40.678, 36.428, 1.0, 50.182, 38.432, 1.0, 53.046, 36.796, + 1.0, 50.709, 38.959, 1.0, 53.799, 37.549, 1.0, 51.784, + 40.034, 1.0, 55.334, 39.084, 1.0, 53.977, 42.227, 1.0, + 58.468, 42.218, 1.0, 58.454, 46.704, 1.0, 64.862, 48.612, + 1.0, 67.589, 36.839, 1.0, 50.77, 39.02, 1.0, 53.886, 43.52, + 40.02, 41.339, 37.839, 53.112, 49.612, 51.204, 47.704, + 46.718, 43.218, 46.727, 43.227, 43.584, 40.084, 44.534, + 41.034, 42.049, 38.549, 43.459, 39.959, 41.296, 37.796, + 42.932, 39.432, 40.928, 37.428, 47.662, 46.689, 43.189, + 46.707, 43.207, 43.57, 40.07, 48.983, 47.613, 44.113, + 47.354, 43.854, 44.023, 40.523, 44.841, 41.341, 42.264, + 38.764, 43.61, 40.11, 41.402, 37.902, 45.106, 41.606, + 45.599, 42.099, 42.795, 39.295, 43.981, 40.481, 41.662, + 38.162, 43.188, 39.688, 41.107, 37.607, 44.9, 41.4, 45.455, + 41.955, 42.693, 39.193, 43.91, 40.41, 41.612, 38.112, + 47.931, 46.877, 43.377, 46.839, 43.339, 43.662, 40.162, + 48.956, 47.594, 44.094, 47.341, 43.841, 44.014, 40.514, + 44.641, 40.391, 1.0, 55.844, 44.094, 1.0, 61.134, 44.884, + 1.0, 62.264, 49.384, 45.884, 48.594, 45.094, 44.891, 41.391, + 50.202, 48.467, 44.967, 47.952, 44.452, 44.441, 40.941, + 44.434, 40.934, 52.862, 48.612, 1.0, 67.589, 36.839, 1.0, + 50.77, 39.02, 1.0, 53.886, 43.52, 40.02, 41.339, 37.839, + 53.112, 49.612, 54.523, 51.491, 47.991, 50.069, 46.569, + 45.923, 42.423, 55.268, 52.012, 48.512, 50.434, 46.934, + 46.179, 42.679, 46.35, 42.85, 43.32, 39.82, 44.349, 40.849, + 41.919, 38.419, 45.469, 41.969, 45.853, 42.353, 42.972, + 39.472, 44.105, 40.605, 41.749, 38.249, 43.249, 39.749, + 41.149, 37.649, 44.93, 41.43, 45.476, 41.976, 42.708, + 39.208, 43.921, 40.421, 41.619, 38.119, 43.89, 39.64, + 1.0, 54.771, 44.521, 41.021, 47.459, 43.209, 1.0, 59.869, + 47.709, 44.209, 44.021, 44.14, 40.64, 48.63, 47.366, 43.866, + 47.181, 43.681, 43.902, 40.402, 44.756, 41.256, 42.204, + 38.704, 42.868, 39.368, 40.633, 41.768, 38.268, 43.262, + 39.762, 41.159, 37.659, 42.136, 38.636, 51.886, 57.886, + 40.318, 36.818, 51.886, 53.727, 38.239, 34.739, 28.0, + 1.0, 5.0, 40.744, 31.747, 28.247, 40.997, 31.874, 28.374, + 22.423, 18.173, 1.0, 33.347, 21.597, 1.0, 40.193, 23.943, + 1.0, 44.887, 34.637, 31.137, 21.277, 17.027, 1.0, 31.053, + 19.303, 1.0, 35.606, 19.356, 1.0, 35.713, 16.463, 1.0, + 29.926, 18.176, 1.0, 33.352, 17.102, 1.0, 31.203, 19.453, + 1.0, 35.906, 19.656, 1.0, 36.313, 17.063, 1.0, 31.125, + 19.375, 1.0, 35.751, 19.501, 1.0, 36.002, 24.252, 1.0, + 45.504, 25.754, 1.0, 48.507, 38.257, 34.757, 31.757, 24.007, + 1.0, 45.015, 34.765, 31.265, 32.405, 24.655, 1.0, 46.311, + 36.061, 32.561, 24.124, 19.874, 1.0, 36.749, 24.999, 1.0, + 46.997, 29.499, 25.999, 24.374, 20.874, 35.561, 29.155, + 25.655, 24.124, 19.874, 1.0, 36.749, 24.999, 1.0, 46.997, + 29.499, 25.999, 24.374, 20.874, 34.265, 28.507, 25.007, + 31.757, 24.007, 1.0, 45.015, 34.765, 31.265, 32.405, 24.655, + 1.0, 46.311, 36.061, 32.561, 24.124, 19.874, 1.0, 36.749, + 24.999, 1.0, 46.997, 29.499, 25.999, 24.374, 20.874, 35.561, + 29.155, 25.655, 24.124, 19.874, 1.0, 36.749, 24.999, 1.0, + 46.997, 29.499, 25.999, 24.374, 20.874, 34.265, 28.507, + 25.007, 37.757, 30.254, 26.754, 28.752, 25.252, 24.001, + 20.501, 23.875, 20.375, 21.563, 18.063, 24.156, 20.656, + 23.953, 20.453, 21.602, 18.102, 22.676, 19.176, 20.963, + 17.463, 23.856, 20.356, 23.803, 20.303, 21.527, 18.027, + 34.137, 28.443, 24.943, 26.097, 22.597, 22.673, 19.173, + 34.773, 28.762, 25.262, 48.012, 35.381, 31.881, 31.315, + 27.815, 25.283, 21.783] + + answer = M.solve(v) + + assert len(answer) == len(expected) + for x, y in zip(answer, expected): + error = abs(y - x) + assert error < 0.01 From auc at codespeak.net Fri Sep 29 17:55:59 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Fri, 29 Sep 2006 17:55:59 +0200 (CEST) Subject: [pypy-svn] r32743 - pypy/dist/pypy/objspace/cclp Message-ID: <20060929155559.55CFC10053@code0.codespeak.net> Author: auc Date: Fri Sep 29 17:55:55 2006 New Revision: 32743 Modified: pypy/dist/pypy/objspace/cclp/variable.py Log: remove assertion from translated pypys Modified: pypy/dist/pypy/objspace/cclp/variable.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/variable.py (original) +++ pypy/dist/pypy/objspace/cclp/variable.py Fri Sep 29 17:55:55 2006 @@ -9,6 +9,7 @@ from pypy.objspace.cclp.global_state import scheduler from pypy.objspace.cclp.types import deref, W_Var, W_CVar, W_Future, W_FailedValue +from pypy.rpython.objectmodel import we_are_translated W_Root = baseobjspace.W_Root all_mms = {} @@ -39,7 +40,8 @@ return w_ret def wait(space, w_obj): - assert isinstance(w_obj, W_Root) + if not we_are_translated(): + assert isinstance(w_obj, W_Root) return space.wait(w_obj) app_wait = gateway.interp2app(wait) From auc at codespeak.net Fri Sep 29 17:57:25 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Fri, 29 Sep 2006 17:57:25 +0200 (CEST) Subject: [pypy-svn] r32744 - in pypy/dist/pypy/objspace/cclp: . constraint Message-ID: <20060929155725.E868F10053@code0.codespeak.net> Author: auc Date: Fri Sep 29 17:57:23 2006 New Revision: 32744 Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py pypy/dist/pypy/objspace/cclp/types.py Log: copiers Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/domain.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/domain.py Fri Sep 29 17:57:23 2006 @@ -29,6 +29,8 @@ self._values = space.newdict() self.set_values(w_values) + def copy(self): + return W_FiniteDomain(self._space, self.w_get_values()) def clear_change(self): "create a fresh change synchonizer" Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Fri Sep 29 17:57:23 2006 @@ -48,6 +48,9 @@ else: cspace.register_var(self) + def copy(self, space): + return W_CVar(space, self.w_dom.copy(), self.w_nam) + def name_w(self): return self.name From cfbolz at codespeak.net Fri Sep 29 19:22:48 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 19:22:48 +0200 (CEST) Subject: [pypy-svn] r32747 - in pypy/dist/pypy: bin config config/test interpreter tool tool/build translator/goal Message-ID: <20060929172248.4D24510053@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 19:22:44 2006 New Revision: 32747 Removed: pypy/dist/pypy/translator/goal/targetpypymain.py pypy/dist/pypy/translator/goal/targetthunkstandalone.py Modified: pypy/dist/pypy/bin/py.py pypy/dist/pypy/config/config.py pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/config/test/test_config.py pypy/dist/pypy/config/test/test_pypyoption.py pypy/dist/pypy/interpreter/interactive.py pypy/dist/pypy/tool/build/systemoption.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/goal/targetpypystandalone.py pypy/dist/pypy/translator/goal/translate.py Log: svn merge -r 32051:HEAD http://codespeak.net/svn/pypy/branch/config-in-more-places/ Merge in config branch. Now py.py and targetpypystandalone both take a lot more options. Modified: pypy/dist/pypy/bin/py.py ============================================================================== --- pypy/dist/pypy/bin/py.py (original) +++ pypy/dist/pypy/bin/py.py Fri Sep 29 19:22:44 2006 @@ -12,7 +12,7 @@ pass from pypy.tool import option -from optparse import make_option +from py.compat.optparse import make_option from pypy.interpreter import main, interactive, error import os, sys import time @@ -26,8 +26,9 @@ module_args = [] def get_main_options(): - options = option.get_standard_options() + config, parser = option.get_standard_options() + options = [] options.append(make_option( '-v', action='store_true', dest='verbose', help='show verbose interpreter-level traceback')) @@ -63,28 +64,20 @@ callback=runmodule_callback, type="string", help="library module to be run as a script (terminates option list)")) - + parser.add_options(options) - return options + return config, parser -def make_objspace(conf): - mod = __import__('pypy.objspace.%s' % conf.objspace.name, - None, None, ['Space']) - Space = mod.Space - #conf.objspace.logbytecodes = True - space = Space(conf) - return space - def main_(argv=None): - starttime = time.time() - args = option.process_options(get_main_options(), Options, argv[1:]) + starttime = time.time() + config, parser = get_main_options() + args = option.process_options(parser, Options, argv[1:]) if Options.verbose: error.RECORD_INTERPLEVEL_TRACEBACK = True # create the object space - config = option.make_config(Options) - space = make_objspace(config) + space = option.make_objspace(config) space._starttime = starttime #assert 'pypy.tool.udir' not in sys.modules, ( @@ -147,66 +140,6 @@ return exit_status -##def main_(argv=None): -## starttime = time.time() -## from pypy.tool import tb_server -## args = option.process_options(get_main_options(), Options, argv[1:]) -## space = None -## exit_status = 1 # until proven otherwise -## # XXX should review what CPython's policy is for -## # the exit status code -## try: -## space = option.objspace() -## space._starttime = starttime -## assert 'pypy.tool.udir' not in sys.modules, ( -## "running py.py should not import pypy.tool.udir, which is\n" -## "only for testing or translating purposes.") -## go_interactive = Options.interactive -## if Options.verbose: -## error.RECORD_INTERPLEVEL_TRACEBACK = True -## banner = '' -## space.setitem(space.sys.w_dict,space.wrap('executable'),space.wrap(argv[0])) -## if Options.command: -## args = ['-c'] + Options.command[1:] -## for arg in args: -## space.call_method(space.sys.get('argv'), 'append', space.wrap(arg)) -## try: -## if Options.command: -## main.run_string(Options.command[0], '', space) -## elif args: -## main.run_file(args[0], space) -## else: -## space.call_method(space.sys.get('argv'), 'append', space.wrap('')) -## go_interactive = 1 -## banner = None -## exit_status = 0 -## except error.OperationError, operationerr: -## if Options.verbose: -## operationerr.print_detailed_traceback(space) -## else: -## operationerr.print_application_traceback(space) -## if go_interactive: -## con = interactive.PyPyConsole(space, verbose=Options.verbose, completer=Options.completer) -## if banner == '': -## banner = '%s / %s'%(con.__class__.__name__, -## repr(space)) -## con.interact(banner) -## except: -## exc_type, value, tb = sys.exc_info() -## sys.last_type = exc_type -## sys.last_value = value -## sys.last_traceback = tb -## if issubclass(exc_type, SystemExit): -## pass # don't print tracebacks for SystemExit -## elif isinstance(value, error.OperationError): -## value.print_detailed_traceback(space=space) -## else: -## sys.excepthook(exc_type, value, tb) -## tb_server.wait_until_interrupt() -## exit_status = 1 - -## tb_server.stop() -## return exit_status if __name__ == '__main__': try: Modified: pypy/dist/pypy/config/config.py ============================================================================== --- pypy/dist/pypy/config/config.py (original) +++ pypy/dist/pypy/config/config.py Fri Sep 29 19:22:44 2006 @@ -1,12 +1,13 @@ -import optparse +from py.compat import optparse class Config(object): _frozen = False - def __init__(self, descr, **overrides): + def __init__(self, descr, parent=None, **overrides): self._descr = descr self._value_owners = {} + self._parent = parent self._build(overrides) def _build(self, overrides): @@ -15,7 +16,7 @@ self.__dict__[child._name] = child.default self._value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): - self.__dict__[child._name] = Config(child) + self.__dict__[child._name] = Config(child, parent=self) for name, value in overrides.iteritems(): subconfig, name = self._get_by_path(name) setattr(subconfig, name, value) @@ -52,6 +53,11 @@ self = getattr(self, step) return self, path[-1] + def _get_toplevel(self): + while self._parent is not None: + self = self._parent + return self + def _freeze_(self): self.__dict__['_frozen'] = True return True @@ -87,7 +93,7 @@ result += substr return result - def getpaths(self, currpath=None): + def getpaths(self, include_groups=False, currpath=None): """returns a list of all paths in self, recursively currpath should not be provided (helps with recursion) @@ -95,19 +101,28 @@ if currpath is None: currpath = [] paths = [] - for attr, value in self.__dict__.iteritems(): + for option in self._descr._children: + attr = option._name if attr.startswith('_'): continue + value = getattr(self, attr) if isinstance(value, Config): + if include_groups: + paths.append('.'.join(currpath + [attr])) currpath.append(attr) - paths += value.getpaths(currpath) + paths += value.getpaths(include_groups=include_groups, + currpath=currpath) currpath.pop() else: paths.append('.'.join(currpath + [attr])) return paths + +DEFAULT_OPTION_NAME = object() + + class Option(object): - def __init__(self, name, doc, cmdline=None): + def __init__(self, name, doc, cmdline=DEFAULT_OPTION_NAME): self._name = name self.doc = doc self.cmdline = cmdline @@ -131,10 +146,21 @@ raise NotImplemented('abstract base class') class ChoiceOption(Option): - def __init__(self, name, doc, values, default, cmdline=None): + def __init__(self, name, doc, values, default, requires=None, + cmdline=DEFAULT_OPTION_NAME): super(ChoiceOption, self).__init__(name, doc, cmdline) self.values = values self.default = default + if requires is None: + requires = {} + self._requires = requires + + def setoption(self, config, value): + name = self._name + for path, reqvalue in self._requires.get(value, []): + subconfig, name = config._get_toplevel()._get_by_path(path) + subconfig.require(name, reqvalue) + super(ChoiceOption, self).setoption(config, value) def validate(self, value): return value in self.values @@ -146,21 +172,17 @@ except ValueError, e: raise optparse.OptionValueError(e.args[0]) parser.add_option(help=self.doc, - action='callback', type='string', + action='callback', type='string', callback=_callback, *argnames) class BoolOption(ChoiceOption): - def __init__(self, name, doc, default=True, requires=None, cmdline=None): + def __init__(self, name, doc, default=True, requires=None, + cmdline=DEFAULT_OPTION_NAME): + if requires is not None: + requires = {True: requires} super(BoolOption, self).__init__(name, doc, [True, False], default, - cmdline=cmdline) - self._requires = requires or [] - - def setoption(self, config, value): - name = self._name - for path, reqvalue in self._requires: - subconfig, name = config._get_by_path(path) - subconfig.require(name, reqvalue) - super(BoolOption, self).setoption(config, value) + requires=requires, + cmdline=cmdline) def add_optparse_option(self, argnames, parser, config): def _callback(option, opt_str, value, parser, *args, **kwargs): @@ -169,11 +191,11 @@ except ValueError, e: raise optparse.OptionValueError(e.args[0]) parser.add_option(help=self.doc, - action='callback', + action='callback', callback=_callback, *argnames) class IntOption(Option): - def __init__(self, name, doc, default=0, cmdline=None): + def __init__(self, name, doc, default=0, cmdline=DEFAULT_OPTION_NAME): super(IntOption, self).__init__(name, doc, cmdline) self.default = default @@ -194,11 +216,11 @@ def _callback(option, opt_str, value, parser, *args, **kwargs): config.setoption(self._name, value, who='cmdline') parser.add_option(help=self.doc, - action='callback', type='int', + action='callback', type='int', callback=_callback, *argnames) class FloatOption(Option): - def __init__(self, name, doc, default=0.0, cmdline=None): + def __init__(self, name, doc, default=0.0, cmdline=DEFAULT_OPTION_NAME): super(FloatOption, self).__init__(name, doc, cmdline) self.default = default @@ -219,12 +241,13 @@ def _callback(option, opt_str, value, parser, *args, **kwargs): config.setoption(self._name, value, who='cmdline') parser.add_option(help=self.doc, - action='callback', type='float', - callback=_callback, *argnames) + action='callback', type='float', + callback=_callback, *argnames) class OptionDescription(object): - def __init__(self, name, children, cmdline=None): + def __init__(self, name, doc, children, cmdline=DEFAULT_OPTION_NAME): self._name = name + self.doc = doc self._children = children self._build() self.cmdline = cmdline @@ -259,12 +282,24 @@ callback=_callback, *argnames) -def to_optparse(config, useoptions, parser=None): +def to_optparse(config, useoptions=None, parser=None): + grps = {} + def get_group(name, doc): + steps = name.split('.') + if len(steps) < 2: + return parser + grpname = steps[-2] + grp = grps.get(grpname, None) + if grp is None: + grp = grps[grpname] = parser.add_option_group(doc) + return grp + if parser is None: parser = optparse.OptionParser() + if useoptions is None: + useoptions = config.getpaths(include_groups=True) for path in useoptions: - if path.endswith("*"): - assert path.endswith("*") + if path.endswith(".*"): path = path[:-2] subconf, name = config._get_by_path(path) children = [ @@ -274,10 +309,17 @@ else: subconf, name = config._get_by_path(path) option = getattr(subconf._descr, name) - if option.cmdline is None: + if option.cmdline is DEFAULT_OPTION_NAME: chunks = ('--%s' % (path.replace('.', '-'),),) + elif option.cmdline is None: + continue else: chunks = option.cmdline.split(' ') - option.add_optparse_option(chunks, parser, subconf) + try: + grp = get_group(path, subconf._descr.doc) + option.add_optparse_option(chunks, grp, subconf) + except ValueError: + # an option group that does not only contain bool values + pass return parser Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Fri Sep 29 19:22:44 2006 @@ -1,4 +1,6 @@ import py +print py.magic.autopath().dirpath().dirpath().dirpath() +py.std.sys.path.insert(0, py.magic.autopath().dirpath().dirpath().dirpath()) from pypy.config.config import OptionDescription, BoolOption, IntOption from pypy.config.config import ChoiceOption, to_optparse, Config @@ -11,33 +13,42 @@ "math", "_sre", "_pickle_support", "sys", "exceptions", "__builtins__", "recparser", "symbol", "_random"]) -pypy_optiondescription = OptionDescription("pypy", [ - OptionDescription("objspace", [ +pypy_optiondescription = OptionDescription("pypy", "All PyPy Options", [ + OptionDescription("objspace", "Object Space Option", [ ChoiceOption("name", "Object Space name", ["std", "flow", "logic", "thunk", "cpy"], "std", + requires = { + "thunk": [("objspace.geninterp", False)], + "logic": [("objspace.geninterp", False)], + }, cmdline='--objspace -o'), ChoiceOption("parser", "parser", - ["pypy", "cpython"], "pypy"), + ["pypy", "cpython"], "pypy", + cmdline='--parser'), ChoiceOption("compiler", "compiler", - ["cpython", "ast"], "ast"), + ["cpython", "ast"], "ast", + cmdline='--compiler'), BoolOption("nofaking", "disallow faking in the object space", default=False, requires=[ - ("uselibfile", True), - ("usemodules.posix", True), - ("usemodules.time", True), - ("usemodules.errno", True)]), + ("objspace.uselibfile", True), + ("objspace.usemodules.posix", True), + ("objspace.usemodules.time", True), + ("objspace.usemodules.errno", True)], + cmdline='--nofaking'), BoolOption("uselibfile", "use the applevel file implementation", - default=False), + default=False, + cmdline='--uselibfile'), - OptionDescription("usemodules", [ + OptionDescription("usemodules", "Which Modules should be used", [ BoolOption(modname, "use module %s" % (modname, ), - default=modname in default_modules) - for modname in all_modules]), + default=modname in default_modules, + cmdline=None) + for modname in all_modules], cmdline="--usemodules"), BoolOption("geninterp", "specify whether geninterp should be used"), @@ -45,12 +56,13 @@ "keep track of bytecode usage", default=False), - OptionDescription("std", [ + OptionDescription("std", "Standard Object Space Options", [ BoolOption("withsmallint", "use tagged integers", default=False), BoolOption("withprebuiltint", "prebuilt commonly used int objects", - default=False, requires=[("withsmallint", False)]), + default=False, + requires=[("objspace.std.withsmallint", False)]), IntOption("prebuiltintfrom", "lowest integer which is prebuilt", default=-5, cmdline="--prebuiltinfrom"), @@ -70,28 +82,31 @@ BoolOption("withmultidict", "use dictionaries optimized for flexibility", - default=False, requires=[("withstrdict", False)]), + default=False, + requires=[("objspace.std.withstrdict", False)]), BoolOption("withdictmeasurement", "create huge files with masses of information " "about dictionaries", - default=False, requires=[("withmultidict", True)]), + default=False, + requires=[("objspace.std.withmultidict", True)]), BoolOption("oldstyle", "specify whether the default metaclass should be classobj", - default=False), + default=False, cmdline="--oldstyle"), ]), ]), BoolOption("translating", "indicates whether we are translating currently", - default=False), + default=False, cmdline=None), ]) + if __name__ == '__main__': config = Config(pypy_optiondescription) - paths = config.getpaths() - parser = to_optparse(config, paths) + print config.getpaths() + parser = to_optparse(config) option, args = parser.parse_args() print config Modified: pypy/dist/pypy/config/test/test_config.py ============================================================================== --- pypy/dist/pypy/config/test/test_config.py (original) +++ pypy/dist/pypy/config/test/test_config.py Fri Sep 29 19:22:44 2006 @@ -4,7 +4,7 @@ def make_description(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) - objspaceoption = ChoiceOption('objspace', 'Object space', + objspaceoption = ChoiceOption('objspace', 'Object space', ['std', 'logic'], 'std') booloption = BoolOption('bool', 'Test boolean option') intoption = IntOption('int', 'Test int option') @@ -13,9 +13,9 @@ wantref_option = BoolOption('wantref', 'Test requires', default=False, requires=[('gc.name', 'ref')]) - gcgroup = OptionDescription('gc', [gcoption, gcdummy, floatoption]) - descr = OptionDescription('pypy', [gcgroup, booloption, objspaceoption, - wantref_option, intoption]) + gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) + descr = OptionDescription('pypy', '', [gcgroup, booloption, objspaceoption, + wantref_option, intoption]) return descr def test_base_config(): @@ -57,8 +57,8 @@ from pypy.translator.interactive import Translation gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') - gcgroup = OptionDescription('gc', [gcoption]) - descr = OptionDescription('pypy', [gcgroup]) + gcgroup = OptionDescription('gc', '', [gcoption]) + descr = OptionDescription('pypy', '', [gcgroup]) config = Config(descr) def f(x): @@ -102,8 +102,8 @@ def test_to_optparse(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref', cmdline='--gc -g') - gcgroup = OptionDescription('gc', [gcoption]) - descr = OptionDescription('pypy', [gcgroup]) + gcgroup = OptionDescription('gc', '', [gcoption]) + descr = OptionDescription('pypy', '', [gcgroup]) config = Config(descr) parser = to_optparse(config, ['gc.name']) @@ -115,14 +115,14 @@ assert config.gc.name == 'ref' # XXX strange exception - py.test.raises(SystemExit, + py.test.raises(SystemExit, "(options, args) = parser.parse_args(args=['-g foobar'])") def test_to_optparse_number(): intoption = IntOption('int', 'Int option test', cmdline='--int -i') floatoption = FloatOption('float', 'Float option test', cmdline='--float -f') - descr = OptionDescription('test', [intoption, floatoption]) + descr = OptionDescription('test', '', [intoption, floatoption]) config = Config(descr) parser = to_optparse(config, ['int', 'float']) @@ -137,7 +137,7 @@ def test_to_optparse_bool(): booloption = BoolOption('bool', 'Boolean option test', default=False, cmdline='--bool -b') - descr = OptionDescription('test', [booloption]) + descr = OptionDescription('test', '', [booloption]) config = Config(descr) parser = to_optparse(config, ['bool']) @@ -154,7 +154,7 @@ "(options, args) = parser.parse_args(args=['-bfoo'])") def test_optparse_boolgroup(): - group = OptionDescription("test", [ + group = OptionDescription("test", '', [ BoolOption("smallint", "use tagged integers", default=False), BoolOption("strjoin", "use strings optimized for addition", @@ -164,7 +164,7 @@ BoolOption("strdict", "use dictionaries optimized for string keys", default=False), ], cmdline="--test") - descr = OptionDescription("all", [group]) + descr = OptionDescription("all", '', [group]) config = Config(descr) parser = to_optparse(config, ['test']) (options, args) = parser.parse_args( @@ -195,8 +195,8 @@ def test_optparse_path_options(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') - gcgroup = OptionDescription('gc', [gcoption]) - descr = OptionDescription('pypy', [gcgroup]) + gcgroup = OptionDescription('gc', '', [gcoption]) + descr = OptionDescription('pypy', '', [gcgroup]) config = Config(descr) parser = to_optparse(config, ['gc.name']) @@ -208,6 +208,51 @@ descr = make_description() config = Config(descr) - assert config.getpaths(), ['gc.name', 'gc.dummy', 'gc.float', 'bool', - 'objspace', 'wantref', 'int'] - assert config.gc.getpaths(), ['name', 'dummy', 'float'] + assert config.getpaths() == ['gc.name', 'gc.dummy', 'gc.float', 'bool', + 'objspace', 'wantref', 'int'] + assert config.gc.getpaths() == ['name', 'dummy', 'float'] + assert config.getpaths(include_groups=True) == [ + 'gc', 'gc.name', 'gc.dummy', 'gc.float', + 'bool', 'objspace', 'wantref', 'int'] + +def test_none(): + dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None) + dummy2 = BoolOption('dummy2', 'doc dummy', default=False, cmdline='--dummy') + group = OptionDescription('group', '', [dummy1, dummy2]) + config = Config(group) + + parser = to_optparse(config) + py.test.raises(SystemExit, + "(options, args) = parser.parse_args(args=['--dummy1'])") + +def test_requirements_from_top(): + descr = OptionDescription("test", '', [ + BoolOption("toplevel", "", default=False), + OptionDescription("sub", '', [ + BoolOption("opt", "", default=False, + requires=[("toplevel", True)]) + ]) + ]) + config = Config(descr) + config.sub.opt = True + assert config.toplevel + +def test_requirements_for_choice(): + descr = OptionDescription("test", '', [ + BoolOption("toplevel", "", default=False), + OptionDescription("s", '', [ + ChoiceOption("type_system", "", ["ll", "oo"], "ll"), + ChoiceOption("backend", "", + ["c", "llvm", "cli"], "llvm", + requires={ + "c": [("s.type_system", "ll"), + ("toplevel", True)], + "llvm": [("s.type_system", "ll")], + "cli": [("s.type_system", "oo")], + }) + ]) + ]) + config = Config(descr) + config.s.backend = "cli" + assert config.s.type_system == "oo" + Modified: pypy/dist/pypy/config/test/test_pypyoption.py ============================================================================== --- pypy/dist/pypy/config/test/test_pypyoption.py (original) +++ pypy/dist/pypy/config/test/test_pypyoption.py Fri Sep 29 19:22:44 2006 @@ -16,3 +16,11 @@ assert not conf.objspace.std.withprebuiltint conf.objspace.std.withprebuiltint = True assert not conf.objspace.std.withsmallint + +def test_objspace_incopatibilities(): + conf = Config(pypy_optiondescription) + conf.objspace.name = "thunk" + assert not conf.objspace.geninterp + conf = Config(pypy_optiondescription) + conf.objspace.name = "logic" + assert not conf.objspace.geninterp Modified: pypy/dist/pypy/interpreter/interactive.py ============================================================================== --- pypy/dist/pypy/interpreter/interactive.py (original) +++ pypy/dist/pypy/interpreter/interactive.py Fri Sep 29 19:22:44 2006 @@ -225,16 +225,3 @@ class IncompleteInput(Exception): pass -if __name__ == '__main__': - try: - import readline - except ImportError: - pass - - from pypy.tool import option - from pypy.tool import testit - args = option.process_options(option.get_standard_options(), - option.Options) - objspace = option.objspace() - con = PyPyConsole(objspace) - con.interact() Modified: pypy/dist/pypy/tool/build/systemoption.py ============================================================================== --- pypy/dist/pypy/tool/build/systemoption.py (original) +++ pypy/dist/pypy/tool/build/systemoption.py Fri Sep 29 19:22:44 2006 @@ -3,7 +3,7 @@ from pypy.config.config import ChoiceOption, to_optparse, Config import sys -system_optiondescription = OptionDescription('system', [ +system_optiondescription = OptionDescription('system', '', [ ChoiceOption('maxint', 'maximum int value in bytes (32/64)', ['32', '64'], sys.maxint, '-i --maxint'), ChoiceOption('byteorder', 'endianness, byte order (little/big)', Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Fri Sep 29 19:22:44 2006 @@ -2,11 +2,12 @@ # XXX needs clean-up and reorganization. import os -import optparse +from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.config import Config, to_optparse +from py.compat import optparse make_option = optparse.make_option class Options: - showwarning = 0 objspace = "std" oldstyle = 0 uselibfile = 0 @@ -15,64 +16,26 @@ compiler = "ast" # "ast" uses interpreter/pyparser & interpreter/astcompiler.py # "cpython" uses cpython parser and cpython c-level compiler - usemodules = [] + usemodules = [] version = "2.5a" # "native" / "2.3" / "2.4" / "2.5a" def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server tb_server.start() + def get_standard_options(): - options = [] - - def usemodules_callback(option, opt, value, parser): - parser.values.usemodules.append(value) - - options.append(make_option( - '-o', '--objspace', action="store", type="string", dest="objspace", - help="object space to run PyPy on.")) - options.append(make_option( - '--usemodules', action="callback", metavar='NAME', - callback=usemodules_callback, type="string", - help="(mixed) modules to use.")) - options.append(make_option( - '--oldstyle', action="store_true", dest="oldstyle", - help="enable oldstyle classes as default metaclass (std objspace only)")) - options.append(make_option( - '--uselibfile', action="store_true", dest="uselibfile", - help="enable our custom file implementation")) - options.append(make_option( - '--nofaking', action="store_true", dest="nofaking", - help="avoid faking of modules or objects")) - options.append(make_option( - '-w', action="store_true", dest="showwarning", - help="enable warnings (disabled by default)")) - options.append(make_option( + config = Config(pypy_optiondescription) + parser = to_optparse(config) + parser.add_option( '-H', action="callback", callback=run_tb_server, - help="use web browser for traceback info")) - options.append(make_option( - '--compiler', action="store", type="string", dest="compiler", - default=None, - help="""select compiling approach. see pypy/doc/README.compiling""", - metavar="[ast|cpython]")) - options.append(make_option( - '--parser', action="store",type="string", dest="parser", default=None, - help="select the parser module to use", - metavar="[pypy|cpython]")) -## for this to work the option module need to be loaded before the grammar! -## options.append(make_option( -## '--version', action="store",type="string", dest="version", -## help="select the Python version to emulate", -## metavar="[native|2.3|2.4]")) - - return options + help="use web browser for traceback info") + return config, parser -def process_options(optionlist, input_options, argv=None): +def process_options(op, input_options, argv=None): global Options Options = input_options - op = optparse.OptionParser() - op.add_options(optionlist) op.disable_interspersed_args() options, args = op.parse_args(argv, input_options) return args @@ -121,3 +84,11 @@ setattr(subconf, names[-1], value) return conf +def make_objspace(conf): + mod = __import__('pypy.objspace.%s' % conf.objspace.name, + None, None, ['Space']) + Space = mod.Space + #conf.objspace.logbytecodes = True + space = Space(conf) + return space + Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Fri Sep 29 19:22:44 2006 @@ -1,6 +1,6 @@ -import os, sys +import py -from pypy.tool.option import make_config +import os, sys # as of revision 27081, multimethod.py uses the InstallerVersion1 by default # because it is much faster both to initialize and run on top of CPython. @@ -10,12 +10,13 @@ multimethod.Installer = multimethod.InstallerVersion2 from pypy.objspace.std.objspace import StdObjSpace -# XXX from pypy.annotation.model import * -# since we are execfile()'ed this would pull some -# weird objects into the globals, which we would try to pickle. from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy +from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.config import Config, to_optparse +from pypy.tool.option import make_objspace + try: this_dir = os.path.dirname(__file__) @@ -70,22 +71,20 @@ take_options = True -def opt_parser(): - import py - defl = {'thread': False, 'usemodules': ''} - parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", +def opt_parser_config(): + parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", add_help_option=False) - parser.set_defaults(**defl) - parser.add_option("--thread", action="store_true", dest="thread", - help="enable threading") - parser.add_option("--usemodules", action="store", type="string", - dest="usemodules", help=("list of mixed modules to " - "include, comma-separated")) - return parser + parser.set_defaults(thread=False) + parser.add_option("--thread", action="store_true", dest="thread", + help="enable threading") + config = Config(pypy_optiondescription) + opt_parser = py.compat.optparse.OptionParser(usage="target PyPy standalone", + add_help_option=False) + to_optparse(config, parser=parser) + return config, parser def print_help(): - opt_parser().print_help() - + opt_parser_config()[1].print_help() def call_finish(space): space.finish() @@ -95,14 +94,13 @@ def target(driver, args): + global config, opt_parser driver.exe_name = 'pypy-%(backend)s' options = driver.options - tgt_options, _ = opt_parser().parse_args(args) - - config = make_config(tgt_options) + config, opt_parser = opt_parser_config() - translate.log_options(tgt_options, "target PyPy options in effect") + tgt_options, _ = opt_parser.parse_args(args) # expose the following variables to ease debugging global space, entry_point @@ -115,19 +113,28 @@ wrapstr = 'space.wrap(%r)' % (options.__dict__) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr - usemodules = [] - if tgt_options.usemodules: - for modname in tgt_options.usemodules.split(","): - setattr(config.objspace.usemodules, modname, True) if tgt_options.thread: config.objspace.usemodules.thread = True + elif config.objspace.usemodules.thread: + tgt_options.thread = True + if options.stackless: config.objspace.usemodules._stackless = True + elif config.objspace.usemodules._stackless: + options.stackless = True + config.objspace.nofaking = True config.objspace.compiler = "ast" config.translating = True + + translate.log_options(tgt_options, "target PyPy options in effect") + translate.log_config(config, "PyPy config object") - space = StdObjSpace(config) + space = make_objspace(config) + + # disable translation of the whole of classobjinterp.py + StdObjSpace.setup_old_style_classes = lambda self: None + # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Fri Sep 29 19:22:44 2006 @@ -268,6 +268,10 @@ optvalue = getattr(options, name) log('%25s: %s' %(name, optvalue)) +def log_config(config, header="config used"): + log('%s:' % header) + log(str(config)) + def main(): targetspec_dic, options, args = parse_options_and_load_target() From cfbolz at codespeak.net Fri Sep 29 19:23:15 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 19:23:15 +0200 (CEST) Subject: [pypy-svn] r32748 - pypy/branch/config-in-more-places Message-ID: <20060929172315.462BA10053@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 19:23:14 2006 New Revision: 32748 Removed: pypy/branch/config-in-more-places/ Log: delete merged branch From cfbolz at codespeak.net Fri Sep 29 19:33:56 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 19:33:56 +0200 (CEST) Subject: [pypy-svn] r32749 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060929173356.24D5010053@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 19:33:55 2006 New Revision: 32749 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py Log: I think this operation is missing. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Fri Sep 29 19:33:55 2006 @@ -283,6 +283,7 @@ 'cast_int_to_float': LLOp(canfold=True), 'cast_int_to_longlong': LLOp(canfold=True), 'cast_uint_to_int': LLOp(canfold=True), + 'cast_uint_to_float': LLOp(canfold=True), 'cast_float_to_int': LLOp(canraise=(OverflowError,)), 'cast_float_to_uint': LLOp(canfold=True), 'truncate_longlong_to_int':LLOp(canfold=True), From cfbolz at codespeak.net Fri Sep 29 19:35:01 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 19:35:01 +0200 (CEST) Subject: [pypy-svn] r32750 - pypy/branch/even-more-config Message-ID: <20060929173501.477A310053@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 19:34:59 2006 New Revision: 32750 Added: pypy/branch/even-more-config/ - copied from r32749, pypy/dist/ Log: Another branch for the advancement of configuration. From xoraxax at codespeak.net Fri Sep 29 19:38:10 2006 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Fri, 29 Sep 2006 19:38:10 +0200 (CEST) Subject: [pypy-svn] r32751 - pypy/dist/pypy/translator/goal Message-ID: <20060929173810.66EF310053@code0.codespeak.net> Author: xoraxax Date: Fri Sep 29 19:38:09 2006 New Revision: 32751 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Added strdict benchmark targets for C and LLVM. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Fri Sep 29 19:38:09 2006 @@ -122,7 +122,11 @@ realname += "-" + features if backend == 'llvm': #create llvm exectutable from the current source - compile_llvm_variants(revision) + if features: + revname = revision + "-" + features + else: + revname = revision + compile_llvm_variants(revname) elif os.path.exists(basename): #copy executable pypy = open(basename, 'rb').read() if len(pypy) > 0: @@ -143,7 +147,7 @@ def main(backends=[]): if backends == []: #_ prefix means target specific option #backends = """llvm at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++""".split('@') - backends = """llvm at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++ at c--profopt='-c "from richards import *;main(iterations=1)"'""".split('@') + backends = """llvm at llvm--objspace-std-withstrdict@c at c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++ at c--objspace-std-withstrdict@c--profopt='-c "from richards import *;main(iterations=1)"'""".split('@') #backends = 'llvm c c--gc=framework c--_thread c--stackless'.split() #backends = 'llvm c c--gc=framework c--new-stackless c--_thread'.split() #backends = 'llvm c c--stackless c--_thread c--stackless--_thread'.split() From xoraxax at codespeak.net Fri Sep 29 19:50:52 2006 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Fri, 29 Sep 2006 19:50:52 +0200 (CEST) Subject: [pypy-svn] r32752 - pypy/dist/pypy/translator/goal Message-ID: <20060929175052.B0AF610053@code0.codespeak.net> Author: xoraxax Date: Fri Sep 29 19:50:52 2006 New Revision: 32752 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Removed the nonstrdict LLVM build because the whole LLVM chain is presumely to long to fit two times into a night together with the other builds :) Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Fri Sep 29 19:50:52 2006 @@ -147,7 +147,7 @@ def main(backends=[]): if backends == []: #_ prefix means target specific option #backends = """llvm at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++""".split('@') - backends = """llvm at llvm--objspace-std-withstrdict@c at c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++ at c--objspace-std-withstrdict@c--profopt='-c "from richards import *;main(iterations=1)"'""".split('@') + backends = """llvm--objspace-std-withstrdict at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++ at c--objspace-std-withstrdict@c--profopt='-c "from richards import *;main(iterations=1)"'""".split('@') #backends = 'llvm c c--gc=framework c--_thread c--stackless'.split() #backends = 'llvm c c--gc=framework c--new-stackless c--_thread'.split() #backends = 'llvm c c--stackless c--_thread c--stackless--_thread'.split() From xoraxax at codespeak.net Fri Sep 29 19:55:49 2006 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Fri, 29 Sep 2006 19:55:49 +0200 (CEST) Subject: [pypy-svn] r32753 - pypy/dist/pypy/translator/goal Message-ID: <20060929175549.CE4B810053@code0.codespeak.net> Author: xoraxax Date: Fri Sep 29 19:55:49 2006 New Revision: 32753 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Now we just have a normal LLVM build, no strdicts for LLVM to keep the runtime short. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Fri Sep 29 19:55:49 2006 @@ -147,7 +147,7 @@ def main(backends=[]): if backends == []: #_ prefix means target specific option #backends = """llvm at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++""".split('@') - backends = """llvm--objspace-std-withstrdict at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++ at c--objspace-std-withstrdict@c--profopt='-c "from richards import *;main(iterations=1)"'""".split('@') + backends = """llvm at c@c--gc=framework at c--_thread@c--stackless at c--gc=framework--cc=c++ at c--cc=c++ at c--objspace-std-withstrdict@c--profopt='-c "from richards import *;main(iterations=1)"'""".split('@') #backends = 'llvm c c--gc=framework c--_thread c--stackless'.split() #backends = 'llvm c c--gc=framework c--new-stackless c--_thread'.split() #backends = 'llvm c c--stackless c--_thread c--stackless--_thread'.split() From ericvrp at codespeak.net Fri Sep 29 21:52:14 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Sep 2006 21:52:14 +0200 (CEST) Subject: [pypy-svn] r32754 - pypy/dist/pypy/translator/goal Message-ID: <20060929195214.A8F8F10036@code0.codespeak.net> Author: ericvrp Date: Fri Sep 29 21:52:13 2006 New Revision: 32754 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: some changes in the ~pypytester working copy that were not yet checked in Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Fri Sep 29 21:52:13 2006 @@ -134,14 +134,29 @@ os.chmod(realname, stat.S_IRWXU) os.unlink(basename) +def get_load(): + g = os.popen('uptime', 'r') + buf = g.read().strip() + g.close() + return buf + def benchmark(): #run('cat /proc/cpuinfo') #run('free') os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal') - run('/usr/local/bin/python bench-unix.py 2>&1 | tee benchmark.txt' % locals()) - run('echo "
"    >  benchmark.html')
-    run('cat benchmark.txt           >> benchmark.html')
-    run('echo "
" >> benchmark.html') + startload = get_load() + run('/usr/local/bin/withlock /tmp/cpu_cycles_lock /usr/local/bin/python bench-unix.py 2>&1 | tee benchmark.txt' % locals()) + endload = get_load() + f = open('benchmark.html', 'w') + print >> f, "" + print >> f, "
"
+    print >> f, "Benchmark started:", startload
+    print >> f, "            ended:", endload
+    print >> f
+    f.write(open('benchmark.txt').read())
+    print >> f, "
" + print >> f, "" + f.close() #run('scp benchmark.html ericvrp at codespeak.net:public_html/benchmark/index.html') def main(backends=[]): @@ -167,4 +182,7 @@ print 80*'-' if __name__ == '__main__': - main(sys.argv[1:]) + if sys.argv[1:] == ['--benchmark-only']: + benchmark() + else: + main(sys.argv[1:]) From cfbolz at codespeak.net Fri Sep 29 22:47:29 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Sep 2006 22:47:29 +0200 (CEST) Subject: [pypy-svn] r32755 - in pypy/branch/even-more-config/pypy/config: . test Message-ID: <20060929204729.7176610053@code0.codespeak.net> Author: cfbolz Date: Fri Sep 29 22:47:27 2006 New Revision: 32755 Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py Log: some simple translation options Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/pypyoption.py (original) +++ pypy/branch/even-more-config/pypy/config/pypyoption.py Fri Sep 29 22:47:27 2006 @@ -101,6 +101,29 @@ BoolOption("translating", "indicates whether we are translating currently", default=False, cmdline=None), + + OptionDescription("translation", "Translation Options", [ + BoolOption("stackless", "compile stackless features in", + default=False, cmdline="--stackless", + requires=[("translation.typesystem", "lltype")]), + ChoiceOption("typesystem", "Type system to use when RTyping", + ["lltype", "ootype"], "lltype", cmdline=None), + ChoiceOption("backend", "Backend to use for code generation", + ["c", "llvm", "cli", "js", "squeak", "cl"], "c", + cmdline="--gc", + requires={ + "c": [("translation.typesystem", "lltype")], + "llvm": [("translation.typesystem", "lltype")], + "cli": [("translation.typesystem", "ootype")], + "js": [("translation.typesystem", "ootype")], + "squeak": [("translation.typesystem", "ootype")], + "cl": [("translation.typesystem", "ootype")], + }), + ChoiceOption("gc", "Garbage Collection Strategy", + ["boehm", "ref", "framework", "none", "stacklessgc"], + "boehm", requires={ + "stacklessgc": [("translation.stackless", True)]}) + ]) ]) Modified: pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py (original) +++ pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py Fri Sep 29 22:47:27 2006 @@ -24,3 +24,9 @@ conf = Config(pypy_optiondescription) conf.objspace.name = "logic" assert not conf.objspace.geninterp + +def test_stacklessgc_required(): + conf = Config(pypy_optiondescription) + conf.translation.gc = "stacklessgc" + assert conf.translation.stackless + assert conf.translation.typesystem == "lltype" From cfbolz at codespeak.net Sat Sep 30 00:36:18 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 00:36:18 +0200 (CEST) Subject: [pypy-svn] r32756 - in pypy/branch/even-more-config/pypy: config objspace/flow objspace/flow/test translator Message-ID: <20060929223618.EFCBE10071@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 00:36:09 2006 New Revision: 32756 Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py pypy/branch/even-more-config/pypy/objspace/flow/flowcontext.py pypy/branch/even-more-config/pypy/objspace/flow/objspace.py pypy/branch/even-more-config/pypy/objspace/flow/specialcase.py pypy/branch/even-more-config/pypy/objspace/flow/test/test_objspace.py pypy/branch/even-more-config/pypy/translator/driver.py pypy/branch/even-more-config/pypy/translator/geninterplevel.py pypy/branch/even-more-config/pypy/translator/translator.py Log: start to use config objects in the TranslationContext and the flow object space. Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/pypyoption.py (original) +++ pypy/branch/even-more-config/pypy/config/pypyoption.py Sat Sep 30 00:36:09 2006 @@ -122,7 +122,20 @@ ChoiceOption("gc", "Garbage Collection Strategy", ["boehm", "ref", "framework", "none", "stacklessgc"], "boehm", requires={ - "stacklessgc": [("translation.stackless", True)]}) + "stacklessgc": [("translation.stackless", True)]}), + + BoolOption("verbose", "Print extra information", default=False), + + # Flags of the TranslationContext: + BoolOption("verbose", "Print extra information", default=False), + BoolOption("simplifying", "Simplify flow graphs", default=True), + BoolOption("do_imports_immediately", "XXX", default=True, + cmdline=None), + BoolOption("builtins_can_raise_exceptions", "XXX", default=False, + cmdline=None), + BoolOption("list_comprehension_operations", "XXX", default=False, + cmdline=None), + ]) ]) Modified: pypy/branch/even-more-config/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/branch/even-more-config/pypy/objspace/flow/flowcontext.py (original) +++ pypy/branch/even-more-config/pypy/objspace/flow/flowcontext.py Sat Sep 30 00:36:09 2006 @@ -281,7 +281,7 @@ except OperationError, e: #print "OE", e.w_type, e.w_value - if (self.space.do_imports_immediately and + if (self.space.config.translation.do_imports_immediately and e.w_type is self.space.w_ImportError): raise ImportError('import statement always raises %s' % ( e,)) Modified: pypy/branch/even-more-config/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/branch/even-more-config/pypy/objspace/flow/objspace.py (original) +++ pypy/branch/even-more-config/pypy/objspace/flow/objspace.py Sat Sep 30 00:36:09 2006 @@ -34,9 +34,6 @@ full_exceptions = False - builtins_can_raise_exceptions = False - do_imports_immediately = True - def initialize(self): import __builtin__ self.concrete_mode = 1 @@ -424,7 +421,7 @@ exceptions = [Exception] # *any* exception by default if isinstance(w_callable, Constant): c = w_callable.value - if not self.builtins_can_raise_exceptions: + if not self.config.translation.builtins_can_raise_exceptions: if (isinstance(c, (types.BuiltinFunctionType, types.BuiltinMethodType, types.ClassType, Modified: pypy/branch/even-more-config/pypy/objspace/flow/specialcase.py ============================================================================== --- pypy/branch/even-more-config/pypy/objspace/flow/specialcase.py (original) +++ pypy/branch/even-more-config/pypy/objspace/flow/specialcase.py Sat Sep 30 00:36:09 2006 @@ -11,7 +11,7 @@ # import * in a function gives us the locals as Variable # we always forbid it as a SyntaxError raise SyntaxError, "RPython: import * is not allowed in functions" - if space.do_imports_immediately: + if space.config.translation.do_imports_immediately: name, glob, loc, frm = (space.unwrap(w_name), space.unwrap(w_glob), space.unwrap(w_loc), space.unwrap(w_frm)) try: @@ -36,7 +36,7 @@ else: raise Exception, "should call %r with exactly %d arguments" % ( fn, Arity[opname]) - if space.builtins_can_raise_exceptions: + if space.config.translation.builtins_can_raise_exceptions: # in this mode, avoid constant folding and raise an implicit Exception w_result = space.do_operation(opname, *args_w) space.handle_implicit_exceptions([Exception]) Modified: pypy/branch/even-more-config/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/branch/even-more-config/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/branch/even-more-config/pypy/objspace/flow/test/test_objspace.py Sat Sep 30 00:36:09 2006 @@ -713,9 +713,9 @@ class TestFlowObjSpaceDelay(Base): - def setup_class(cls): + def setup_class(cls): cls.space = FlowObjSpace() - cls.space.do_imports_immediately = False + cls.space.config.translation.do_imports_immediately = False def test_import_something(self): def f(): Modified: pypy/branch/even-more-config/pypy/translator/driver.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/driver.py (original) +++ pypy/branch/even-more-config/pypy/translator/driver.py Sat Sep 30 00:36:09 2006 @@ -176,7 +176,7 @@ if empty_translator: # set verbose flags - empty_translator.flags['verbose'] = True + empty_translator.config.translation.verbose = True translator = empty_translator else: translator = TranslationContext(verbose=True) Modified: pypy/branch/even-more-config/pypy/translator/geninterplevel.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/geninterplevel.py (original) +++ pypy/branch/even-more-config/pypy/translator/geninterplevel.py Sat Sep 30 00:36:09 2006 @@ -64,13 +64,6 @@ uniquemodulename, C_IDENTIFIER, NameManager -# list of simplifcation passes needed by geninterp -from pypy.translator.simplify import transform_ovfcheck, all_passes as needed_passes - -needed_passes = needed_passes[:] -needed_passes.remove(transform_ovfcheck) - - import pypy # __path__ import py.path from pypy.tool.ansi_print import ansi_log @@ -1487,7 +1480,7 @@ sys.path.remove(libdir) entrypoint = dic - t = TranslationContext(verbose=False, simplifying=needed_passes, + t = TranslationContext(verbose=False, simplifying=True, do_imports_immediately=do_imports_immediately, builtins_can_raise_exceptions=True, list_comprehension_operations=False) Modified: pypy/branch/even-more-config/pypy/translator/translator.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/translator.py (original) +++ pypy/branch/even-more-config/pypy/translator/translator.py Sat Sep 30 00:36:09 2006 @@ -12,9 +12,9 @@ from pypy.tool.ansi_print import ansi_log from pypy.tool.sourcetools import nice_repr_for_func import py -log = py.log.Producer("flowgraph") -py.log.setconsumer("flowgraph", ansi_log) - +log = py.log.Producer("flowgraph") +py.log.setconsumer("flowgraph", ansi_log) + class TranslationContext(object): FLOWING_FLAGS = { 'verbose': False, @@ -24,11 +24,18 @@ 'list_comprehension_operations': False, # True, - not super-tested } - def __init__(self, **flowing_flags): - self.flags = self.FLOWING_FLAGS.copy() - self.flags.update(flowing_flags) - if len(self.flags) > len(self.FLOWING_FLAGS): - raise TypeError("unexpected keyword argument") + def __init__(self, config=None, **flowing_flags): + if config is None: + from pypy.config.config import Config + from pypy.config.pypyoption import pypy_optiondescription + config = Config(pypy_optiondescription) + # ZZZ should go away in the end + for attr in ['verbose', 'simplifying', 'do_imports_immediately', + 'builtins_can_raise_exceptions', + 'list_comprehension_operations']: + if attr in flowing_flags: + setattr(config.translation, attr, flowing_flags[attr]) + self.config = config self.annotator = None self.rtyper = None self.exceptiontransformer = None @@ -47,18 +54,18 @@ if func in self._prebuilt_graphs: graph = self._prebuilt_graphs.pop(func) else: - if self.flags.get('verbose'): + if self.config.translation.verbose: log.start(nice_repr_for_func(func)) - space = FlowObjSpace() - space.__dict__.update(self.flags) # xxx push flags there + space = FlowObjSpace(self.config) if self.annotator: + # ZZZ self.annotator.policy._adjust_space_config(space) graph = space.build_flow(func) - if self.flags.get('simplifying'): + if self.config.translation.simplifying: simplify.simplify_graph(graph) - if self.flags.get('list_comprehension_operations'): + if self.config.translation.list_comprehension_operations: simplify.detect_list_comprehension(graph) - if self.flags.get('verbose'): + if self.config.translation.verbose: log.done(func.__name__) self.graphs.append(graph) # store the graph in our list return graph From cfbolz at codespeak.net Sat Sep 30 01:24:28 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 01:24:28 +0200 (CEST) Subject: [pypy-svn] r32757 - in pypy/branch/even-more-config/pypy: config translator translator/backendopt Message-ID: <20060929232428.45B2C10053@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 01:24:25 2006 New Revision: 32757 Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py pypy/branch/even-more-config/pypy/translator/backendopt/all.py pypy/branch/even-more-config/pypy/translator/driver.py Log: make it possible to use options to change the backend optimizations Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/pypyoption.py (original) +++ pypy/branch/even-more-config/pypy/config/pypyoption.py Sat Sep 30 01:24:25 2006 @@ -136,6 +136,27 @@ BoolOption("list_comprehension_operations", "XXX", default=False, cmdline=None), + OptionDescription("backendopt", "Backend Optimization Options", [ + BoolOption("print_statistics", "Print statistics while optimizing", + default=False), + BoolOption("merge_if_blocks", "Remove mallocs", default=True), + BoolOption("raisingop2direct_call", + "Transform exception raising operations", + default=False, cmdline="--raisingop2direct_call"), + BoolOption("mallocs", "Remove mallocs", default=True), + BoolOption("merge_if_blocks", "Remove mallocs", default=True), + BoolOption("propagate", "Constant propagation, deprecated", + default=False), + BoolOption("constfold", "Constant propagation", + default=True), + BoolOption("heap2stack", "Escape analysis and stack allocation", + default=False, + requires=[("translation.stackless", False)]), + BoolOption("clever_malloc_removal", + "Remove mallocs in a clever way", default=False), + IntOption("inline_threshold", "Threshold when to inline functions", + default=1, cmdline=None), + ]), ]) ]) Modified: pypy/branch/even-more-config/pypy/translator/backendopt/all.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/backendopt/all.py (original) +++ pypy/branch/even-more-config/pypy/translator/backendopt/all.py Sat Sep 30 01:24:25 2006 @@ -12,8 +12,6 @@ from pypy.translator.backendopt.support import log from pypy.objspace.flow.model import checkgraph -PRINT_STATISTICS = False - def backend_optimizations(translator, graphs=None, raisingop2direct_call_all=False, inline_threshold=1, @@ -24,10 +22,22 @@ heap2stack=False, clever_malloc_removal=False): + config = translator.config.translation.backendopt + # ZZZ the arguments here should disappear + raisingop2direct_call_all = (config.raisingop2direct_call or + raisingop2direct_call_all) + mallocs = config.mallocs or mallocs + merge_if_blocks_to_switch = (config.merge_if_blocks or + merge_if_blocks_to_switch) + propagate = config.propagate or propagate + constfold = config.propagate or propagate + heap2stack = config.heap2stack or heap2stack + clever_malloc_removal = config.clever_malloc_removal or clever_malloc_removal + if graphs is None: graphs = translator.graphs - if PRINT_STATISTICS: + if config.print_statistics: print "before optimizations:" print_statistics(translator.graphs[0], translator, "per-graph.txt") @@ -41,7 +51,7 @@ simplify.transform_dead_op_vars(graph, translator) removenoops.remove_duplicate_casts(graph, translator) - if PRINT_STATISTICS: + if config.print_statistics: print "after no-op removal:" print_statistics(translator.graphs[0], translator) @@ -60,7 +70,7 @@ removenoops.remove_superfluous_keep_alive(graph) removenoops.remove_duplicate_casts(graph, translator) - if PRINT_STATISTICS: + if config.print_statistics: print "after inlining:" print_statistics(translator.graphs[0], translator) @@ -77,14 +87,14 @@ tot += count log.malloc("removed %d simple mallocs in total" % tot) - if PRINT_STATISTICS: + if config.print_statistics: print "after malloc removal:" print_statistics(translator.graphs[0], translator) else: assert graphs is translator.graphs # XXX for now clever_inlining_and_malloc_removal(translator) - if PRINT_STATISTICS: + if config.print_statistics: print "after clever inlining and malloc removal" print_statistics(translator.graphs[0], translator) @@ -104,7 +114,7 @@ for graph in graphs: merge_if_blocks(graph) - if PRINT_STATISTICS: + if config.print_statistics: print "after if-to-switch:" print_statistics(translator.graphs[0], translator) Modified: pypy/branch/even-more-config/pypy/translator/driver.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/driver.py (original) +++ pypy/branch/even-more-config/pypy/translator/driver.py Sat Sep 30 01:24:25 2006 @@ -274,7 +274,7 @@ raisingop2direct_call_all=opt.raisingop2direct_call, merge_if_blocks_to_switch=opt.merge_if_blocks) # - task_backendopt_lltype = taskdef(task_backendopt_lltype, + task_backendopt_lltype = taskdef(task_backendopt_lltype, [RTYPE], "Back-end optimisations") BACKENDOPT = 'backendopt_lltype' From cfbolz at codespeak.net Sat Sep 30 01:45:02 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 01:45:02 +0200 (CEST) Subject: [pypy-svn] r32758 - pypy/branch/even-more-config/pypy/translator Message-ID: <20060929234502.9EAEF10053@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 01:44:59 2006 New Revision: 32758 Modified: pypy/branch/even-more-config/pypy/translator/driver.py Log: whitespace Modified: pypy/branch/even-more-config/pypy/translator/driver.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/driver.py (original) +++ pypy/branch/even-more-config/pypy/translator/driver.py Sat Sep 30 01:44:59 2006 @@ -102,7 +102,7 @@ if task in ('rtype', 'backendopt', 'llinterpret'): if ts: if ts == postfix: - expose_task(task, explicit_task) + expose_task(task, explicit_task) else: expose_task(explicit_task) elif task in ('source', 'compile', 'run'): @@ -167,7 +167,7 @@ self.inputtypes = inputtypes if policy is None: - policy = annpolicy.AnnotatorPolicy() + policy = annpolicy.AnnotatorPolicy() if standalone: policy.allow_someobjects = False self.policy = policy From cfbolz at codespeak.net Sat Sep 30 02:22:56 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 02:22:56 +0200 (CEST) Subject: [pypy-svn] r32759 - in pypy/branch/even-more-config/pypy/config: . test Message-ID: <20060930002256.78D3910053@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 02:22:54 2006 New Revision: 32759 Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py Log: rename typesystem to type_system (which seems more common). add some more config options. Modified: pypy/branch/even-more-config/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/pypyoption.py (original) +++ pypy/branch/even-more-config/pypy/config/pypyoption.py Sat Sep 30 02:22:54 2006 @@ -105,26 +105,32 @@ OptionDescription("translation", "Translation Options", [ BoolOption("stackless", "compile stackless features in", default=False, cmdline="--stackless", - requires=[("translation.typesystem", "lltype")]), - ChoiceOption("typesystem", "Type system to use when RTyping", - ["lltype", "ootype"], "lltype", cmdline=None), + requires=[("translation.type_system", "lltype")]), + ChoiceOption("type_system", "Type system to use when RTyping", + [None, "lltype", "ootype"], "lltype", cmdline=None), ChoiceOption("backend", "Backend to use for code generation", - ["c", "llvm", "cli", "js", "squeak", "cl"], "c", - cmdline="--gc", + [None, "c", "llvm", "cli", "js", "squeak", "cl"], "c", requires={ - "c": [("translation.typesystem", "lltype")], - "llvm": [("translation.typesystem", "lltype")], - "cli": [("translation.typesystem", "ootype")], - "js": [("translation.typesystem", "ootype")], - "squeak": [("translation.typesystem", "ootype")], - "cl": [("translation.typesystem", "ootype")], + "c": [("translation.type_system", "lltype")], + "llvm": [("translation.type_system", "lltype")], + "cli": [("translation.type_system", "ootype")], + "js": [("translation.type_system", "ootype")], + "squeak": [("translation.type_system", "ootype")], + "cl": [("translation.type_system", "ootype")], }), ChoiceOption("gc", "Garbage Collection Strategy", ["boehm", "ref", "framework", "none", "stacklessgc"], "boehm", requires={ - "stacklessgc": [("translation.stackless", True)]}), + "stacklessgc": [("translation.stackless", True)]}, + cmdline="--gc"), + BoolOption("thread", "enable use of threading primitives", + default=False), BoolOption("verbose", "Print extra information", default=False), + BoolOption("insist", "Try hard to go on RTyping", default=False), + BoolOption("lowmem", "Try to use little memory during translation", + default=False, cmdline="--lowmem"), + # Flags of the TranslationContext: BoolOption("verbose", "Print extra information", default=False), Modified: pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py (original) +++ pypy/branch/even-more-config/pypy/config/test/test_pypyoption.py Sat Sep 30 02:22:54 2006 @@ -29,4 +29,4 @@ conf = Config(pypy_optiondescription) conf.translation.gc = "stacklessgc" assert conf.translation.stackless - assert conf.translation.typesystem == "lltype" + assert conf.translation.type_system == "lltype" From cfbolz at codespeak.net Sat Sep 30 02:38:17 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 02:38:17 +0200 (CEST) Subject: [pypy-svn] r32760 - pypy/branch/even-more-config/pypy/translator Message-ID: <20060930003817.E22CA10053@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 02:38:06 2006 New Revision: 32760 Modified: pypy/branch/even-more-config/pypy/translator/driver.py Log: mini-steps in using options in the driver. Modified: pypy/branch/even-more-config/pypy/translator/driver.py ============================================================================== --- pypy/branch/even-more-config/pypy/translator/driver.py (original) +++ pypy/branch/even-more-config/pypy/translator/driver.py Sat Sep 30 02:38:06 2006 @@ -57,14 +57,42 @@ class TranslationDriver(SimpleTaskEngine): def __init__(self, options=None, default_goal=None, disable=[], - exe_name=None, extmod_name=None): + exe_name=None, extmod_name=None, + config=None): SimpleTaskEngine.__init__(self) self.log = log + if config is None: + from pypy.config.config import Config + from pypy.config.pypyoption import pypy_optiondescription + config = Config(pypy_optiondescription) + self.config = config + + # YYY the option argument should disappear if options is None: options = _default_options + else: + # move options over to config + + # YYY debug + # YYY fork_before + # YYY debug_transform + tconf = config.translation + tconf.gc = options.gc + tconf.thread = options.thread + tconf.stackless = options.stackless + tconf.backend = options.backend + tconf.type_system = options.type_system + tconf.insist = options.insist + tconf.lowmem = options.lowmem + tconf.backendopt.merge_if_blocks = options.merge_if_blocks + tconf.backendopt.raisingop2direct_call = ( + options.raisingop2direct_call) + + self.options = options + self.exe_name = exe_name self.extmod_name = extmod_name @@ -179,7 +207,7 @@ empty_translator.config.translation.verbose = True translator = empty_translator else: - translator = TranslationContext(verbose=True) + translator = TranslationContext(config=self.config, verbose=True) self.entry_point = entry_point self.translator = translator @@ -249,30 +277,27 @@ def task_rtype_lltype(self): - opt = self.options rtyper = self.translator.buildrtyper(type_system='lltype') + insist = not self.config.translation.insist rtyper.specialize(dont_simplify_again=True, - crash_on_first_typeerror=not opt.insist) + crash_on_first_typeerror=insist) # task_rtype_lltype = taskdef(task_rtype_lltype, ['annotate'], "RTyping") RTYPE = 'rtype_lltype' def task_rtype_ootype(self): # Maybe type_system should simply be an option used in task_rtype - opt = self.options + insist = not self.config.translation.insist rtyper = self.translator.buildrtyper(type_system="ootype") rtyper.specialize(dont_simplify_again=True, - crash_on_first_typeerror=not opt.insist) + crash_on_first_typeerror=insist) # task_rtype_ootype = taskdef(task_rtype_ootype, ['annotate'], "ootyping") OOTYPE = 'rtype_ootype' def task_backendopt_lltype(self): from pypy.translator.backendopt.all import backend_optimizations - opt = self.options - backend_optimizations(self.translator, - raisingop2direct_call_all=opt.raisingop2direct_call, - merge_if_blocks_to_switch=opt.merge_if_blocks) + backend_optimizations(self.translator) # task_backendopt_lltype = taskdef(task_backendopt_lltype, [RTYPE], "Back-end optimisations") @@ -290,7 +315,6 @@ def task_database_c(self): translator = self.translator - opt = self.options if translator.annotator is not None: translator.frozen = True @@ -301,9 +325,9 @@ else: from pypy.translator.c.genc import CExtModuleBuilder as CBuilder cbuilder = CBuilder(self.translator, self.entry_point, - gcpolicy = opt.gc, - thread_enabled = getattr(opt, 'thread', False)) - cbuilder.stackless = opt.stackless + gcpolicy = self.config.translation.gc, + thread_enabled = self.config.translation.thread) + cbuilder.stackless = self.config.translation.stackless if not standalone: # xxx more messy cbuilder.modulename = self.extmod_name database = cbuilder.build_database() @@ -385,14 +409,14 @@ def task_source_llvm(self): translator = self.translator - opts = self.options if translator.annotator is None: raise ValueError, "llvm requires annotation." from pypy.translator.llvm import genllvm # XXX Need more options for policies/llvm-backendoptions here? - self.llvmgen = genllvm.GenLLVM(translator, self.options.gc, self.standalone) + self.llvmgen = genllvm.GenLLVM(translator, self.config.translation.gc, + self.standalone) llvm_filename = self.llvmgen.gen_llvm_source(self.entry_point) self.log.info("written: %s" % (llvm_filename,)) @@ -460,7 +484,8 @@ def task_source_js(self): from pypy.translator.js.js import JS self.gen = JS(self.translator, functions=[self.entry_point], - stackless=self.options.stackless, use_debug=self.options.debug_transform) + stackless=self.config.translation.stackless, + use_debug=self.options.debug_transform) filename = self.gen.write_source() self.log.info("Wrote %s" % (filename,)) task_source_js = taskdef(task_source_js, @@ -519,13 +544,12 @@ goals = self.backend_select_goals(goals) return self._execute(goals, task_skip = self._maybe_skip()) - def from_targetspec(targetspec_dic, options=None, args=None, empty_translator=None, + def from_targetspec(targetspec_dic, options=None, args=None, + empty_translator=None, disable=[], default_goal=None): if args is None: args = [] - if options is None: - options = _default_options driver = TranslationDriver(options, default_goal, disable) # patch some attributes of the os module to make sure they From arigo at codespeak.net Sat Sep 30 09:57:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Sep 2006 09:57:50 +0200 (CEST) Subject: [pypy-svn] r32761 - pypy/dist/pypy/tool/algo Message-ID: <20060930075750.E214410053@code0.codespeak.net> Author: arigo Date: Sat Sep 30 09:57:48 2006 New Revision: 32761 Modified: pypy/dist/pypy/tool/algo/sparsemat.py Log: Be even more careful in 'del'. Modified: pypy/dist/pypy/tool/algo/sparsemat.py ============================================================================== --- pypy/dist/pypy/tool/algo/sparsemat.py (original) +++ pypy/dist/pypy/tool/algo/sparsemat.py Sat Sep 30 09:57:48 2006 @@ -60,9 +60,8 @@ if abs(value) > EPSILON: line2[col] = columns[col][i] = value else: - if col in line2: - del line2[col] - del columns[col][i] + line2.pop(col, 0) + columns[col].pop(i, 0) solution = [None] * len(vector) for i in range(len(vector)-1, -1, -1): row = nrows[i] From mwh at codespeak.net Sat Sep 30 11:40:54 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 30 Sep 2006 11:40:54 +0200 (CEST) Subject: [pypy-svn] r32762 - in pypy/dist/pypy/translator: c llvm Message-ID: <20060930094054.6805F10053@code0.codespeak.net> Author: mwh Date: Sat Sep 30 11:40:52 2006 New Revision: 32762 Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/llvm/database.py Log: revert stuff accidentally checked in when i removed the l3interp. (it was a half-hearted attempt to make llvm's test_gc pass) Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sat Sep 30 11:40:52 2006 @@ -36,7 +36,6 @@ self.containerstats = {} self.externalfuncs = {} self.helper2ptr = {} - self.raisingop2direct = True # late_initializations is for when the value you want to # assign to a constant object is something C doesn't think is Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sat Sep 30 11:40:52 2006 @@ -46,10 +46,6 @@ if db.stacklesstransformer: db.stacklesstransformer.transform_graph(graph) # apply the exception transformation - if self.db.raisingop2direct: - from pypy.translator.backendopt.raisingop2direct_call import raisingop2direct_call - raisingop2direct_call(db.translator, [graph]) - if self.db.exctransformer: self.db.exctransformer.create_exception_handling(self.graph) # apply the gc transformation Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sat Sep 30 11:40:52 2006 @@ -142,8 +142,6 @@ # actually generating the source. if db is None: db = self.build_database() - from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(self.translator, raisingop2direct_call_all=True) for node in db.containerlist: if isinstance(node, FuncNode): for funcgen in node.funcgens: Modified: pypy/dist/pypy/translator/llvm/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm/database.py (original) +++ pypy/dist/pypy/translator/llvm/database.py Sat Sep 30 11:40:52 2006 @@ -560,12 +560,7 @@ elif isinstance(value, llmemory.CompositeOffset): from_, indices, to = self.get_offset(value.offsets[0], indices) for item in value.offsets[1:]: - if not isinstance(item, llmemory.GCHeaderOffset): - _, indices, to = self.get_offset(item, indices) - - elif isinstance(value, llmemory.GCHeaderOffset): - from_ = lltype.Ptr(value.gcheaderbuilder.HDR) - to = "BBB" # better not use this! + _, indices, to = self.get_offset(item, indices) else: raise Exception("unsupported offset") From cfbolz at codespeak.net Sat Sep 30 12:32:48 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 12:32:48 +0200 (CEST) Subject: [pypy-svn] r32763 - pypy/branch/even-more-config/pypy/config Message-ID: <20060930103248.B0D9110060@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 12:32:47 2006 New Revision: 32763 Modified: pypy/branch/even-more-config/pypy/config/config.py Log: add prefix '_cprefix' to all internal attributes to avoid name clashes with attributes that really start with _. Modified: pypy/branch/even-more-config/pypy/config/config.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/config.py (original) +++ pypy/branch/even-more-config/pypy/config/config.py Sat Sep 30 12:32:47 2006 @@ -2,29 +2,33 @@ from py.compat import optparse class Config(object): - _frozen = False + _cprefix_frozen = False def __init__(self, descr, parent=None, **overrides): - self._descr = descr - self._value_owners = {} - self._parent = parent - self._build(overrides) + self._cprefix_descr = descr + self._cprefix_value_owners = {} + self._cprefix_parent = parent + self._cprefix_build(overrides) + self._cprefix_read = {} - def _build(self, overrides): - for child in self._descr._children: + def _cprefix_build(self, overrides): + for child in self._cprefix_descr._children: if isinstance(child, Option): self.__dict__[child._name] = child.default - self._value_owners[child._name] = 'default' + self._cprefix_value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): self.__dict__[child._name] = Config(child, parent=self) + self.override(overrides) + + def override(self, overrides): for name, value in overrides.iteritems(): - subconfig, name = self._get_by_path(name) + subconfig, name = self._cprefix_get_by_path(name) setattr(subconfig, name, value) def __setattr__(self, name, value): - if self._frozen: + if self._cprefix_frozen: raise TypeError("trying to change a frozen option object") - if name.startswith('_'): + if name.startswith('_cprefix_'): self.__dict__[name] = value return self.setoption(name, value, 'user') @@ -32,8 +36,8 @@ def setoption(self, name, value, who): if name not in self.__dict__: raise ValueError('unknown option %s' % (name,)) - child = getattr(self._descr, name) - oldowner = self._value_owners[child._name] + child = getattr(self._cprefix_descr, name) + oldowner = self._cprefix_value_owners[child._name] oldvalue = getattr(self, name) if oldowner == 'required': if oldvalue != value: @@ -41,29 +45,29 @@ (value, name)) return child.setoption(self, value) - self._value_owners[name] = who + self._cprefix_value_owners[name] = who def require(self, name, value): self.setoption(name, value, "required") - def _get_by_path(self, path): + def _cprefix_get_by_path(self, path): """returns tuple (config, name)""" path = path.split('.') for step in path[:-1]: self = getattr(self, step) return self, path[-1] - def _get_toplevel(self): - while self._parent is not None: - self = self._parent + def _cprefix_get_toplevel(self): + while self._cprefix_parent is not None: + self = self._cprefix_parent return self def _freeze_(self): - self.__dict__['_frozen'] = True + self.__dict__['_cprefix_frozen'] = True return True def getkey(self): - return self._descr.getkey(self) + return self._cprefix_descr.getkey(self) def __hash__(self): return hash(self.getkey()) @@ -75,15 +79,15 @@ return not self == other def __iter__(self): - for child in self._descr._children: + for child in self._cprefix_descr._children: if isinstance(child, Option): yield child._name, getattr(self, child._name) def __str__(self): result = "[%s]\n" % (self._descr._name, ) - for child in self._descr._children: + for child in self._cprefix_descr._children: if isinstance(child, Option): - if self._value_owners[child._name] == 'default': + if self._cprefix_value_owners[child._name] == 'default': continue result += " %s = %s\n" % ( child._name, getattr(self, child._name)) @@ -101,7 +105,7 @@ if currpath is None: currpath = [] paths = [] - for option in self._descr._children: + for option in self._cprefix_descr._children: attr = option._name if attr.startswith('_'): continue @@ -158,7 +162,8 @@ def setoption(self, config, value): name = self._name for path, reqvalue in self._requires.get(value, []): - subconfig, name = config._get_toplevel()._get_by_path(path) + toplevel = config._cprefix_get_toplevel() + subconfig, name = toplevel._cprefix_get_by_path(path) subconfig.require(name, reqvalue) super(ChoiceOption, self).setoption(config, value) @@ -301,14 +306,14 @@ for path in useoptions: if path.endswith(".*"): path = path[:-2] - subconf, name = config._get_by_path(path) + subconf, name = config._cprefix_get_by_path(path) children = [ path + "." + child._name - for child in getattr(subconf, name)._descr._children] + for child in getattr(subconf, name)._cprefix_descr._children] useoptions.extend(children) else: - subconf, name = config._get_by_path(path) - option = getattr(subconf._descr, name) + subconf, name = config._cprefix_get_by_path(path) + option = getattr(subconf._cprefix_descr, name) if option.cmdline is DEFAULT_OPTION_NAME: chunks = ('--%s' % (path.replace('.', '-'),),) elif option.cmdline is None: @@ -316,7 +321,7 @@ else: chunks = option.cmdline.split(' ') try: - grp = get_group(path, subconf._descr.doc) + grp = get_group(path, subconf._cprefix_descr.doc) option.add_optparse_option(chunks, grp, subconf) except ValueError: # an option group that does not only contain bool values From cfbolz at codespeak.net Sat Sep 30 13:18:33 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 13:18:33 +0200 (CEST) Subject: [pypy-svn] r32764 - in pypy/branch/even-more-config/pypy/config: . test Message-ID: <20060930111833.B39D010068@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 13:18:30 2006 New Revision: 32764 Modified: pypy/branch/even-more-config/pypy/config/config.py pypy/branch/even-more-config/pypy/config/test/test_config.py Log: don't store the values in the __dict__ anymore Modified: pypy/branch/even-more-config/pypy/config/config.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/config.py (original) +++ pypy/branch/even-more-config/pypy/config/config.py Sat Sep 30 13:18:30 2006 @@ -8,16 +8,17 @@ self._cprefix_descr = descr self._cprefix_value_owners = {} self._cprefix_parent = parent + self._cprefix_values = {} self._cprefix_build(overrides) self._cprefix_read = {} def _cprefix_build(self, overrides): for child in self._cprefix_descr._children: if isinstance(child, Option): - self.__dict__[child._name] = child.default + self._cprefix_values[child._name] = child.default self._cprefix_value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): - self.__dict__[child._name] = Config(child, parent=self) + self._cprefix_values[child._name] = Config(child, parent=self) self.override(overrides) def override(self, overrides): @@ -26,15 +27,21 @@ setattr(subconfig, name, value) def __setattr__(self, name, value): - if self._cprefix_frozen: + if self._cprefix_frozen and getattr(self, name) != value: raise TypeError("trying to change a frozen option object") if name.startswith('_cprefix_'): self.__dict__[name] = value return self.setoption(name, value, 'user') + def __getattr__(self, name): + if name not in self._cprefix_values: + raise AttributeError("%s object has no attribute %s" % + (self.__class__, name)) + return self._cprefix_values[name] + def setoption(self, name, value, who): - if name not in self.__dict__: + if name not in self._cprefix_values: raise ValueError('unknown option %s' % (name,)) child = getattr(self._cprefix_descr, name) oldowner = self._cprefix_value_owners[child._name] @@ -141,7 +148,7 @@ name = self._name if not self.validate(value): raise ValueError('invalid value %s for option %s' % (value, name)) - config.__dict__[name] = value + config._cprefix_values[name] = value def getkey(self, value): return value Modified: pypy/branch/even-more-config/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/test/test_config.py (original) +++ pypy/branch/even-more-config/pypy/config/test/test_config.py Sat Sep 30 13:18:30 2006 @@ -77,6 +77,8 @@ assert block.operations[0].opname == 'int_add' assert config._freeze_() + # does not raise, since it does not change the attribute + config.gc.name = "ref" py.test.raises(TypeError, 'config.gc.name = "framework"') def test_compare_configs(): From cfbolz at codespeak.net Sat Sep 30 13:20:58 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Sep 2006 13:20:58 +0200 (CEST) Subject: [pypy-svn] r32765 - pypy/branch/even-more-config/pypy/config Message-ID: <20060930112058.7381C1006F@code0.codespeak.net> Author: cfbolz Date: Sat Sep 30 13:20:55 2006 New Revision: 32765 Modified: pypy/branch/even-more-config/pypy/config/config.py Log: use cfgimpl as a prefix, as proposed by samuele Modified: pypy/branch/even-more-config/pypy/config/config.py ============================================================================== --- pypy/branch/even-more-config/pypy/config/config.py (original) +++ pypy/branch/even-more-config/pypy/config/config.py Sat Sep 30 13:20:55 2006 @@ -2,49 +2,48 @@ from py.compat import optparse class Config(object): - _cprefix_frozen = False + _cfgimpl_frozen = False def __init__(self, descr, parent=None, **overrides): - self._cprefix_descr = descr - self._cprefix_value_owners = {} - self._cprefix_parent = parent - self._cprefix_values = {} - self._cprefix_build(overrides) - self._cprefix_read = {} + self._cfgimpl_descr = descr + self._cfgimpl_value_owners = {} + self._cfgimpl_parent = parent + self._cfgimpl_values = {} + self._cfgimpl_build(overrides) - def _cprefix_build(self, overrides): - for child in self._cprefix_descr._children: + def _cfgimpl_build(self, overrides): + for child in self._cfgimpl_descr._children: if isinstance(child, Option): - self._cprefix_values[child._name] = child.default - self._cprefix_value_owners[child._name] = 'default' + self._cfgimpl_values[child._name] = child.default + self._cfgimpl_value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): - self._cprefix_values[child._name] = Config(child, parent=self) + self._cfgimpl_values[child._name] = Config(child, parent=self) self.override(overrides) def override(self, overrides): for name, value in overrides.iteritems(): - subconfig, name = self._cprefix_get_by_path(name) + subconfig, name = self._cfgimpl_get_by_path(name) setattr(subconfig, name, value) def __setattr__(self, name, value): - if self._cprefix_frozen and getattr(self, name) != value: + if self._cfgimpl_frozen and getattr(self, name) != value: raise TypeError("trying to change a frozen option object") - if name.startswith('_cprefix_'): + if name.startswith('_cfgimpl_'): self.__dict__[name] = value return self.setoption(name, value, 'user') def __getattr__(self, name): - if name not in self._cprefix_values: + if name not in self._cfgimpl_values: raise AttributeError("%s object has no attribute %s" % (self.__class__, name)) - return self._cprefix_values[name] + return self._cfgimpl_values[name] def setoption(self, name, value, who): - if name not in self._cprefix_values: + if name not in self._cfgimpl_values: raise ValueError('unknown option %s' % (name,)) - child = getattr(self._cprefix_descr, name) - oldowner = self._cprefix_value_owners[child._name] + child = getattr(self._cfgimpl_descr, name) + oldowner = self._cfgimpl_value_owners[child._name] oldvalue = getattr(self, name) if oldowner == 'required': if oldvalue != value: @@ -52,29 +51,29 @@ (value, name)) return child.setoption(self, value) - self._cprefix_value_owners[name] = who + self._cfgimpl_value_owners[name] = who def require(self, name, value): self.setoption(name, value, "required") - def _cprefix_get_by_path(self, path): + def _cfgimpl_get_by_path(self, path): """returns tuple (config, name)""" path = path.split('.') for step in path[:-1]: self = getattr(self, step) return self, path[-1] - def _cprefix_get_toplevel(self): - while self._cprefix_parent is not None: - self = self._cprefix_parent + def _cfgimpl_get_toplevel(self): + while self._cfgimpl_parent is not None: + self = self._cfgimpl_parent return self def _freeze_(self): - self.__dict__['_cprefix_frozen'] = True + self.__dict__['_cfgimpl_frozen'] = True return True def getkey(self): - return self._cprefix_descr.getkey(self) + return self._cfgimpl_descr.getkey(self) def __hash__(self): return hash(self.getkey()) @@ -86,15 +85,15 @@ return not self == other def __iter__(self): - for child in self._cprefix_descr._children: + for child in self._cfgimpl_descr._children: if isinstance(child, Option): yield child._name, getattr(self, child._name) def __str__(self): result = "[%s]\n" % (self._descr._name, ) - for child in self._cprefix_descr._children: + for child in self._cfgimpl_descr._children: if isinstance(child, Option): - if self._cprefix_value_owners[child._name] == 'default': + if self._cfgimpl_value_owners[child._name] == 'default': continue result += " %s = %s\n" % ( child._name, getattr(self, child._name)) @@ -112,7 +111,7 @@ if currpath is None: currpath = [] paths = [] - for option in self._cprefix_descr._children: + for option in self._cfgimpl_descr._children: attr = option._name if attr.startswith('_'): continue @@ -148,7 +147,7 @@ name = self._name if not self.validate(value): raise ValueError('invalid value %s for option %s' % (value, name)) - config._cprefix_values[name] = value + config._cfgimpl_values[name] = value def getkey(self, value): return value @@ -169,8 +168,8 @@ def setoption(self, config, value): name = self._name for path, reqvalue in self._requires.get(value, []): - toplevel = config._cprefix_get_toplevel() - subconfig, name = toplevel._cprefix_get_by_path(path) + toplevel = config._cfgimpl_get_toplevel() + subconfig, name = toplevel._cfgimpl_get_by_path(path) subconfig.require(name, reqvalue) super(ChoiceOption, self).setoption(config, value) @@ -313,14 +312,14 @@ for path in useoptions: if path.endswith(".*"): path = path[:-2] - subconf, name = config._cprefix_get_by_path(path) + subconf, name = config._cfgimpl_get_by_path(path) children = [ path + "." + child._name - for child in getattr(subconf, name)._cprefix_descr._children] + for child in getattr(subconf, name)._cfgimpl_descr._children] useoptions.extend(children) else: - subconf, name = config._cprefix_get_by_path(path) - option = getattr(subconf._cprefix_descr, name) + subconf, name = config._cfgimpl_get_by_path(path) + option = getattr(subconf._cfgimpl_descr, name) if option.cmdline is DEFAULT_OPTION_NAME: chunks = ('--%s' % (path.replace('.', '-'),),) elif option.cmdline is None: @@ -328,7 +327,7 @@ else: chunks = option.cmdline.split(' ') try: - grp = get_group(path, subconf._cprefix_descr.doc) + grp = get_group(path, subconf._cfgimpl_descr.doc) option.add_optparse_option(chunks, grp, subconf) except ValueError: # an option group that does not only contain bool values From arigo at codespeak.net Sat Sep 30 16:36:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Sep 2006 16:36:45 +0200 (CEST) Subject: [pypy-svn] r32766 - pypy/dist/pypy/translator/c/src Message-ID: <20060930143645.4F2E710053@code0.codespeak.net> Author: arigo Date: Sat Sep 30 16:36:39 2006 New Revision: 32766 Modified: pypy/dist/pypy/translator/c/src/int.h Log: Add a missing operation. Most LLONG_*_OVF operations are still missing. Modified: pypy/dist/pypy/translator/c/src/int.h ============================================================================== --- pypy/dist/pypy/translator/c/src/int.h (original) +++ pypy/dist/pypy/translator/c/src/int.h Sat Sep 30 16:36:39 2006 @@ -2,6 +2,18 @@ /************************************************************/ /*** C header subsection: operations between ints ***/ +#ifndef LLONG_MAX +# if SIZEOF_LONG_LONG == 8 +# define LLONG_MAX 0X7FFFFFFFFFFFFFFFLL +# else +# error "fix LLONG_MAX" +# endif +#endif + +#ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX-1) +#endif + /*** unary operations ***/ #define OP_INT_IS_TRUE(x,r) OP_INT_NE(x,0,r) @@ -11,16 +23,20 @@ #define OP_INT_NEG(x,r) r = -(x) #define OP_INT_NEG_OVF(x,r) \ - OP_INT_NEG(x,r); \ - if ((x) >= 0 || (x) != -(x)); \ - else FAIL_OVF("integer negate") + if ((x) == LONG_MIN) FAIL_OVF("integer negate"); \ + OP_INT_NEG(x,r) +#define OP_LLONG_NEG_OVF(x,r) \ + if ((x) == LLONG_MIN) FAIL_OVF("integer negate"); \ + OP_LLONG_NEG(x,r) #define OP_INT_ABS(x,r) r = (x) >= 0 ? x : -(x) #define OP_INT_ABS_OVF(x,r) \ - OP_INT_ABS(x,r); \ - if ((x) >= 0 || (x) != -(x)); \ - else FAIL_OVF("integer absolute") + if ((x) == LONG_MIN) FAIL_OVF("integer absolute"); \ + OP_INT_ABS(x,r) +#define OP_LLONG_ABS_OVF(x,r) \ + if ((x) == LLONG_MIN) FAIL_OVF("integer absolute"); \ + OP_LLONG_ABS(x,r) /*** binary operations ***/ From arigo at codespeak.net Sat Sep 30 18:48:11 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Sep 2006 18:48:11 +0200 (CEST) Subject: [pypy-svn] r32767 - in pypy/dist/pypy/jit: codegen codegen/llgraph timeshifter timeshifter/test Message-ID: <20060930164811.C877410060@code0.codespeak.net> Author: arigo Date: Sat Sep 30 18:48:09 2006 New Revision: 32767 Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/model.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_promotion.py pypy/dist/pypy/jit/timeshifter/transform.py Log: (pedronis, arigo) Generate residual indirect calls when the target is not known at compile-time. (It's in test_promotion but it's not about promotion so far.) Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Sat Sep 30 18:48:09 2006 @@ -70,8 +70,12 @@ if gv_arg is not None: gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, gv_arg.v)) vars_gv.append(gv_arg) - # XXX indirect_call later - return LLVar(llimpl.genop(self.b, 'direct_call', vars_gv, gv_RESULT.v)) + if gv_callable.is_const: + v = llimpl.genop(self.b, 'direct_call', vars_gv, gv_RESULT.v) + else: + vars_gv.append(gv_dummy_placeholder) + v = llimpl.genop(self.b, 'indirect_call', vars_gv, gv_RESULT.v) + return LLVar(v) def genop_getfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr): vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v] Modified: pypy/dist/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/dist/pypy/jit/codegen/model.py Sat Sep 30 18:48:09 2006 @@ -1,11 +1,15 @@ from pypy.rpython.objectmodel import specialize +class NotConstant(Exception): + pass + + class GenVarOrConst(object): @specialize.arg(1) def revealconst(self, T): - raise NotImplementedError + raise NotConstant(self) class GenVar(GenVarOrConst): is_const = False Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Sat Sep 30 18:48:09 2006 @@ -321,6 +321,24 @@ ##def ll_gvar_from_constant(jitstate, ll_value): ## return jitstate.curbuilder.rgenop.genconst(ll_value) +class CallDesc: + __metaclass__ = cachedtype + + def __init__(self, RGenOp, FUNCTYPE): + self.sigtoken = RGenOp.sigToken(FUNCTYPE) + self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT) + self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT) + + def _freeze_(self): + return True + +def ll_gen_residual_call(jitstate, calldesc, funcbox): + builder = jitstate.curbuilder + gv_funcbox = funcbox.getgenvar(builder) + argboxes = jitstate.frame.local_boxes + args_gv = [argbox.getgenvar(builder) for argbox in argboxes] + gv_result = builder.genop_call(calldesc.sigtoken, gv_funcbox, args_gv) + return calldesc.redboxbuilder(calldesc.result_kind, gv_result) class ResumingInfo(object): Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sat Sep 30 18:48:09 2006 @@ -911,7 +911,6 @@ hop.llops.setjitstate(v_newjitstate) def translate_op_indirect_red_call(self, hop): - bk = self.annotator.bookkeeper v_jitstate = hop.llops.getjitstate() FUNC = originalconcretetype(hop.args_s[0]) v_func = hop.inputarg(self.getgreenrepr(FUNC), arg=0) @@ -935,6 +934,25 @@ translate_op_yellow_call = translate_op_red_call translate_op_indirect_yellow_call = translate_op_indirect_red_call + def translate_op_residual_red_call(self, hop, color='red'): + FUNC = originalconcretetype(hop.args_s[0]) + [v_funcbox] = hop.inputargs(self.getredrepr(FUNC)) + calldesc = rtimeshift.CallDesc(self.RGenOp, FUNC.TO) + c_calldesc = inputconst(lltype.Void, calldesc) + s_calldesc = self.rtyper.annotator.bookkeeper.immutablevalue(calldesc) + v_jitstate = hop.llops.getjitstate() + if color == 'red': + s_result = self.s_RedBox + else: + s_result = annmodel.s_None + return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gen_residual_call, + [self.s_JITState, s_calldesc, self.s_RedBox], + [v_jitstate, c_calldesc, v_funcbox ], + s_result) + + def translate_op_residual_gray_call(self, hop): + self.translate_op_residual_red_call(hop, color='gray') + class HintLowLevelOpList(LowLevelOpList): """Warning: the HintLowLevelOpList's rtyper is the *original* Modified: pypy/dist/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_promotion.py Sat Sep 30 18:48:09 2006 @@ -42,16 +42,36 @@ assert res == ll_function(10, 0) self.check_insns(int_add=10, int_mul=0) -## def test_method_call(self): -## class Base(object): -## pass -## class Int(Base): -## def __init__(self, n): -## self.n = n -## def double(self): -## return Int(self.n * 2) -## class Str(Base): -## def __init__(self, s): -## self.s = s -## def double(self): -## return Str(self.s + self.s) + def test_method_call_nonpromote(self): + class Base(object): + pass + class Int(Base): + def __init__(self, n): + self.n = n + def double(self): + return Int(self.n * 2) + def get(self): + return self.n + class Str(Base): + def __init__(self, s): + self.s = s + def double(self): + return Str(self.s + self.s) + def get(self): + return int(self.s) + + def ll_make(n): + if n > 0: + return Int(n) + else: + return Str('123') + + def ll_function(n): + o = ll_make(n) + return o.double().get() + + res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL) + assert res == 10 + + res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL) + assert res == 123123 Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Sat Sep 30 18:48:09 2006 @@ -417,6 +417,8 @@ handler(block, i) def make_call(self, block, op, save_locals_vars, color='red'): + # the 'save_locals' pseudo-operation is used to save all + # alive local variables into the current JITState self.genop(block, 'save_locals', save_locals_vars) targets = dict(self.graphs_from(op)) for tsgraph in targets.values(): @@ -424,15 +426,18 @@ # make sure jitstate.resumepoint is set to zero self.genop(block, 'resetresumepoint', []) break + args_v = op.args[1:] + if op.opname == 'indirect_call': + del args_v[-1] if len(targets) == 1: [tsgraph] = targets.values() c_tsgraph = inputconst(lltype.Void, tsgraph) - self.genop(block, '%s_call' % (color,), [c_tsgraph] + op.args[1:]) + self.genop(block, '%s_call' % (color,), [c_tsgraph] + args_v) # Void result, because the call doesn't return its redbox result, # but only has the hidden side-effect of putting it in the jitstate else: c_targets = inputconst(lltype.Void, targets) - args_v = op.args[:-1] + [c_targets] + args_v = op.args[:1] + args_v + [c_targets] hs_func = self.hannotator.binding(args_v[0]) if not hs_func.is_green(): # XXX for now, assume that it will be a constant red box @@ -442,13 +447,8 @@ self.genop(block, 'indirect_%s_call' % (color,), args_v) def handle_red_call(self, block, pos, color='red'): - # the 'save_locals' pseudo-operation is used to save all - # alive local variables into the current JITState - beforeops = block.operations[:pos] - op = block.operations[pos] - afterops = block.operations[pos+1:] - varsalive = self.variables_alive(block, pos+1) + op = block.operations.pop(pos) try: varsalive.remove(op.result) uses_retval = True # it will be restored by 'fetch_return' @@ -456,29 +456,69 @@ uses_retval = False reds, greens = self.sort_by_color(varsalive) - newops = [] - self.make_call(newops, op, reds, color) + nextblock = self.naive_split_block(block, pos) + + v_func = op.args[0] + hs_func = self.hannotator.binding(v_func) + if hs_func.is_green(): + constantblock = block + nonconstantblock = None + blockset = {} + else: + constantblock = Block([]) + nonconstantblock = Block([]) + blockset = {constantblock: False, + nonconstantblock: False} + v_is_constant = self.genop(block, 'is_constant', [v_func], + resulttype = lltype.Bool) + self.genswitch(block, v_is_constant, true = constantblock, + false = nonconstantblock) + constantblock.closeblock(Link([], nextblock)) + nonconstantblock.closeblock(Link([], nextblock)) + + self.make_call(constantblock, op, reds, color) mapping = {} for i, var in enumerate(reds): c_index = Constant(i, concretetype=lltype.Signed) - newvar = self.genop(newops, 'restore_local', [c_index], + newvar = self.genop(constantblock, 'restore_local', [c_index], result_like = var) mapping[var] = newvar if uses_retval: assert not self.hannotator.binding(op.result).is_green() var = op.result - newvar = self.genop(newops, 'fetch_return', [], + newvar = self.genop(constantblock, 'fetch_return', [], result_like = var) mapping[var] = newvar - saved = block.inputargs - block.inputargs = [] # don't rename these! - block.operations = afterops - block.renamevariables(mapping) - block.inputargs = saved - block.operations[:0] = beforeops + newops + nextblock.renamevariables(mapping) + + if nonconstantblock is not None: + args_v = op.args[1:] + if op.opname == 'indirect_call': + del args_v[-1] + # pseudo-obscure: the arguments for the call go in save_locals + self.genop(nonconstantblock, 'save_locals', args_v) + v_res = self.genop(nonconstantblock, 'residual_%s_call' % (color,), + [op.args[0]], result_like = op.result) + + oldvars = mapping.keys() + newvars = [mapping[v] for v in oldvars] + constantblock.exits[0].args = newvars + nextblock.inputargs = newvars + + mapping2 = dict([(v, copyvar(self.hannotator, v)) + for v in newvars]) + nextblock.renamevariables(mapping2) + + mapping3 = {op.result: v_res} + nonconstantblock.exits[0].args = [mapping3.get(v, v) + for v in oldvars] + + blockset[block] = True # reachable from outside + blockset[nextblock] = False + SSA_to_SSI(blockset, self.hannotator) def handle_gray_call(self, block, pos): self.handle_red_call(block, pos, color='gray') From arigo at codespeak.net Sat Sep 30 20:49:16 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Sep 2006 20:49:16 +0200 (CEST) Subject: [pypy-svn] r32771 - in pypy/dist/pypy/jit: codegen/llgraph timeshifter timeshifter/test Message-ID: <20060930184916.3DC8710053@code0.codespeak.net> Author: arigo Date: Sat Sep 30 20:49:14 2006 New Revision: 32771 Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/timeshifter/rtyper.py pypy/dist/pypy/jit/timeshifter/test/test_promotion.py Log: (pedronis, arigo) More tests, all failing (but skipped). Checked in anyway because these tests were not easy to arrive at. Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Sat Sep 30 20:49:14 2006 @@ -195,6 +195,10 @@ return LLConst(llimpl.genconst(llvalue)) @staticmethod + def erasedType(T): + return lltype.erasedType(T) + + @staticmethod @specialize.memo() def kindToken(T): return LLConst(llimpl.constTYPE(T)) Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sat Sep 30 20:49:14 2006 @@ -133,6 +133,7 @@ self.ll_fresh_jitstate = ll_fresh_jitstate def ll_finish_jitstate(jitstate, graphsigtoken): + assert jitstate.resuming is None returnbox = rtimeshift.getreturnbox(jitstate) gv_ret = returnbox.getgenvar(jitstate.curbuilder) store_global_excdata(jitstate) @@ -826,8 +827,7 @@ TYPE = originalconcretetype(hop.args_s[0]) r_arg = self.getredrepr(TYPE) [v_box] = hop.inputargs(r_arg) - r_result = self.getgreenrepr(TYPE) - ERASED = annmodel.annotation_to_lltype(r_result.erased_annotation()) + ERASED = self.RGenOp.erasedType(TYPE) desc = rtimeshift.PromotionDesc(ERASED, self) s_desc = self.rtyper.annotator.bookkeeper.immutablevalue(desc) c_desc = hop.inputconst(lltype.Void, desc) Modified: pypy/dist/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_promotion.py Sat Sep 30 20:49:14 2006 @@ -42,6 +42,47 @@ assert res == ll_function(10, 0) self.check_insns(int_add=10, int_mul=0) + def test_multiple_portal_calls(self): + # so far, crashes when we call timeshift() multiple times + py.test.skip("in-progress") + def ll_function(n): + k = n + if k > 5: + k //= 2 + k = hint(k, promote=True) + k *= 17 + return hint(k, variable=True) + ll_function._global_merge_points_ = True + + res = self.timeshift(ll_function, [4], [], policy=P_NOVIRTUAL) + assert res == 68 + self.check_insns(int_floordiv=1, int_mul=0) + + res = self.timeshift(ll_function, [4], [], policy=P_NOVIRTUAL) + assert res == 68 + self.check_insns(int_floordiv=1, int_mul=0) + + def test_promote_after_call(self): + py.test.skip("the next problem to fix") + S = lltype.GcStruct('S', ('x', lltype.Signed)) + def ll_two(k, s): + if k > 5: + s.x = 20 + else: + s.x = 10 + def ll_function(n): + s = lltype.malloc(S) + ll_two(n, s) + k = hint(n, promote=True) + k *= 17 + return hint(k, variable=True) + s.x + ll_function._global_merge_points_ = True + + res = self.timeshift(ll_function, [4], [], policy=P_NOVIRTUAL) + assert res == 4*17 + 10 + self.check_insns(int_mul=0, int_add=1) + + def test_method_call_nonpromote(self): class Base(object): pass @@ -72,6 +113,48 @@ res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL) assert res == 10 + self.check_insns(indirect_call=2) res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL) assert res == 123123 + self.check_insns(indirect_call=2) + + + def test_method_call_promote(self): + py.test.skip("in-progress") + class Base(object): + pass + class Int(Base): + def __init__(self, n): + self.n = n + def double(self): + return Int(self.n * 2) + def get(self): + return self.n + class Str(Base): + def __init__(self, s): + self.s = s + def double(self): + return Str(self.s + self.s) + def get(self): + return ord(self.s[4]) + + def ll_make(n): + if n > 0: + return Int(n) + else: + return Str('123') + + def ll_function(n): + o = ll_make(n) + hint(o.__class__, promote=True) + return o.double().get() + ll_function._global_merge_points_ = True + + res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL) + assert res == 10 + self.check_insns(indirect_call=0, direct_call=1) + + res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL) + assert res == ord('2') + self.check_insns(indirect_call=0, direct_call=1) From arigo at codespeak.net Sat Sep 30 22:43:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Sep 2006 22:43:55 +0200 (CEST) Subject: [pypy-svn] r32774 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20060930204355.C92BB10053@code0.codespeak.net> Author: arigo Date: Sat Sep 30 22:43:54 2006 New Revision: 32774 Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py pypy/dist/pypy/jit/timeshifter/test/test_promotion.py Log: (arigo, pedronis) Fixed promotion paths, which would get mangled if there were intermediate calls. Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Sat Sep 30 22:43:54 2006 @@ -387,14 +387,25 @@ def __init__(self, next): self.next = next def follow_path(self, path): - path.append(self.direct) + path.append(self.answer) return self.next.follow_path(path) -class PromotionPathDirect(PromotionPathNode): - direct = True +class PromotionPathYes(PromotionPathNode): + answer = True -class PromotionPathIndirect(PromotionPathNode): - direct = False +class PromotionPathNo(PromotionPathNode): + answer = False + +class PromotionPathNoWithArg(PromotionPathNo): + + def __init__(self, next, arg): + self.next = next + self.arg = arg + + def follow_path(self, path): + path.append(self.arg) + return PromotionPathNo.follow_path(self, path) + def ll_continue_compilation(promotion_point_ptr, value): try: @@ -481,6 +492,9 @@ # ____________________________________________________________ class BaseDispatchQueue(object): + parent_promotion_path = None + parent_resuming = None + def __init__(self): self.split_chain = None self.return_chain = None @@ -622,8 +636,8 @@ self.exc_value_box.copy(memo), newresumepoint, newgreens, - PromotionPathIndirect(self.promotion_path)) - self.promotion_path = PromotionPathDirect(self.promotion_path) + PromotionPathNo(self.promotion_path)) + self.promotion_path = PromotionPathYes(self.promotion_path) # add the later_jitstate to the chain of pending-for-dispatch_next() dispatch_queue = self.frame.dispatch_queue later_jitstate.next = dispatch_queue.split_chain @@ -648,10 +662,22 @@ def enter_graph(jitstate, DispatchQueueClass): - jitstate.frame = VirtualFrame(jitstate.frame, DispatchQueueClass()) + dispatchqueue = DispatchQueueClass() + enter_frame(jitstate, dispatchqueue) enter_graph._annspecialcase_ = 'specialize:arg(1)' -# XXX is that too many specializations? ^^^ +def enter_frame(jitstate, dispatchqueue): + resuming = jitstate.resuming + if resuming is None: + dispatchqueue.parent_promotion_path = jitstate.promotion_path + jitstate.promotion_path = PromotionPathYes(jitstate.promotion_path) + else: + dispatchqueue.parent_resuming = resuming + taking = resuming.path.pop() + if not taking: + jitstate.resuming = None + jitstate.frame = VirtualFrame(jitstate.frame, dispatchqueue) + class CompilationInterrupted(Exception): pass @@ -680,21 +706,52 @@ def leave_graph_red(jitstate): jitstate = merge_returning_jitstates(jitstate) myframe = jitstate.frame + leave_frame(jitstate) jitstate.returnbox = myframe.local_boxes[0] # ^^^ fetched by a 'fetch_return' operation - jitstate.frame = myframe.backframe return jitstate def leave_graph_gray(jitstate): jitstate = merge_returning_jitstates(jitstate) - myframe = jitstate.frame - jitstate.frame = myframe.backframe + leave_frame(jitstate) return jitstate +def leave_frame(jitstate): + myframe = jitstate.frame + jitstate.frame = myframe.backframe + assert jitstate.resuming is None + mydispatchqueue = myframe.dispatch_queue + resuming = mydispatchqueue.parent_resuming + if resuming is None: + parent_promotion_path = mydispatchqueue.parent_promotion_path + jitstate.promotion_path = PromotionPathNo(parent_promotion_path) + else: + jitstate.resuming = resuming + jitstate.promotion_path = None + def leave_graph_yellow(jitstate): - return_chain = jitstate.frame.dispatch_queue.return_chain + mydispatchqueue = jitstate.frame.dispatch_queue + return_chain = mydispatchqueue.return_chain jitstate = return_chain - while jitstate is not None: + resuming = mydispatchqueue.parent_resuming + if resuming is None: + n = 0 + parent_promotion_path = mydispatchqueue.parent_promotion_path + while jitstate is not None: + assert jitstate.resuming is None + node = PromotionPathNoWithArg(parent_promotion_path, n) + jitstate.promotion_path = node + n += 1 + jitstate.frame = jitstate.frame.backframe + jitstate = jitstate.next + return return_chain # a jitstate, which is the head of the chain + else: + n = resuming.path.pop() + for i in range(n): + assert jitstate.resuming is None + jitstate = jitstate.next + jitstate.resuming = resuming + jitstate.promotion_path = None jitstate.frame = jitstate.frame.backframe - jitstate = jitstate.next - return return_chain # a jitstate, which is the head of the chain + jitstate.next = None + return jitstate Modified: pypy/dist/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_promotion.py Sat Sep 30 22:43:54 2006 @@ -63,7 +63,6 @@ self.check_insns(int_floordiv=1, int_mul=0) def test_promote_after_call(self): - py.test.skip("the next problem to fix") S = lltype.GcStruct('S', ('x', lltype.Signed)) def ll_two(k, s): if k > 5: