From arigo at codespeak.net Tue Jan 1 15:18:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 1 Jan 2008 15:18:40 +0100 (CET) Subject: [pypy-svn] r50241 - pypy/dist/pypy/rlib/test Message-ID: <20080101141840.CBE181684F8@codespeak.net> Author: arigo Date: Tue Jan 1 15:18:39 2008 New Revision: 50241 Modified: pypy/dist/pypy/rlib/test/test_rsocket.py Log: Thanks fijal Modified: pypy/dist/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rsocket.py (original) +++ pypy/dist/pypy/rlib/test/test_rsocket.py Tue Jan 1 15:18:39 2008 @@ -127,11 +127,11 @@ lock = thread.allocate_lock() lock.acquire() thread.start_new_thread(connecting, ()) - print 'waiting for connexion' + print 'waiting for connection' s1, addr2 = sock.accept() - print 'connexion accepted' + print 'connection accepted' lock.acquire() - print 'connecting side knows that the connexion was accepted too' + print 'connecting side knows that the connection was accepted too' assert addr.eq(s2.getpeername()) assert addr2.eq(s2.getsockname()) assert addr2.eq(s1.getpeername()) From pedronis at codespeak.net Tue Jan 1 15:26:00 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 1 Jan 2008 15:26:00 +0100 (CET) Subject: [pypy-svn] r50242 - pypy/dist/pypy/translator/microbench Message-ID: <20080101142600.791BC1684CB@codespeak.net> Author: pedronis Date: Tue Jan 1 15:26:00 2008 New Revision: 50242 Modified: pypy/dist/pypy/translator/microbench/microbench.py pypy/dist/pypy/translator/microbench/test_dispatch.py Log: with these changes the microbenchs run out of the box on top of a recent Jython if given enough java heap. test_disaptch_nop cannot be run there though. Modified: pypy/dist/pypy/translator/microbench/microbench.py ============================================================================== --- pypy/dist/pypy/translator/microbench/microbench.py (original) +++ pypy/dist/pypy/translator/microbench/microbench.py Tue Jan 1 15:26:00 2008 @@ -4,7 +4,18 @@ implementations on a set of microbenchmarks. The script usally is started with "./microbench.py python ./pypy" where pypy is a symlink to you pypy exectable.""" -import os, time, sys, gc +import os, time, sys + +try: + import gc +except ImportError: + if sys.platform.startswith('java'): + import java.lang + gccollect = java.lang.System.gc + else: + gccollect = lambda: None +else: + gccollect = gc.collect try: this_dir = os.path.dirname(__file__) @@ -18,7 +29,7 @@ microbench = fname[:-3] microbenches.append(microbench) -def run(test_cases): +def run(test_cases, fmt): MINIMUM_MICROBENCH_TIME = 1.0 for microbench in microbenches: @@ -33,7 +44,7 @@ continue testcase_name = microbench + '.' + k + '()' testcase = testmoddict[k] - gc.collect() + gccollect() start = time.clock() n = 0 duration = 0.0 @@ -41,10 +52,16 @@ testcase() n += 1 duration = time.clock() - start - print '%s took %.2f seconds' % (testcase_name, duration / float(n)) + print ('%s took ' + fmt +' seconds') % (testcase_name, duration / float(n)) if __name__ == '__main__': args = sys.argv[1:] + if args[0].startswith('-F'): + fmt = "%" + args[0][2:] + args.pop(0) + else: + fmt = "%.2f" + if '-k' in args: i = args.index('-k') executables = args[:i] @@ -57,7 +74,7 @@ for n, exe in enumerate(executables): print 'exe:', exe - data = [s for s in os.popen(exe + ' microbench.py %s 2>&1' % limit).readlines() if not s.startswith('debug:')] + data = [s for s in os.popen(exe + ' microbench.py -Fr %s 2>&1' % limit).readlines() if not s.startswith('debug:')] benchdata = {} for d in data: try: @@ -78,4 +95,4 @@ print '%5.2fx slower on %s' % (slowdown, testcase) if not executables: - run(test_cases) + run(test_cases, fmt) Modified: pypy/dist/pypy/translator/microbench/test_dispatch.py ============================================================================== --- pypy/dist/pypy/translator/microbench/test_dispatch.py (original) +++ pypy/dist/pypy/translator/microbench/test_dispatch.py Tue Jan 1 15:26:00 2008 @@ -1,31 +1,36 @@ -import new, dis, sys +try: + import dis +except ImportError: + pass +else: + import new, sys -N_NOPS = 10**7 -N = int(50) + N_NOPS = 10**7 + N = int(50) -codestr = "" -ccode = compile(codestr, '', 'exec') -mycode = N_NOPS * chr(dis.opmap['NOP']) + ccode.co_code -co = new.code(ccode.co_argcount, - ccode.co_nlocals, - ccode.co_stacksize, - ccode.co_flags, - mycode, - ccode.co_consts, - ccode.co_names, - ccode.co_varnames, - ccode.co_filename, - ccode.co_name, - ccode.co_firstlineno, - ccode.co_lnotab, - ccode.co_freevars, - ccode.co_cellvars) + codestr = "" + ccode = compile(codestr, '', 'exec') + mycode = N_NOPS * chr(dis.opmap['NOP']) + ccode.co_code + co = new.code(ccode.co_argcount, + ccode.co_nlocals, + ccode.co_stacksize, + ccode.co_flags, + mycode, + ccode.co_consts, + ccode.co_names, + ccode.co_varnames, + ccode.co_filename, + ccode.co_name, + ccode.co_firstlineno, + ccode.co_lnotab, + ccode.co_freevars, + ccode.co_cellvars) -def test_dispatch_nop(): - x = 0 - n = N - while x < n: - exec co - x += 1 - #sys.stdout.write('.') - #sys.stdout.flush() + def test_dispatch_nop(): + x = 0 + n = N + while x < n: + exec co + x += 1 + #sys.stdout.write('.') + #sys.stdout.flush() From fijal at codespeak.net Tue Jan 1 19:05:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jan 2008 19:05:11 +0100 (CET) Subject: [pypy-svn] r50243 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080101180511.D663F168471@codespeak.net> Author: fijal Date: Tue Jan 1 19:05:10 2008 New Revision: 50243 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: The test that passes, but it shouldn't. It seems that there are two different wrappers for eating_callback. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Tue Jan 1 19:05:10 2008 @@ -320,7 +320,7 @@ gn = self.compile(g, []) assert gn() == "c" - def test_c_callback(self): + def eating_callback(self): h_source = py.code.Source(""" int eating_callback(int arg, int(*call)(int)) { @@ -338,30 +338,38 @@ eating_callback = llexternal('eating_callback', args, INT, compilation_info=eci) + return eating_callback + + def test_c_callback(self): + eating_callback = self.eating_callback() def g(i): return i + 3 - def z(i): - if i: - raise ValueError() - else: - return 0 - def f(): return eating_callback(3, g) fn = self.compile(f, []) assert fn() == 6 - def z2(): - return eating_callback(3, z) + def test_double_callback(self): + eating_callback = self.eating_callback() + + def one(i): + return i + + def two(i): + return i + 2 + + def f(i): + if i > 3: + return eating_callback(i, one) + else: + return eating_callback(i, two) + + fn = self.compile(f, [int]) + assert fn(4) == 4 + assert fn(1) == 3 - # this should complain if there are unhandled exceptions inside - # callbacks, or complain if really raising exception - #fn = self.compile(z2, []) - #fn() - #raises(UnhandledRPythonException, "self.compile(z2, [])") - class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) From fijal at codespeak.net Tue Jan 1 19:14:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 1 Jan 2008 19:14:29 +0100 (CET) Subject: [pypy-svn] r50244 - pypy/dist/pypy/translator/js/modules Message-ID: <20080101181429.A5DF8168471@codespeak.net> Author: fijal Date: Tue Jan 1 19:14:28 2008 New Revision: 50244 Modified: pypy/dist/pypy/translator/js/modules/dom.py Log: (Justus Winter) fix signatures 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 Tue Jan 1 19:14:28 2008 @@ -401,10 +401,10 @@ 'cloneNode' : MethodDesc([int], Element), 'getElementsByTagName' : MethodDesc([str], [Element]), 'hasChildNodes' : MethodDesc([], bool), - 'insertBefore' : MethodDesc([Element], Element), + 'insertBefore' : MethodDesc([Element, Element], Element), 'normalize' : MethodDesc([]), 'removeChild' : MethodDesc([Element]), - 'replaceChild' : MethodDesc([Element], Element), + 'replaceChild' : MethodDesc([Element, Element], Element), }) Element._fields = Node._fields.copy() From fijal at codespeak.net Wed Jan 2 10:15:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jan 2008 10:15:22 +0100 (CET) Subject: [pypy-svn] r50247 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080102091522.BC13C1683FB@codespeak.net> Author: fijal Date: Wed Jan 2 10:15:20 2008 New Revision: 50247 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Use llhelper instead of custom _callback. We force here the constantness of argument though. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed Jan 2 10:15:20 2008 @@ -12,6 +12,7 @@ from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer +from pypy.rpython.annlowlevel import llhelper import os class UnhandledRPythonException(Exception): @@ -104,7 +105,8 @@ # and was not the first in this function freeme = arg elif isfunctype(TARGET): - arg = _callback(arg, TARGET) + # XXX pass additional arguments + arg = llhelper(TARGET, _make_wrapper_for(arg)) else: SOURCE = lltype.typeOf(arg) if SOURCE != TARGET: @@ -137,6 +139,15 @@ return func_with_new_name(wrapper, name) +def _make_wrapper_for(callable, error_code=None): + """ Function creating wrappers for callbacks. Note that this is + cheating as we assume constant callbacks and we just memoize wrappers + """ + def wrapper(*args): + return callable(*args) + return wrapper +_make_wrapper_for._annspecialcase_ = 'specialize:memo' + AroundFnPtr = lltype.Ptr(lltype.FuncType([], lltype.Void)) class AroundState: def _freeze_(self): From arigo at codespeak.net Wed Jan 2 11:08:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 11:08:55 +0100 (CET) Subject: [pypy-svn] r50250 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080102100855.A423E168450@codespeak.net> Author: arigo Date: Wed Jan 2 11:08:53 2008 New Revision: 50250 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: BUILD_LIST -> BUILD_TUPLE in the few cases where the difference does not matter. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py Wed Jan 2 11:08:53 2008 @@ -180,7 +180,23 @@ def visitBitxor(self, node): return self._visitBitOp(node, _spacewrapper2('xor')) - #def visitCompare(self, node): XXX + def _List2Tuple(self, node): + if isinstance(node, ast.List): + newnode = ast.Tuple(node.nodes) + copy_node_fields(node, newnode) + # if the resulting tuple contains only constants, we can + # completely constant-fold the tuple creation itself + return self.visitTuple(newnode) + else: + return node + + def visitCompare(self, node): + # xxx could do some constant-folding too, even if it sounds + # a bit unlikely to be useful in practice + last_op_name, last_subnode = node.ops[-1] + if last_op_name == 'in' or last_op_name == 'not in': + node.ops[-1] = last_op_name, self._List2Tuple(last_subnode) + return node def _visitAbstractTest(self, node, is_and): # Logic for And nodes: @@ -217,6 +233,18 @@ consts_w.append(subnode.value) return ast.Const(self.space.newtuple(consts_w)) + def visitFor(self, node): + node.list = self._List2Tuple(node.list) + return node + + def visitListCompFor(self, node): + node.list = self._List2Tuple(node.list) + return node + + def visitGenExprFor(self, node): + node.iter = self._List2Tuple(node.iter) + return node + def _spacewrapper1(name): """Make a wrapper around the method: space.(w_x) @@ -241,6 +269,11 @@ def constant_fold_pow(space, w_x, w_y): return space.pow(w_x, w_y, space.w_None) + def copy_node_fields(src, dst): + dst.lineno = src.lineno + dst.filename = src.filename + dst.parent = src.parent + def optimize_ast_tree(space, tree): return tree.mutate(OptimizerMutator(space)) Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Wed Jan 2 11:08:53 2008 @@ -279,3 +279,38 @@ ''', "doc"), ]: yield self.simple_test, source, "foo.__doc__", expected + + def test_in(self): + yield self.st, "n = 5; x = n in [3,4,5]", 'x', True + yield self.st, "n = 5; x = n in [3,4,6]", 'x', False + yield self.st, "n = 5; x = n in [3,4,n]", 'x', True + yield self.st, "n = 5; x = n in [3,4,n+1]", 'x', False + yield self.st, "n = 5; x = n in (3,4,5)", 'x', True + yield self.st, "n = 5; x = n in (3,4,6)", 'x', False + yield self.st, "n = 5; x = n in (3,4,n)", 'x', True + yield self.st, "n = 5; x = n in (3,4,n+1)", 'x', False + + def test_for_loops(self): + yield self.st, """ + total = 0 + for i in [2, 7, 5]: + total += i + """, 'total', 2 + 7 + 5 + yield self.st, """ + total = 0 + for i in (2, 7, 5): + total += i + """, 'total', 2 + 7 + 5 + yield self.st, """ + total = 0 + for i in [2, 7, total+5]: + total += i + """, 'total', 2 + 7 + 5 + yield self.st, "x = sum([n+2 for n in [6, 1, 2]])", 'x', 15 + yield self.st, "x = sum([n+2 for n in (6, 1, 2)])", 'x', 15 + yield self.st, "k=2; x = sum([n+2 for n in [6, 1, k]])", 'x', 15 + yield self.st, "k=2; x = sum([n+2 for n in (6, 1, k)])", 'x', 15 + yield self.st, "x = sum(n+2 for n in [6, 1, 2])", 'x', 15 + yield self.st, "x = sum(n+2 for n in (6, 1, 2))", 'x', 15 + yield self.st, "k=2; x = sum(n+2 for n in [6, 1, k])", 'x', 15 + yield self.st, "k=2; x = sum(n+2 for n in (6, 1, k))", 'x', 15 From arigo at codespeak.net Wed Jan 2 11:24:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 11:24:08 +0100 (CET) Subject: [pypy-svn] r50251 - in pypy/branch/astcompilertests/pypy: interpreter/astcompiler objspace/std Message-ID: <20080102102408.90C53168466@codespeak.net> Author: arigo Date: Wed Jan 2 11:24:08 2008 New Revision: 50251 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/astcompilertests/pypy/objspace/std/listobject.py pypy/branch/astcompilertests/pypy/objspace/std/objspace.py Log: We never generated LIST_APPEND so far. Fix this and add a shortcut in the stdobjspace to make it faster. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Wed Jan 2 11:24:08 2008 @@ -1064,6 +1064,7 @@ 'FOR_ITER': 1, 'WITH_CLEANUP': 3, 'LOOKUP_METHOD': 1, + 'LIST_APPEND': -2, } # use pattern match patterns = [ Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py Wed Jan 2 11:24:08 2008 @@ -604,13 +604,11 @@ def visitListComp(self, node): self.set_lineno(node) # setup list - append = "$append%d" % self.__list_count + tmpname = "$list%d" % self.__list_count self.__list_count = self.__list_count + 1 self.emitop_int('BUILD_LIST', 0) self.emit('DUP_TOP') - self.emitop('LOAD_ATTR', 'append') - self._implicitNameOp('STORE', append) - + self._implicitNameOp('STORE', tmpname) stack = [] i = 0 @@ -626,10 +624,9 @@ self.genexpr_cont_stack.pop() i += 1 - self._implicitNameOp('LOAD', append) + self._implicitNameOp('LOAD', tmpname) node.expr.accept( self ) - self.emitop_int('CALL_FUNCTION', 1) - self.emit('POP_TOP') + self.emit('LIST_APPEND') for start, cont, anchor in stack: if cont: @@ -640,7 +637,7 @@ self.nextBlock(skip_one) self.emitop_block('JUMP_ABSOLUTE', start) self.startBlock(anchor) - self._implicitNameOp('DELETE', append) + self._implicitNameOp('DELETE', tmpname) self.__list_count = self.__list_count - 1 Modified: pypy/branch/astcompilertests/pypy/objspace/std/listobject.py ============================================================================== --- pypy/branch/astcompilertests/pypy/objspace/std/listobject.py (original) +++ pypy/branch/astcompilertests/pypy/objspace/std/listobject.py Wed Jan 2 11:24:08 2008 @@ -23,6 +23,9 @@ items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]# XXX generic mixed types unwrap return list(items) + def append(w_list, w_item): + w_list.wrappeditems.append(w_item) + registerimplementation(W_ListObject) Modified: pypy/branch/astcompilertests/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/astcompilertests/pypy/objspace/std/objspace.py (original) +++ pypy/branch/astcompilertests/pypy/objspace/std/objspace.py Wed Jan 2 11:24:08 2008 @@ -103,6 +103,14 @@ w_result = f.space.getitem(w_1, w_2) f.pushvalue(w_result) + def LIST_APPEND(f, *ignored): + w = f.popvalue() + v = f.popvalue() + if type(v) is W_ListObject: + v.append(w) + else: + f.space.call_method(v, 'append', w) + if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN: def CALL_LIKELY_BUILTIN(f, oparg, *ignored): from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module From arigo at codespeak.net Wed Jan 2 11:53:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 11:53:13 +0100 (CET) Subject: [pypy-svn] r50252 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080102105313.1B4441684BF@codespeak.net> Author: arigo Date: Wed Jan 2 11:53:12 2008 New Revision: 50252 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: Avoids the intermediate tuple during tuple assignment in some common cases. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py Wed Jan 2 11:53:12 2008 @@ -5,7 +5,7 @@ import sys from pypy.interpreter.astcompiler import ast -from pypy.interpreter.astcompiler import pyassem, misc, future, symbols +from pypy.interpreter.astcompiler import pyassem, misc, future, symbols, opt from pypy.interpreter.astcompiler.consts import SC_LOCAL, SC_GLOBAL, \ SC_FREE, SC_CELL, SC_DEFAULT, OP_APPLY, OP_ASSIGN, OP_DELETE, OP_NONE from pypy.interpreter.astcompiler.consts import CO_VARARGS, CO_VARKEYWORDS, \ @@ -14,6 +14,7 @@ from pypy.interpreter.pyparser.error import SyntaxError from pypy.interpreter.astcompiler.opt import is_constant_false from pypy.interpreter.astcompiler.opt import is_constant_true +from pypy.interpreter.error import OperationError # drop VERSION dependency since it the ast transformer for 2.4 doesn't work with 2.3 anyway VERSION = 2 @@ -921,14 +922,82 @@ def visitAssign(self, node): self.set_lineno(node) + if opt.OPTIMIZE and self._visitTupleAssignment(node): + return node.expr.accept( self ) dups = len(node.nodes) - 1 for i in range(len(node.nodes)): elt = node.nodes[i] if i < dups: self.emit('DUP_TOP') - if isinstance(elt, ast.Node): - elt.accept( self ) + assert isinstance(elt, ast.Node) + elt.accept( self ) + + def _visitTupleAssignment(self, parentnode): + # look for the assignment pattern (...) = (...) + space = self.space + expr = parentnode.expr + if isinstance(expr, ast.Tuple): + srcnodes = expr.nodes + elif isinstance(expr, ast.List): + srcnodes = expr.nodes + elif isinstance(expr, ast.Const): + try: + values_w = space.unpackiterable(expr.value) + except OperationError: + return False + srcnodes = [ast.Const(w) for w in values_w] + else: + return False + if len(parentnode.nodes) != 1: + return False + target = parentnode.nodes[0] + if not isinstance(target, ast.AssSeq): + return False + targetnodes = target.nodes + if len(targetnodes) != len(srcnodes): + return False + # we can only optimize two (common) particular cases, because + # the order of evaluation of the expression *and* the order + # of assignment should both be kept, in principle. + # 1. if all targetnodes are simple names, the assignment order + # *should* not really matter. + # 2. otherwise, if the tuple is of length <= 3, we can emit simple + # bytecodes to reverse the items in the value stack. + for node in targetnodes: + if not isinstance(node, ast.AssName): + break # not a simple name + else: + # all simple names, case 1. + for node in srcnodes: + node.accept(self) + # let's be careful about the same name appearing several times + seen = {} + for i in range(len(targetnodes)-1, -1, -1): + node = targetnodes[i] + assert isinstance(node, ast.AssName) + if node.name not in seen: + seen[node.name] = True + self.storeName(node.name, node.lineno) + else: + self.emit('POP_TOP') + return True # done + + n = len(srcnodes) + if n > 3: + return False # can't do it + else: + # case 2. + for node in srcnodes: + node.accept(self) + if n == 2: + self.emit('ROT_TWO') + elif n == 3: + self.emit('ROT_THREE') + self.emit('ROT_TWO') + for node in targetnodes: + node.accept(self) + return True # done def visitAssName(self, node): if node.flags == OP_ASSIGN: Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Wed Jan 2 11:53:12 2008 @@ -33,6 +33,7 @@ source = str(py.code.Source(source)) space = self.space code = compile_with_astcompiler(source, 'exec', space) + print code.dump() w_dict = space.newdict() code.exec_code(space, w_dict, w_dict) @@ -78,6 +79,32 @@ yield self.simple_test, "[x,y,z,t] = [1,2,3,4]", "x,y,z,t", (1, 2, 3,4) yield self.simple_test, "[x,y,x,t] = 1,2,3,4", "x,y,t", (3, 2, 4) + def test_tuple_assign_order(self): + decl = py.code.Source(""" + class A: + def __getattr__(self, name): + global seen + seen += name + return name + def __setattr__(self, name, value): + global seen + seen += '%s=%s' % (name, value) + seen = '' + a = A() + """) + decl = str(decl) + '\n' + yield self.st, decl+"a.x,= a.a,", 'seen', 'ax=a' + yield self.st, decl+"a.x,a.y = a.a,a.b", 'seen', 'abx=ay=b' + yield self.st, decl+"a.x,a.y,a.z = a.a,a.b,a.c", 'seen', 'abcx=ay=bz=c' + yield self.st, decl+"a.x,a.y,a.x,a.t = a.a,a.b,a.c,a.d", 'seen', \ + 'abcdx=ay=bx=ct=d' + yield self.st, decl+"[a.x] = [a.a]", 'seen', 'ax=a' + yield self.st, decl+"[a.x,a.y] = a.a,a.b", 'seen', 'abx=ay=b' + yield self.st, decl+"[a.x,a.y,a.z] = [a.a,a.b,a.c]", 'seen', \ + 'abcx=ay=bz=c' + yield self.st, decl+"[a.x,a.y,a.x,a.t] = a.a,a.b,a.c,a.d", 'seen', \ + 'abcdx=ay=bx=ct=d' + def test_binary_operator(self): for operator in ['+', '-', '*', '**', '/', '&', '|', '^', '//', '<<', '>>', 'and', 'or', '<', '>', '<=', '>=', From arigo at codespeak.net Wed Jan 2 12:05:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 12:05:36 +0100 (CET) Subject: [pypy-svn] r50253 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080102110536.862D21684CB@codespeak.net> Author: arigo Date: Wed Jan 2 12:05:35 2008 New Revision: 50253 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: not (x in y) ===> x not in y. That's the last of the bytecode optimizations done by CPython 2.6 (svn), excluding some optimizations that just remove dead opcodes. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py Wed Jan 2 12:05:35 2008 @@ -104,12 +104,19 @@ return self._visitUnaryOp(node, _spacewrapper1('repr')) def visitInvert(self, node): return self._visitUnaryOp(node, _spacewrapper1('invert')) - def visitNot(self, node): - return self._visitUnaryOp(node, _spacewrapper1('not_')) def visitUnaryAdd(self, node): return self._visitUnaryOp(node, _spacewrapper1('pos')) def visitUnarySub(self, node): return self._visitUnaryOp(node, _spacewrapper1('neg')) + def visitNot(self, node): + expr = node.expr + if isinstance(expr, ast.Compare) and len(expr.ops) == 1: + op, subnode = expr.ops[0] + if op in opposite_cmp_op: + # not (x in y) ===> x not in y (resp: not in, is, etc.) + expr.ops[0] = opposite_cmp_op[op], subnode + return expr + return self._visitUnaryOp(node, _spacewrapper1('not_')) def _visitBinaryOp(self, node, constant_fold): left = node.left @@ -274,6 +281,13 @@ dst.filename = src.filename dst.parent = src.parent + opposite_cmp_op = { + 'in' : 'not in', + 'not in' : 'in', + 'is' : 'is not', + 'is not' : 'is', + } + def optimize_ast_tree(space, tree): return tree.mutate(OptimizerMutator(space)) Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Wed Jan 2 12:05:35 2008 @@ -218,6 +218,27 @@ yield self.st, "n = None; x = n is True", "x", False yield self.st, "n = None; x = n is False", "x", False yield self.st, "n = None; x = n is None", "x", True + yield self.st, "t = True; x = t is not True", "x", False + yield self.st, "t = True; x = t is not False", "x", True + yield self.st, "t = True; x = t is not None", "x", True + yield self.st, "n = None; x = n is not True", "x", True + yield self.st, "n = None; x = n is not False", "x", True + yield self.st, "n = None; x = n is not None", "x", False + + yield self.st, "x = not (3 in {3: 5})", "x", False + yield self.st, "x = not (3 not in {3: 5})", "x", True + yield self.st, "t = True; x = not (t is True)", "x", False + yield self.st, "t = True; x = not (t is False)", "x", True + yield self.st, "t = True; x = not (t is None)", "x", True + yield self.st, "n = None; x = not (n is True)", "x", True + yield self.st, "n = None; x = not (n is False)", "x", True + yield self.st, "n = None; x = not (n is None)", "x", False + yield self.st, "t = True; x = not (t is not True)", "x", True + yield self.st, "t = True; x = not (t is not False)", "x", False + yield self.st, "t = True; x = not (t is not None)", "x", False + yield self.st, "n = None; x = not (n is not True)", "x", False + yield self.st, "n = None; x = not (n is not False)", "x", False + yield self.st, "n = None; x = not (n is not None)", "x", True def test_multiexpr(self): yield self.st, "z = 2+3; x = y = z", "x,y,z", (5,5,5) From arigo at codespeak.net Wed Jan 2 12:19:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 12:19:02 +0100 (CET) Subject: [pypy-svn] r50254 - pypy/branch/llvmgcroot/pypy/translator/c Message-ID: <20080102111902.B759716846C@codespeak.net> Author: arigo Date: Wed Jan 2 12:19:01 2008 New Revision: 50254 Modified: pypy/branch/llvmgcroot/pypy/translator/c/trackgcroot.py Log: Forgot to check this in. Modified: pypy/branch/llvmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/llvmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/llvmgcroot/pypy/translator/c/trackgcroot.py Wed Jan 2 12:19:01 2008 @@ -96,6 +96,8 @@ if tracker.funcname == entrypoint: table = [(label, (-1,)) for label, _ in table] # ^^^ we set the framesize of the entry point to -1 as a marker + # (the code in llvmgcroot.py actually takes any odd-valued number + # as marker.) self.gcmaptable.extend(table) newfile.writelines(tracker.lines) @@ -442,6 +444,7 @@ FUNCTIONS_NOT_RETURNING = { 'abort': None, + '_exit': None, '__assert_fail': None, } From arigo at codespeak.net Wed Jan 2 13:44:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 13:44:28 +0100 (CET) Subject: [pypy-svn] r50256 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080102124428.60766168507@codespeak.net> Author: arigo Date: Wed Jan 2 13:44:27 2008 New Revision: 50256 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.txt pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py Log: Translation fixes. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py Wed Jan 2 13:44:27 2008 @@ -45,7 +45,7 @@ def accept(self, visitor): raise NotImplementedError def mutate(self, visitor): - return visitor.visitNode(self) + raise NotImplementedError def flatten(self): res = [] nodes = self.getChildNodes() @@ -364,12 +364,7 @@ return visitor.visitAnd(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitAnd(self) def fget_nodes( space, self): @@ -550,12 +545,7 @@ return visitor.visitAssList(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitAssList(self) def fget_nodes( space, self): @@ -697,12 +687,7 @@ return visitor.visitAssTuple(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitAssTuple(self) def fget_nodes( space, self): @@ -859,12 +844,7 @@ return visitor.visitAssign(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) self.expr = self.expr.mutate(visitor) return visitor.visitAssign(self) @@ -1156,12 +1136,7 @@ return visitor.visitBitand(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitBitand(self) def fget_nodes( space, self): @@ -1234,12 +1209,7 @@ return visitor.visitBitor(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitBitor(self) def fget_nodes( space, self): @@ -1312,12 +1282,7 @@ return visitor.visitBitxor(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitBitxor(self) def fget_nodes( space, self): @@ -1443,12 +1408,7 @@ def mutate(self, visitor): self.node = self.node.mutate(visitor) - newlist = [] - for n in self.args: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.args[:] = newlist + visitor._mutate_list(self.args) if self.star_args is not None: self.star_args = self.star_args.mutate(visitor) if self.dstar_args is not None: @@ -1567,12 +1527,7 @@ return visitor.visitClass(self) def mutate(self, visitor): - newlist = [] - for n in self.bases: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.bases[:] = newlist + visitor._mutate_list(self.bases) self.code = self.code.mutate(visitor) return visitor.visitClass(self) @@ -1688,7 +1643,11 @@ def mutate(self, visitor): self.expr = self.expr.mutate(visitor) - self.ops[:] = [(op_name, node.mutate(visitor)) for (op_name, node) in self.ops] + for i in range(len(self.ops)): + + op_name, node = self.ops[i] + + self.ops[i] = op_name, node.mutate(visitor) return visitor.visitCompare(self) @@ -1934,12 +1893,7 @@ return visitor.visitDecorators(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitDecorators(self) def fget_nodes( space, self): @@ -2032,7 +1986,11 @@ return visitor.visitDict(self) def mutate(self, visitor): - self.items[:] = [(n.mutate(visitor), o.mutate(visitor)) for (n, o) in self.items] + for i in range(len(self.items)): + + n, o = self.items[i] + + self.items[i] = n.mutate(visitor), o.mutate(visitor) return visitor.visitDict(self) @@ -2645,18 +2603,8 @@ def mutate(self, visitor): if self.decorators is not None: self.decorators = self.decorators.mutate(visitor) - newlist = [] - for n in self.argnames: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.argnames[:] = newlist - newlist = [] - for n in self.defaults: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.defaults[:] = newlist + visitor._mutate_list(self.argnames) + visitor._mutate_list(self.defaults) self.code = self.code.mutate(visitor) return visitor.visitFunction(self) @@ -2865,12 +2813,7 @@ def mutate(self, visitor): self.assign = self.assign.mutate(visitor) self.iter = self.iter.mutate(visitor) - newlist = [] - for n in self.ifs: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.ifs[:] = newlist + visitor._mutate_list(self.ifs) return visitor.visitGenExprFor(self) def fget_assign( space, self): @@ -3015,12 +2958,7 @@ def mutate(self, visitor): self.expr = self.expr.mutate(visitor) - newlist = [] - for n in self.quals: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.quals[:] = newlist + visitor._mutate_list(self.quals) return visitor.visitGenExprInner(self) def fget_expr( space, self): @@ -3231,7 +3169,11 @@ return visitor.visitIf(self) def mutate(self, visitor): - self.tests[:] = [(n.mutate(visitor), o.mutate(visitor)) for (n, o) in self.tests] + for i in range(len(self.tests)): + + n, o = self.tests[i] + + self.tests[i] = n.mutate(visitor), o.mutate(visitor) if self.else_ is not None: self.else_ = self.else_.mutate(visitor) @@ -3516,18 +3458,8 @@ return visitor.visitLambda(self) def mutate(self, visitor): - newlist = [] - for n in self.argnames: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.argnames[:] = newlist - newlist = [] - for n in self.defaults: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.defaults[:] = newlist + visitor._mutate_list(self.argnames) + visitor._mutate_list(self.defaults) self.code = self.code.mutate(visitor) return visitor.visitLambda(self) @@ -3703,12 +3635,7 @@ return visitor.visitList(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitList(self) def fget_nodes( space, self): @@ -3787,12 +3714,7 @@ def mutate(self, visitor): self.expr = self.expr.mutate(visitor) - newlist = [] - for n in self.quals: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.quals[:] = newlist + visitor._mutate_list(self.quals) return visitor.visitListComp(self) def fget_expr( space, self): @@ -3876,12 +3798,7 @@ def mutate(self, visitor): self.assign = self.assign.mutate(visitor) self.list = self.list.mutate(visitor) - newlist = [] - for n in self.ifs: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.ifs[:] = newlist + visitor._mutate_list(self.ifs) return visitor.visitListCompFor(self) def fget_assign( space, self): @@ -4355,12 +4272,7 @@ return visitor.visitOr(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitOr(self) def fget_nodes( space, self): @@ -4545,12 +4457,7 @@ return visitor.visitPrint(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) if self.dest is not None: self.dest = self.dest.mutate(visitor) return visitor.visitPrint(self) @@ -4647,12 +4554,7 @@ return visitor.visitPrintnl(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) if self.dest is not None: self.dest = self.dest.mutate(visitor) return visitor.visitPrintnl(self) @@ -5088,12 +4990,7 @@ return visitor.visitSliceobj(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitSliceobj(self) def fget_nodes( space, self): @@ -5166,12 +5063,7 @@ return visitor.visitStmt(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitStmt(self) def fget_nodes( space, self): @@ -5423,9 +5315,9 @@ def mutate(self, visitor): self.body = self.body.mutate(visitor) - newhandlers = [] + for i in range(len(self.handlers)): - for expr1, expr2, body in self.handlers: + expr1, expr2, body = self.handlers[i] if expr1 is not None: @@ -5439,9 +5331,7 @@ body = body.mutate(visitor) - newhandlers.append((expr1, expr2, body)) - - self.handlers[:] = newhandlers + self.handlers[i] = expr1, expr2, body if self.else_ is not None: self.else_ = self.else_.mutate(visitor) @@ -5616,12 +5506,7 @@ return visitor.visitTuple(self) def mutate(self, visitor): - newlist = [] - for n in self.nodes: - item = n.mutate(visitor) - if item is not None: - newlist.append(item) - self.nodes[:] = newlist + visitor._mutate_list(self.nodes) return visitor.visitTuple(self) def fget_nodes( space, self): @@ -6032,6 +5917,17 @@ def default(self, node): for child in node.getChildNodes(): child.accept(self) + return node + + def _mutate_list(self, lst): + i = 0 + while i < len(lst): + item = lst[i].mutate(self) + if item is not None: + lst[i] = item + i += 1 + else: + del lst[i] def visitExpression(self, node): return self.default(node) Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.txt ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.txt (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.txt Wed Jan 2 13:44:27 2008 @@ -127,7 +127,9 @@ nodelist.append(node) mutate(Compare.ops): - self.ops[:] = [(op_name, node.mutate(visitor)) for (op_name, node) in self.ops] + for i in range(len(self.ops)): + op_name, node = self.ops[i] + self.ops[i] = op_name, node.mutate(visitor) flatten_nodes(TryExcept.handlers): # handlers is a list of triplets (expr1, expr2, body) @@ -140,16 +142,15 @@ nodelist.append(body) mutate(TryExcept.handlers): - newhandlers = [] - for expr1, expr2, body in self.handlers: + for i in range(len(self.handlers)): + expr1, expr2, body = self.handlers[i] if expr1 is not None: expr1 = expr1.mutate(visitor) if expr2 is not None: expr2 = expr2.mutate(visitor) if body is not None: body = body.mutate(visitor) - newhandlers.append((expr1, expr2, body)) - self.handlers[:] = newhandlers + self.handlers[i] = expr1, expr2, body flatten_nodes(Dict.items): # items is a list of couples (node (key), node (value)) @@ -158,7 +159,9 @@ nodelist.append(value) mutate(Dict.items): - self.items[:] = [(n.mutate(visitor), o.mutate(visitor)) for (n, o) in self.items] + for i in range(len(self.items)): + n, o = self.items[i] + self.items[i] = n.mutate(visitor), o.mutate(visitor) flatten_nodes(If.tests): # tests is a list of couples (node (test), node (suite)) @@ -167,7 +170,9 @@ nodelist.append(suite) mutate(If.tests): - self.tests[:] = [(n.mutate(visitor), o.mutate(visitor)) for (n, o) in self.tests] + for i in range(len(self.tests)): + n, o = self.tests[i] + self.tests[i] = n.mutate(visitor), o.mutate(visitor) AssTuple.getArgNames(self): argnames = [] Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py Wed Jan 2 13:44:27 2008 @@ -324,12 +324,8 @@ print >> buf, " if self.%s is not None:" % (argname,) print >> buf, " self.%s = self.%s.mutate(visitor)" % (argname,argname) elif self.argprops[argname] == P_NESTED: - print >> buf, " newlist = []" - print >> buf, " for n in self.%s:"%(argname) - print >> buf, " item = n.mutate(visitor)" - print >> buf, " if item is not None:" - print >> buf, " newlist.append(item)" - print >> buf, " self.%s[:] = newlist"%(argname) + print >> buf, " visitor._mutate_list(self.%s)"%( + argname,) print >> buf, " return visitor.visit%s(self)" % self.name def _gen_fget_func(self, buf, attr, prop ): @@ -602,6 +598,17 @@ def default(self, node): for child in node.getChildNodes(): child.accept(self) + return node + + def _mutate_list(self, lst): + i = 0 + while i < len(lst): + item = lst[i].mutate(self) + if item is not None: + lst[i] = item + i += 1 + else: + del lst[i] def visitExpression(self, node): return self.default(node) @@ -695,7 +702,7 @@ def accept(self, visitor): raise NotImplementedError def mutate(self, visitor): - return visitor.visitNode(self) + raise NotImplementedError def flatten(self): res = [] nodes = self.getChildNodes() Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py Wed Jan 2 13:44:27 2008 @@ -84,11 +84,6 @@ def __init__(self, space): self.space = space - def default(self, node): - for child in node.getChildNodes(): - child.accept(self) - return node - def _visitUnaryOp(self, node, constant_fold): expr = node.expr if isinstance(expr, ast.Const): Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py Wed Jan 2 13:44:27 2008 @@ -2,14 +2,7 @@ from pypy.module.recparser.pyparser import source2ast from pypy.interpreter.pyparser.test.test_astbuilder import FakeSpace -class BaseVisitor: - def __getattr__(self, attr): - if attr.startswith('visit'): - return self.default - else: - raise AttributeError(attr) - def default(self, node): - return node +class BaseVisitor(ast.ASTVisitor): def visitAdd(self, node): return ast.Const(3) From antocuni at codespeak.net Wed Jan 2 14:20:51 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 2 Jan 2008 14:20:51 +0100 (CET) Subject: [pypy-svn] r50257 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080102132051.AEF7616851D@codespeak.net> Author: antocuni Date: Wed Jan 2 14:20:50 2008 New Revision: 50257 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Log: my dates Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Wed Jan 2 14:20:50 2008 @@ -12,6 +12,7 @@ ==================== ============== ===================== Armin Rigo -- private Carl Friedrich Bolz 12th-19th? Ermina +Antonio Cuni 14th-19th? Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -39,7 +40,6 @@ Samuele Pedroni ? ? Michael Hudson ? ? Niko Matsakis ? ? -Antonio Cuni ? ? Maciej Fijalkowski ? ? Eric van Riet Paap ? ? Jacob Hallen ? ? From cfbolz at codespeak.net Wed Jan 2 15:22:07 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 2 Jan 2008 15:22:07 +0100 (CET) Subject: [pypy-svn] r50258 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080102142207.5774A1684C8@codespeak.net> Author: cfbolz Date: Wed Jan 2 15:22:06 2008 New Revision: 50258 Added: pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py (contents, props changed) Log: todays train-experiment: an rlib.parsing based python lexer. Should work, what is missing is mapping this to what our parser expects plus some corner cases. Added: pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py Wed Jan 2 15:22:06 2008 @@ -0,0 +1,239 @@ +import py +from pypy.rlib.parsing.regexparse import parse_regex, make_runner +from pypy.rlib.parsing.lexer import Lexer + +# attempts at writing a Python-lexer + +def group(*choices): + return '(' + '|'.join(choices) + ')' +def any(*choices): + return group(*choices) + '*' +def maybe(*choices): + return group(*choices) + '?' + +#____________________________________________________________ +# Numbers + +Hexnumber = r'0[xX][0-9a-fA-F]*[lL]?' +Octnumber = r'0[0-7]*[lL]?' +Decnumber = r'[1-9][0-9]*[lL]?' +Intnumber = group(Hexnumber, Octnumber, Decnumber) +Exponent = r'[eE][\-\+]?[0-9]+' +Pointfloat = group(r'[0-9]+\.[0-9]*', r'\.[0-9]+') + maybe(Exponent) +Expfloat = r'[0-9]+' + Exponent +Floatnumber = group(Pointfloat, Expfloat) +Imagnumber = group(r'(0|[1-9][0-9]*)[jJ]', Floatnumber + r'[jJ]') +Number = group(Imagnumber, Floatnumber, Intnumber) + +#____________________________________________________________ +# Strings + +_stringheader = r"[uU]?[rR]?" + +# ' or " string. +def make_single_string(delim): + normal_chars = r"[^\n\%s]*" % (delim, ) + return "".join([_stringheader, delim, normal_chars, + any(r"\\." + normal_chars), delim]) + +# triple-quoted-strings +def make_triple_string(delim): + harmless = r"[^\%s]" % (delim, ) + anyharmless = harmless + "*" + atleastoneharmless = harmless + "+" + normal_chars = anyharmless + any(group(delim, 2 * delim) + + atleastoneharmless) + triple = delim * 3 + return "".join([_stringheader, triple, normal_chars, + any(r"\\." + normal_chars), triple]) + +def test_triple_regex(): + delim = '"' + harmless = r"[^\%s]" % (delim, ) + anyharmless = harmless + "*" + atleastoneharmless = harmless + "+" + normal_chars = anyharmless + any(group(delim, 2 * delim) + + atleastoneharmless) + runner = make_runner(normal_chars) + assert runner.recognize('""a""a""a""a') + assert not runner.recognize('""a""a"""a""a') + +SingleString = group(make_single_string("'"), + make_single_string('"')) + +TripleString = group(make_triple_string("'"), + make_triple_string('"')) + +String = group(SingleString, TripleString) + +#____________________________________________________________ +# Ignored + +Whitespace = r'[ \f\t]*' +Newline = r'\r?\n' +Linecontinue = r'\\' + Newline + any(Whitespace) +Comment = r'#[^\r\n]*' +Indent = Newline + any(Whitespace) +Simpleignore = Whitespace + any(Whitespace) + maybe(group(Comment, Linecontinue)) +Ignore = group(Linecontinue, Comment, Simpleignore) + +#____________________________________________________________ + +Special = r'[\:\;\.\,\`\@]' +Name = r'[a-zA-Z_][a-zA-Z0-9_]*' + +Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=", + r"//=?", + r"[\+\-\*\/\%\&\|\^\=\<\>]=?", + r"~") + +OpenBracket = r'[\[\(\{]' +CloseBracket = r'[\]\)\}]' + +#____________________________________________________________ +# all tokens + +tokens = ["Number", "String", "Name", "Ignore", "Special", "Indent", + "OpenBracket", "CloseBracket", "Operator"] + +def make_lexer(): + return Lexer([parse_regex(globals()[r]) for r in tokens], tokens[:]) + +pythonlexer = make_lexer() + +def postprocess(tokens): + parenthesis_level = 0 + indentation_levels = [0] + output_tokens = [] + for token in tokens: + if token.name == "OpenBracket": + parenthesis_level += 1 + token.name = "Operator" + output_tokens.append(token) + elif token.name == "CloseBracket": + parenthesis_level -= 1 + if parenthesis_level < 0: + XXX + token.name = "Operator" + output_tokens.append(token) + elif token.name == "Indent": + if parenthesis_level == 0: + s = token.source + length = len(s) + pos = 1 + column = 0 + while pos < length: # measure leading whitespace + c = s[pos] + if c == ' ': + column = column + 1 + elif c == '\t': + column = (column // tabsize + 1) * tabsize + elif c == '\f': + column = 0 + else: + break + pos = pos + 1 + if column > indentation_levels[-1]: # count indents or dedents + indentation_levels.append(column) + token.name = "Indent" + while column < indentation_levels[-1]: + indentation_levels.pop() + token.name = "Dedent" + output_tokens.append(token) + else: + pass # implicit line-continuations within parenthesis + elif token.name == "Ignore": + pass + else: + output_tokens.append(token) + return output_tokens + +def pythonlex(s): + return postprocess(pythonlexer.tokenize(s)) + + +def test_number(): + for num in ['1.231e-4', '1j', '0J', '123J' + ]: + tokens = pythonlexer.tokenize(num) + token, = tokens + assert token.name == 'Number' + for intnum in ['1', '0', '0xABFfaf1928375']: + for suffix in ['', 'l', 'L']: + tokens = pythonlexer.tokenize(intnum + suffix) + token, = tokens + assert token.name == 'Number' + +def test_single_quoted_string(): + for s in ["""u'abc'""", + """ur'ab"c'""", + """UR'ab\\'c'""", + """'ab\\\nc'"""]: + tokens = pythonlexer.tokenize(s) + token, = tokens + assert token.name == 'String' + +def test_triple_quoted_string(): + for s in ["""'''abc'''""", + """'''a'b'c''d'f'''""", + """uR'''a\\''''""", + """'''\na\nk\n\"\"\"'''"""]: + tokens = pythonlexer.tokenize(s) + token, = tokens + assert token.name == 'String' + +def test_name(): + for s in ["abc", + "_", + "a_0", + "_0", + ]: + tokens = pythonlexer.tokenize(s) + token, = tokens + assert token.name == 'Name' + +def test_long(): + for s, numtoken in [ + ("if x:\n print x", 8), + ("if x:#foo\n x *= 17", 11), + ("1 + \\\n 2", 5)]: + tokens = pythonlexer.tokenize(s) + assert len(tokens) == numtoken + print tokens + +def test_complex_quoting(): + s = '''"""u'abc'""", + """ur'ab"c'""", + """UR'ab\\'c'""", + """'ab\\\nc'"""''' + tokens = pythonlexer.tokenize(s) + assert len(tokens) == 10 + for i in range(4): + assert tokens[i * 3].name == 'String' + +def test_self(): + s = py.magic.autopath().read() + tokens = pythonlexer.tokenize(s) + print tokens + +def test_indentation(): + s = """a +b + c + d + e""" + tokens = pythonlex(s) + assert [t.name for t in tokens] == ["Name", "Indent", "Name", "Indent", + "Name", "Indent", "Name", "Dedent", + "Name"] + +def test_linecont(): + s = "a + \\\n b" + tokens = pythonlex(s) + assert [t.name for t in tokens] == ["Name", "Operator", "Name"] + +def test_parenthesis(): + s = "(a + \n b)" + tokens = pythonlex(s) + assert [t.name for t in tokens] == ["Operator", "Name", "Operator", "Name", + "Operator"] From cfbolz at codespeak.net Wed Jan 2 16:09:55 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 2 Jan 2008 16:09:55 +0100 (CET) Subject: [pypy-svn] r50259 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20080102150955.5855A1684F7@codespeak.net> Author: cfbolz Date: Wed Jan 2 16:09:53 2008 New Revision: 50259 Modified: pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Log: the assert interpretation of py.test is way better than this` Modified: pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Wed Jan 2 16:09:53 2008 @@ -107,7 +107,7 @@ ] for comment, encoding in checks: res = match_encoding_declaration(comment) - assert res == encoding, "Failed on (%s), %s != %s" % (comment, res, encoding) + assert res == encoding def test_check_for_enconding(): From cfbolz at codespeak.net Wed Jan 2 16:10:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 2 Jan 2008 16:10:17 +0100 (CET) Subject: [pypy-svn] r50260 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20080102151017.BD51E1684F9@codespeak.net> Author: cfbolz Date: Wed Jan 2 16:10:17 2008 New Revision: 50260 Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Log: I am pretty sure that these constants are never used Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Wed Jan 2 16:10:17 2008 @@ -27,17 +27,6 @@ return True -punct=['>=', '<>', '!=', '<', '>', '<=', '==', '\\*=', - '//=', '%=', '^=', '<<=', '\\*\\*=', '\\', '=', - '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', - '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', - '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', - '@', '\\[', '\\]', '`', '\\{', '\\}'] - -TERMINALS = ['NAME', 'NUMBER', 'STRING', 'NEWLINE', 'ENDMARKER', - 'INDENT', 'DEDENT' ] - - class NameToken(Token): """A token that is not a keyword""" def __init__(self, parser): From arigo at codespeak.net Wed Jan 2 16:31:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 16:31:19 +0100 (CET) Subject: [pypy-svn] r50261 - pypy/branch/asmgcroot Message-ID: <20080102153119.4124E1684F3@codespeak.net> Author: arigo Date: Wed Jan 2 16:31:17 2008 New Revision: 50261 Added: pypy/branch/asmgcroot/ - copied from r50260, pypy/branch/llvmgcroot/ Log: Branch the branch, to play with a more flexible implementation of trackgcroot.py. From arigo at codespeak.net Wed Jan 2 16:32:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 16:32:05 +0100 (CET) Subject: [pypy-svn] r50262 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080102153205.04BF21684F7@codespeak.net> Author: arigo Date: Wed Jan 2 16:32:05 2008 New Revision: 50262 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Initial check-in, work in progress. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Wed Jan 2 16:32:05 2008 @@ -15,8 +15,10 @@ r_jmptable_item = re.compile(r"\t.long\t([.]?\w+)\s*$") r_jmptable_end = re.compile(r"\t.text\s*$") r_binaryinsn = re.compile(r"\t[a-z]\w*\s+("+OPERAND+"),\s*("+OPERAND+")\s*$") -r_gcroot_marker = re.compile(r"\t/[*](STORE|LOAD) GCROOT ") -r_gcroot_op = re.compile(r"\t/[*](STORE|LOAD) GCROOT (\d*)[(]%esp[)][*]/\s*$") +LOCALVAR = r"%eax|%edx|%ecx|%ebx|%esi|%edi|%ebp|\d*[(]%esp[)]" +r_gcroot_marker = re.compile(r"\t/[*] GCROOT ("+LOCALVAR+") [*]/") +r_localvar = re.compile(LOCALVAR) +r_localvar_esp = re.compile(r"(\d*)[(]%esp[)]") # for sanity-checking, %esp should only appear as a way to access locals, # i.e. inside parenthesis, except if explicitly recognized otherwise @@ -103,7 +105,6 @@ class FunctionGcRootTracker(object): - VISIT_OPERATION = {} def __init__(self, lines): match = r_functionstart.match(lines[0]) @@ -117,13 +118,13 @@ def computegcmaptable(self): self.findlabels() - try: - self.calls = {} # {label_after_call: state} - self.ignore_calls = {} - self.missing_labels_after_call = [] - self.follow_control_flow() - except ReflowCompletely: - return self.computegcmaptable() + self.parse_instructions() + self.findframesize() + self.fixlocalvars() + self.trackgcroots() + self.dump() + xxx + self.follow_control_flow() table = self.gettable() self.extend_calls_with_labels() return table @@ -151,6 +152,106 @@ self.lines.insert(linenum, '%s:\n' % (label,)) self.lines.insert(linenum, '\t.globl\t%s\n' % (label,)) + def parse_instructions(self): + self.insns = [InsnFunctionStart()] + self.linenum = 0 + in_APP = False + for lin in range(1, len(self.lines)): + self.linenum = lin + insn = no_op + line = self.lines[lin] + match = r_insn.match(line) + if match: + if not in_APP: + insn = match.group(1) + meth = getattr(self, 'visit_' + insn) + insn = meth(line) + elif r_gcroot_marker.match(line): + insn = self.handle_gcroot_marker(line) + elif line == '#APP\n': + in_APP = True + elif line == '#NO_APP\n': + in_APP = False + self.insns.append(insn) + del self.linenum + + def findframesize(self): + self.framesize = {0: 0} + + def walker(lin, insn, size_delta): + check = deltas.setdefault(lin, size_delta) + assert check == size_delta, ( + "inconsistent frame size at function line %d" % (lin,)) + if isinstance(insn, InsnStackAdjust): + size_delta -= insn.delta + if lin not in self.framesize: + yield size_delta # continue walking backwards + + for lin, insn in enumerate(self.insns): + if insn.requestgcroots(): + deltas = {} + self.walk_instructions_backwards(walker, lin, 0) + size_at_insn = [] + for n in deltas: + if n in self.framesize: + size_at_insn.append(self.framesize[n] + deltas[n]) + assert len(size_at_insn) > 0, ( + "cannot reach the start of the function??") + size_at_insn = size_at_insn[0] + for n in deltas: + size_at_n = size_at_insn - deltas[n] + check = self.framesize.setdefault(n, size_at_n) + assert check == size_at_n, ( + "inconsistent frame size at function line %d" % (n,)) + + def fixlocalvars(self): + for lin, insn in enumerate(self.insns): + if lin in self.framesize: + for name in insn._locals_: + localvar = getattr(insn, name) + match = r_localvar_esp.match(localvar) + if match: + ofs_from_esp = int(match.group(1) or '0') + localvar = ofs_from_esp - self.framesize[lin] + assert localvar != 0 # that's the return address + setattr(insn, name, localvar) + + def trackgcroots(self): + + def walker(lin, insn, loc): + source = insn.source_of(loc, tag) + if isinstance(source, Value): + pass # done + else: + yield source + + for lin, insn in enumerate(self.insns): + for loc, tag in insn.requestgcroots().items(): + self.walk_instructions_backwards(walker, lin, loc) + + def dump(self): + for n, insn in enumerate(self.insns): + try: + size = self.framesize[n] + except (AttributeError, KeyError): + size = '?' + print '%4s %s' % (size, insn) + + def walk_instructions_backwards(self, walker, initial_line, initial_state): + pending = [] + seen = {} + def schedule(line, state): + assert 0 <= line < len(self.insns) + key = line, state + if key not in seen: + seen[key] = True + pending.append(key) + schedule(initial_line, initial_state) + while pending: + line, state = pending.pop() + for prevstate in walker(line, self.insns[line], state): + schedule(line - 1, prevstate) + def follow_control_flow(self): # 'states' is a list [(framesize, gcroot0, gcroot1, gcroot2...)] self.states = [None] * len(self.lines) @@ -243,88 +344,44 @@ "unreachable call!" + line) def handle_gcroot_marker(self, line): - match = r_gcroot_op.match(line) - op = match.group(1) - position = int(match.group(2) or '0') - assert position % 4 == 0 - if op == 'STORE': - assert position not in self.gcroots - self.gcroots[position] = None - elif op == 'LOAD': - assert position in self.gcroots - del self.gcroots[position] - else: - raise UnrecognizedOperation(line) + match = r_gcroot_marker.match(line) + loc = match.group(1) + return InsnGCROOT(loc) - def find_visitor(self, insn): - opname = insn - while 1: - try: - meth = getattr(self.__class__, 'visit_' + opname) - break - except AttributeError: - assert opname - opname = opname[:-1] - self.VISIT_OPERATION[insn] = meth - return meth - - def visit_(self, line): - # fallback for all operations. By default, ignore the operation, - # unless it appears to do something with %esp - if not self.can_use_frame_pointer: - if r_esp_outside_paren.match(line): - raise UnrecognizedOperation(line) - - def visit_push(self, line): - raise UnrecognizedOperation(line) - - def visit_pushl(self, line): - self.framesize += 4 - - def visit_pop(self, line): - raise UnrecognizedOperation(line) - - def visit_popl(self, line): - self.framesize -= 4 - assert self.framesize >= 0, "stack underflow" - - def visit_subl(self, line): + def visit_addl(self, line, sign=+1): match = r_binaryinsn.match(line) - if match.group(2) == '%esp': + target = match.group(2) + if target == '%esp': count = match.group(1) assert count.startswith('$') - count = int(count[1:]) - assert count % 4 == 0 - self.framesize += count + return InsnStackAdjust(sign * int(count[1:])) + elif r_localvar.match(target): + return InsnSetLocal(Value(), target) + else: + raise UnrecognizedOperation(line) - def visit_addl(self, line): - match = r_binaryinsn.match(line) - if match.group(2) == '%esp': - count = match.group(1) - assert count.startswith('$') - count = int(count[1:]) - assert count % 4 == 0 - self.framesize -= count - assert self.framesize >= 0, "stack underflow" + def visit_subl(self, line): + return self.visit_addl(line, sign=-1) def visit_movl(self, line): match = r_binaryinsn.match(line) - if match.group(1) == '%esp': - # only for movl %esp, %ebp - if match.group(2) != '%ebp': - raise UnrecognizedOperation(line) - assert self.can_use_frame_pointer # only if we can have a frame ptr - assert self.framesize == 4 # only %ebp should have been pushed - elif match.group(2) == '%esp': - raise UnrecognizedOperation(line) + source = match.group(1) + target = match.group(2) + if r_localvar.match(target): + if r_localvar.match(source): + return InsnCopyLocal(source, target) + else: + return InsnSetLocal(Value(), target) + elif target == '%esp': + raise UnrecognizedOperation + else: + return no_op def visit_ret(self, line): - raise LeaveBasicBlock - - def visit_j(self, line): - raise UnrecognizedOperation(line) + return InsnRet() def visit_jmp(self, line): + xxx if self.in_APP: return # ignore jumps inside a #APP/#NO_APP block match = r_jmp_switch.match(line) @@ -355,6 +412,7 @@ raise LeaveBasicBlock def conditional_jump(self, line): + xxx if self.in_APP: return # ignore jumps inside a #APP/#NO_APP block match = r_jump.match(line) @@ -380,43 +438,17 @@ visit_jno = conditional_jump def visit_call(self, line): - if self.in_APP: - self.ignore_calls[self.currentlinenum] = None - return # ignore calls inside a #APP/#NO_APP block match = r_unaryinsn.match(line) if match is None: assert r_unaryinsn_star.match(line) # indirect call else: target = match.group(1) if target in FUNCTIONS_NOT_RETURNING: - self.ignore_calls[self.currentlinenum] = None - raise LeaveBasicBlock - # we need a globally-declared label just after the call. - # Reuse one if it is already there (e.g. from a previous run of this - # script); otherwise invent a name and schedule the line insertion. - label = None - # this checks for a ".globl NAME" followed by "NAME:" - match = r_globl.match(self.lines[self.currentlinenum+1]) - if match: - label1 = match.group(1) - match = r_label.match(self.lines[self.currentlinenum+2]) - if match: - label2 = match.group(1) - if label1 == label2: - label = label2 - if label is None: - k = 0 - while 1: - label = '__gcmap_IN_%s_%d' % (self.funcname, k) - if label not in self.labels: - break - k += 1 - self.labels[label] = self.currentlinenum+1 - self.missing_labels_after_call.append( - (self.currentlinenum+1, label)) - self.calls[self.currentlinenum] = label, self.getstate() + return InsnStop() + return InsnCall() def visit_pypygetframeaddress(self, line): + xxx # this is a pseudo-instruction that is emitted to find the first # frame address on the stack. We cannot just use # __builtin_frame_address(0) - apparently, gcc thinks it can @@ -429,18 +461,121 @@ self.lines[self.currentlinenum] = newline -class LeaveBasicBlock(Exception): - pass - class UnrecognizedOperation(Exception): pass -class ReflowCompletely(Exception): + +class Value(object): + Count = 0 + def __repr__(self): + try: + n = self.n + except AttributeError: + n = self.n = Value.Count + Value.Count += 1 + return '' % n + +class Insn(object): + _args_ = [] + _locals_ = [] + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, + ', '.join([str(getattr(self, name)) + for name in self._args_])) + def requestgcroots(self): + return {} + + def source_of(self, localvar, tag): + return localvar + +class InsnFunctionStart(Insn): + def __init__(self): + self.arguments = {} + for reg in CALLEE_SAVE_REGISTERS: + self.arguments[reg] = Value() + def source_of(self, localvar, tag): + if localvar not in self.arguments: + assert isinstance(localvar, int) and localvar > 0, ( + "must come from an argument to the function, got %r" % + (localvar,)) + self.arguments[localvar] = Value() + return self.arguments[localvar] + +class NoOp(Insn): pass +no_op = NoOp() -class BogusObject(object): +class InsnSetLocal(Insn): + _args_ = ['value', 'target'] + _locals_ = ['target'] + def __init__(self, value, target): + assert value is None or isinstance(value, Value) + self.value = value + self.target = target + def source_of(self, localvar, tag): + if localvar == self.target: + return self.value + return localvar + +class InsnCopyLocal(Insn): + _args_ = ['source', 'target'] + _locals_ = ['source', 'target'] + def __init__(self, source, target): + self.source = source + self.target = target + def source_of(self, localvar, tag): + if localvar == self.target: + return self.source + return localvar + +class InsnStackAdjust(Insn): + _args_ = ['delta'] + def __init__(self, delta): + assert delta % 4 == 0 + self.delta = delta + +class InsnStop(Insn): pass -Bogus = BogusObject() + +class InsnRet(InsnStop): + def requestgcroots(self): + return dict(zip(CALLEE_SAVE_REGISTERS, CALLEE_SAVE_REGISTERS)) + +class InsnCall(Insn): + _args_ = ['gcroots'] + def __init__(self): + # 'gcroots' is a dict built by side-effect during the call to + # FunctionGcRootTracker.trackgcroots(). Its meaning is as follows: + # the keys are the location that contain gc roots (either register + # names like '%esi', or negative integer offsets relative to the end + # of the function frame). The value corresponding to a key is the + # "tag", which is None for a normal gc root, or else the name of a + # callee-saved register. In the latter case it means that this is + # only a gc root if the corresponding register in the caller was + # really containing a gc pointer. A typical example: + # + # InsnCall({'%ebp': '%ebp', -8: '%ebx', '%esi': None}) + # + # means that %esi is a gc root across this call; that %ebp is a + # gc root if it was in the caller (typically because %ebp is not + # modified at all in the current function); and that the word at 8 + # bytes before the end of the current stack frame is a gc root if + # %ebx was a gc root in the caller (typically because the current + # function saves and restores %ebx from there in the prologue and + # epilogue). + # + self.gcroots = {} + def source_of(self, localvar, tag): + self.gcroots[localvar] = tag + return localvar + +class InsnGCROOT(Insn): + _args_ = ['loc'] + def __init__(self, loc): + self.loc = loc + def requestgcroots(self): + return {self.loc: None} + FUNCTIONS_NOT_RETURNING = { 'abort': None, @@ -448,6 +583,8 @@ '__assert_fail': None, } +CALLEE_SAVE_REGISTERS = ['%ebx', '%esi', '%edi', '%ebp'] + if __name__ == '__main__': tracker = GcRootTracker(verbose=True) From vinogradov at codespeak.net Wed Jan 2 17:27:58 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Wed, 2 Jan 2008 17:27:58 +0100 (CET) Subject: [pypy-svn] r50263 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080102162758.F1C0F1684D5@codespeak.net> Author: vinogradov Date: Wed Jan 2 17:27:57 2008 New Revision: 50263 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Rewrite encode and decode functions Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Wed Jan 2 17:27:57 2008 @@ -63,15 +63,10 @@ def __iter__(self): return RopeStringIterator(self._node) - def decode(self, codepage): - if codepage == "utf-8": - return RopeUnicode(rope.str_decode_utf8(self._node)) - if codepage == "latin1": - #Need rewrite - return RopeUnicode(rope.str_decode_latin1(self._node)) - if codepage == "ascii": - #Need rewrite - return RopeUnicode(rope.str_decode_ascii(self._node)) + def decode(self, codepage, errors='strict'): + s = self._node.flatten_string() + result = s.decode(codepage, errors) + return RopeUnicode(result) def getchar(self,index): return self._node.getchar(index) @@ -104,23 +99,10 @@ def __iter__(self): return RopeUnicodeIterator(self._node) - def encode(self, codepage): - if codepage == "utf-8": - return RopeString(rope.unicode_encode_utf8(self._node)) - if codepage == "utf-16": - raise NotImplemented("How i can encode utf-16 string?") - if codepage == "latin-1": - result = rope.unicode_encode_latin1(self._node) - if result: - return RopeString(result) - else: - raise NotImplementedError("Do i need implement such latin-1 encoding?") - if codepage == "ascii": - result = rope.unicode_encode_ascii(self._node) - if result: - return RopeString(result) - else: - raise NotImplementedError("Do i need implement such ascii encoding?") - + def encode(self, encoding, errors = 'strict'): + s = self._node.flatten_unicode() + result = s.encode(encoding, errors) + return RopeString(result) + def getchar(self,index): return self._node.getunichar(index) From cfbolz at codespeak.net Wed Jan 2 17:44:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 2 Jan 2008 17:44:10 +0100 (CET) Subject: [pypy-svn] r50264 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080102164410.3604E168508@codespeak.net> Author: cfbolz Date: Wed Jan 2 17:44:09 2008 New Revision: 50264 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: typo Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Wed Jan 2 17:44:09 2008 @@ -102,7 +102,7 @@ s = self.conststr("\xff") u = s.decode("latin-1") assert u == self.constunicode(u"\xff") - py.test.raises(UnicodeDecodeError, u.decode, "ascii") + py.test.raises(UnicodeDecodeError, s.decode, "ascii") def test_decode_errors(self): s = self.conststr("a\xffb") From vinogradov at codespeak.net Wed Jan 2 17:48:21 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Wed, 2 Jan 2008 17:48:21 +0100 (CET) Subject: [pypy-svn] r50265 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080102164821.1824416844A@codespeak.net> Author: vinogradov Date: Wed Jan 2 17:48:21 2008 New Revision: 50265 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Update encode and decode functions Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Wed Jan 2 17:48:21 2008 @@ -63,6 +63,11 @@ def __iter__(self): return RopeStringIterator(self._node) + def encode(self, encoding, errors='strict'): + s = self._node.flatten_string() + result = s.encode(encoding, errors) + return RopeUnicode(result) + def decode(self, codepage, errors='strict'): s = self._node.flatten_string() result = s.decode(codepage, errors) @@ -104,5 +109,10 @@ result = s.encode(encoding, errors) return RopeString(result) + def decode(self, codepage, errors = 'strict'): + s = self._node.flatten_unicode() + result = s.decode(codepage, errors) + return RopeUnicode(result) + def getchar(self,index): return self._node.getunichar(index) From arigo at codespeak.net Wed Jan 2 17:52:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 2 Jan 2008 17:52:50 +0100 (CET) Subject: [pypy-svn] r50266 - in pypy/branch/asmgcroot/pypy: config rpython/memory/gctransform translator/c translator/c/src Message-ID: <20080102165250.7DDB21684F0@codespeak.net> Author: arigo Date: Wed Jan 2 17:52:49 2008 New Revision: 50266 Added: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py - copied, changed from r50261, pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py pypy/branch/asmgcroot/pypy/translator/c/funcgen.py pypy/branch/asmgcroot/pypy/translator/c/gc.py pypy/branch/asmgcroot/pypy/translator/c/genc.py pypy/branch/asmgcroot/pypy/translator/c/src/mem.h pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Another in-progress check-in. Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py ============================================================================== --- pypy/branch/asmgcroot/pypy/config/translationoption.py (original) +++ pypy/branch/asmgcroot/pypy/config/translationoption.py Wed Jan 2 17:52:49 2008 @@ -64,8 +64,12 @@ suggests=[("translation.gc", "marksweep")]), BoolOption("llvmgcroot", "Use the 'llvm.gcroot' primitive to find roots", default=False, cmdline="--llvmgcroot", - requires=[("translation.gctransformer", "framework")], - suggests=[("translation.backend", "llvm")]), + requires=[("translation.gctransformer", "framework"), + ("translation.backend", "llvm")]), + BoolOption("asmgcroot", "Use the 'trackgcroot' asm hack to find roots", + default=False, cmdline="--asmgcroot", + requires=[("translation.gctransformer", "framework"), + ("translation.backend", "c")]), BoolOption("thread", "enable use of threading primitives", default=False, cmdline="--thread", requires=[("translation.gc", "boehm")]), Modified: pypy/branch/asmgcroot/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/funcgen.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/funcgen.py Wed Jan 2 17:52:49 2008 @@ -217,16 +217,6 @@ def cfunction_body(self): graph = self.graph - - gcrootscount = 0 - for block in graph.iterblocks(): - for op in block.operations: - if op.opname == 'llvm_store_gcroot': - index = op.args[0].value - gcrootscount = max(gcrootscount, index+1) - for i in range(gcrootscount): - yield 'void* gcroot%d;' % i - # generate the body of each block for block in graph.iterblocks(): self.currentblock = block @@ -732,16 +722,8 @@ def OP_IS_EARLY_CONSTANT(self, op): return self.expr(op.result) + ' = 0;' # Allways false - def OP_LLVM_STORE_GCROOT(self, op): - index = op.args[0].value - value = self.expr(op.args[1]) - return ('gcroot%d = %s; ' % (index, value) + - 'asm volatile ("/*STORE GCROOT %%0*/"::"m"(gcroot%d));' % (index,)) - - def OP_LLVM_LOAD_GCROOT(self, op): - index = op.args[0].value - result = self.expr(op.result) - return ('%s = gcroot%d; ' % (result, index) + - 'asm volatile ("/*LOAD GCROOT %%0*/"::"m"(gcroot%d));' % (index,)) + def OP_ASM_GCROOT(self, op): + value = self.expr(op.args[0]) + return 'PYPY_GCROOT(%s);' % (value,) assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/branch/asmgcroot/pypy/translator/c/gc.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gc.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gc.py Wed Jan 2 17:52:49 2008 @@ -5,7 +5,7 @@ typeOf, Ptr, ContainerType, RttiStruct, \ RuntimeTypeInfo, getRuntimeTypeInfo, top_container from pypy.rpython.memory.gctransform import \ - refcounting, boehm, framework, stacklessframework, llvmgcroot + refcounting, boehm, framework, stacklessframework, llvmgcroot, asmgcroot from pypy.rpython.lltypesystem import lltype, llmemory class BasicGcPolicy(object): @@ -308,6 +308,9 @@ class LLVMGcRootFrameworkGcPolicy(FrameworkGcPolicy): transformerclass = llvmgcroot.LLVMGcRootFrameworkGCTransformer +class AsmGcRootFrameworkGcPolicy(FrameworkGcPolicy): + transformerclass = asmgcroot.AsmGcRootFrameworkGCTransformer + name_to_gcpolicy = { 'boehm': BoehmGcPolicy, @@ -316,6 +319,7 @@ 'framework': FrameworkGcPolicy, 'framework+stacklessgc': StacklessFrameworkGcPolicy, 'framework+llvmgcroot': LLVMGcRootFrameworkGcPolicy, + 'framework+asmgcroot': AsmGcRootFrameworkGcPolicy, } Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/genc.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/genc.py Wed Jan 2 17:52:49 2008 @@ -95,6 +95,8 @@ name = "%s+stacklessgc" % (name,) if self.config.translation.llvmgcroot: name = "%s+llvmgcroot" % (name,) + if self.config.translation.asmgcroot: + name = "%s+asmgcroot" % (name,) return gc.name_to_gcpolicy[name] return self.gcpolicy @@ -275,8 +277,8 @@ self.eci, compiler_exe = cc, profbased = profbased) def compile(self): - if self.config.translation.llvmgcroot: - raise Exception("Dunno how to compile with --llvmgcroot. " + if self.config.translation.asmgcroot: + raise Exception("Dunno how to compile with --asmgcroot. " "Just go to the %s directory and type 'make'." % (self.targetdir,)) assert self.c_source_filename @@ -318,6 +320,7 @@ compiler.compile_extra.append(self.config.translation.compilerflags) if self.config.translation.linkerflags: compiler.link_extra.append(self.config.translation.linkerflags) + assert not self.config.translation.llvmgcroot cfiles = [] ofiles = [] for fn in compiler.cfilenames: @@ -328,7 +331,7 @@ assert fn.dirpath().dirpath() == udir name = '../' + fn.relto(udir) cfiles.append(name) - if self.config.translation.llvmgcroot: + if self.config.translation.asmgcroot: ofiles.append(name[:-2] + '.s') else: ofiles.append(name[:-2] + '.o') @@ -349,13 +352,13 @@ print >> f write_list(cfiles, 'SOURCES =') print >> f - if self.config.translation.llvmgcroot: + if self.config.translation.asmgcroot: write_list(ofiles, 'ASMFILES =') print >> f, 'OBJECTS = $(ASMFILES) gcmaptable.s' else: write_list(ofiles, 'OBJECTS =') print >> f - if self.config.translation.llvmgcroot: + if self.config.translation.asmgcroot: print >> f, 'TRACKGCROOT="%s"' % (os.path.join(autopath.this_dir, 'trackgcroot.py'),) print >> f Modified: pypy/branch/asmgcroot/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/src/mem.h (original) +++ pypy/branch/asmgcroot/pypy/translator/c/src/mem.h Wed Jan 2 17:52:49 2008 @@ -12,6 +12,7 @@ extern char __gcmapend; extern char* __gcmap_frame_address(void); +#define PYPY_GCROOT(p) asm ("/* GCROOT %0 */" : "=g" (p) : "0" (p) : "memory") #define OP_LLVM_GCMAPSTART(r) r = &__gcmapstart #define OP_LLVM_GCMAPEND(r) r = &__gcmapend #define OP_LLVM_FRAMEADDRESS(r) asm ("pypygetframeaddress %0" : "=r" (r)) Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Wed Jan 2 17:52:49 2008 @@ -27,7 +27,7 @@ class GcRootTracker(object): - def __init__(self, verbose=False): + def __init__(self, verbose=0): self.gcmaptable = [] self.verbose = verbose @@ -85,10 +85,10 @@ if self.verbose: print >> sys.stderr, '[trackgcroot:%s] %s' % (filename, tracker.funcname) - table = tracker.computegcmaptable() - #if self.verbose: - # for label, state in table: - # print >> sys.stderr, label, '\t', state + table = tracker.computegcmaptable(self.verbose) + if self.verbose > 1: + for label, state in table: + print >> sys.stderr, label, '\t', state if tracker.can_use_frame_pointer: # XXX for now we have no logic to track the gc roots of # functions using %ebp @@ -98,7 +98,7 @@ if tracker.funcname == entrypoint: table = [(label, (-1,)) for label, _ in table] # ^^^ we set the framesize of the entry point to -1 as a marker - # (the code in llvmgcroot.py actually takes any odd-valued number + # (the code in asmgcroot.py actually takes any odd-valued number # as marker.) self.gcmaptable.extend(table) newfile.writelines(tracker.lines) @@ -116,28 +116,45 @@ self.inconsistent_state = {} self.can_use_frame_pointer = False # unless changed by caller - def computegcmaptable(self): + def computegcmaptable(self, verbose=0): self.findlabels() self.parse_instructions() + if not self.enumerate_call_insns(): + return [] + self.makeprevmap() self.findframesize() self.fixlocalvars() self.trackgcroots() - self.dump() - xxx - self.follow_control_flow() - table = self.gettable() self.extend_calls_with_labels() - return table + if verbose > 2: + self.dump() + return self.gettable() def gettable(self): "Returns a list [(label_after_call, (framesize, gcroot0, gcroot1,..))]" - table = self.calls.items() - table.sort() # by line number - table = [value for key, value in table] + table = [] + for i, insn in self.enumerate_call_insns(): + info = [self.framesize[i]] + # the first gcroots are always the ones corresponding to + # the callee-saved registers + for reg in CALLEE_SAVE_REGISTERS: + info.append(None) + for loc, tag in insn.gcroots.items(): + if not isinstance(loc, int): + # a special representation for a register location, + # as an odd-valued number + loc = CALLEE_SAVE_REGISTERS.index(loc) * 2 + 1 + if tag is None: + info.append(loc) + else: + regindex = CALLEE_SAVE_REGISTERS.index(tag) + info[1 + regindex] = loc + assert None not in info + table.append((insn.global_label, tuple(info))) return table def findlabels(self): - self.labels = {} + self.labels = {} # {name: line number} for i, line in enumerate(self.lines): match = r_label.match(line) if match: @@ -145,52 +162,69 @@ assert label not in self.labels, "duplicate label" self.labels[label] = i - def extend_calls_with_labels(self): - self.missing_labels_after_call.sort() - self.missing_labels_after_call.reverse() - for linenum, label in self.missing_labels_after_call: - self.lines.insert(linenum, '%s:\n' % (label,)) - self.lines.insert(linenum, '\t.globl\t%s\n' % (label,)) - def parse_instructions(self): + self.jumpsto = {} # {label: [list-of-source-node-indices]} + for label in self.labels: + self.jumpsto[label] = [] self.insns = [InsnFunctionStart()] - self.linenum = 0 + self.line2nodeindex = {0: 0} in_APP = False for lin in range(1, len(self.lines)): - self.linenum = lin - insn = no_op + self.currentlineno = lin + insn = [] line = self.lines[lin] match = r_insn.match(line) if match: if not in_APP: - insn = match.group(1) - meth = getattr(self, 'visit_' + insn) + opname = match.group(1) + meth = getattr(self, 'visit_' + opname) insn = meth(line) elif r_gcroot_marker.match(line): - insn = self.handle_gcroot_marker(line) + insn = self._visit_gcroot_marker(line) elif line == '#APP\n': in_APP = True elif line == '#NO_APP\n': in_APP = False - self.insns.append(insn) - del self.linenum + self.line2nodeindex.setdefault(lin, len(self.insns)) + if isinstance(insn, list): + self.insns.extend(insn) + else: + self.insns.append(insn) + del self.currentlineno + + def makeprevmap(self): + # builds the prevmap, which only accounts for jumps. Each insn node + # has an implicit previous node, which is (obviously) the previous + # one in self.insns -- unless the previous one is an InsnStop. + self.prevmap = {} # {node-index: [list-of-previous-node-indices]} + for label, sourceindices in self.jumpsto.items(): + line = self.labels[label] + while line not in self.line2nodeindex: + assert line < len(self.lines), ( + "no Insn found after label %r" % (label,)) + line += 1 + self.prevmap[self.line2nodeindex[line]] = sourceindices + + def enumerate_call_insns(self): + return [(i, insn) for (i, insn) in enumerate(self.insns) + if isinstance(insn, InsnCall)] def findframesize(self): self.framesize = {0: 0} - def walker(lin, insn, size_delta): - check = deltas.setdefault(lin, size_delta) + def walker(i, insn, size_delta): + check = deltas.setdefault(i, size_delta) assert check == size_delta, ( - "inconsistent frame size at function line %d" % (lin,)) + "inconsistent frame size at instruction %d: %s" % (i, insn)) if isinstance(insn, InsnStackAdjust): size_delta -= insn.delta - if lin not in self.framesize: + if i not in self.framesize: yield size_delta # continue walking backwards - for lin, insn in enumerate(self.insns): + for i, insn in enumerate(self.insns): if insn.requestgcroots(): deltas = {} - self.walk_instructions_backwards(walker, lin, 0) + self.walk_instructions_backwards(walker, i, 0) size_at_insn = [] for n in deltas: if n in self.framesize: @@ -202,32 +236,33 @@ size_at_n = size_at_insn - deltas[n] check = self.framesize.setdefault(n, size_at_n) assert check == size_at_n, ( - "inconsistent frame size at function line %d" % (n,)) + "inconsistent frame size at instruction %d: %s" % ( + n, self.insns[n])) def fixlocalvars(self): - for lin, insn in enumerate(self.insns): - if lin in self.framesize: + for i, insn in enumerate(self.insns): + if i in self.framesize: for name in insn._locals_: localvar = getattr(insn, name) match = r_localvar_esp.match(localvar) if match: ofs_from_esp = int(match.group(1) or '0') - localvar = ofs_from_esp - self.framesize[lin] + localvar = ofs_from_esp - self.framesize[i] assert localvar != 0 # that's the return address setattr(insn, name, localvar) def trackgcroots(self): - def walker(lin, insn, loc): + def walker(i, insn, loc): source = insn.source_of(loc, tag) if isinstance(source, Value): pass # done else: yield source - for lin, insn in enumerate(self.insns): + for i, insn in enumerate(self.insns): for loc, tag in insn.requestgcroots().items(): - self.walk_instructions_backwards(walker, lin, loc) + self.walk_instructions_backwards(walker, i, loc) def dump(self): for n, insn in enumerate(self.insns): @@ -237,117 +272,72 @@ size = '?' print '%4s %s' % (size, insn) - def walk_instructions_backwards(self, walker, initial_line, initial_state): + def walk_instructions_backwards(self, walker, initial_i, initial_state): pending = [] seen = {} - def schedule(line, state): - assert 0 <= line < len(self.insns) - key = line, state + def schedule(i, state): + assert 0 <= i < len(self.insns) + key = i, state if key not in seen: seen[key] = True pending.append(key) - schedule(initial_line, initial_state) + schedule(initial_i, initial_state) while pending: - line, state = pending.pop() - for prevstate in walker(line, self.insns[line], state): - schedule(line - 1, prevstate) - - def follow_control_flow(self): - # 'states' is a list [(framesize, gcroot0, gcroot1, gcroot2...)] - self.states = [None] * len(self.lines) - self.pending = [] - self.framesize = 0 - self.gcroots = {} - self.propagate_state_to(1) - while self.pending: - lin = self.pending.pop() - self.follow_basic_block(lin) - self.check_all_calls_seen() - - def getstate(self): - if self.gcroots is Bogus: - gcroots = () - else: - gcroots = self.gcroots.keys() - gcroots.sort() - return (self.framesize,) + tuple(gcroots) - - def propagate_state_to(self, lin): - state = self.getstate() - if self.states[lin] is None: - self.states[lin] = state - self.pending.append(lin) - elif self.states[lin] != state: - if lin not in self.inconsistent_state: - self.inconsistent_state[lin] = (self.states[lin], state) - raise ReflowCompletely - - def follow_basic_block(self, lin): - state = self.states[lin] - self.framesize = state[0] - self.gcroots = dict.fromkeys(state[1:]) - if lin in self.inconsistent_state: # in case of inconsistent gcroots, - self.framesize = Bogus # assume that we're about to leave - if self.framesize is Bogus: # the function or fail an assert - self.gcroots = Bogus - line = '?' - self.in_APP = False - while 1: - try: - self.currentlinenum = lin - line = self.lines[lin] - match = r_insn.match(line) - if match: - insn = match.group(1) - try: - meth = self.VISIT_OPERATION[insn] - except KeyError: - meth = self.find_visitor(insn) - meth(self, line) - elif r_label.match(line): - if not self.in_APP: # ignore labels inside #APP/#NO_APP - self.propagate_state_to(lin+1) - break - elif r_gcroot_marker.match(line): - self.handle_gcroot_marker(line) - elif line == '#APP\n': - self.in_APP = True - elif line == '#NO_APP\n': - self.in_APP = False - lin += 1 - except LeaveBasicBlock: - if self.in_APP: # ignore control flow inside #APP/#NO_APP - lin += 1 - continue - break - except UnrecognizedOperation: - if self.in_APP: # ignore strange ops inside #APP/#NO_APP - lin += 1 - continue - raise - except ReflowCompletely: - raise - except Exception, e: - print >> sys.stderr, '*'*60 - print >> sys.stderr, "%s while processing line:" % ( - e.__class__.__name__,) - print >> sys.stderr, line - raise + i, state = pending.pop() + for prevstate in walker(i, self.insns[i], state): + if not isinstance(self.insns[i - 1], InsnStop): + schedule(i - 1, prevstate) + if i in self.prevmap: + for previndex in self.prevmap[i]: + schedule(previndex, prevstate) - def check_all_calls_seen(self): - for i, line in enumerate(self.lines): - match = r_insn.match(line) + def extend_calls_with_labels(self): + # walk backwards, because inserting the global labels in self.lines + # is going to invalidate the lineno of all the InsnCall objects + # after the current one. + for i, call in self.enumerate_call_insns()[::-1]: + self.create_global_label(call) + + def create_global_label(self, call): + # we need a globally-declared label just after the call. + # Reuse one if it is already there (e.g. from a previous run of this + # script); otherwise invent a name and add the label to tracker.lines. + label = None + # this checks for a ".globl NAME" followed by "NAME:" + match = r_globl.match(self.lines[call.lineno+1]) + if match: + label1 = match.group(1) + match = r_label.match(self.lines[call.lineno+2]) if match: - insn = match.group(1) - if insn == 'call': - assert i in self.calls or i in self.ignore_calls, ( - "unreachable call!" + line) + label2 = match.group(1) + if label1 == label2: + label = label2 + if label is None: + k = call.lineno + while 1: + label = '__gcmap_IN_%s_%d' % (self.funcname, k) + if label not in self.labels: + break + k += 1 + self.labels[label] = call.lineno+1 + self.lines.insert(call.lineno+1, '%s:\n' % (label,)) + self.lines.insert(call.lineno+1, '\t.globl\t%s\n' % (label,)) + call.global_label = label + + # ____________________________________________________________ - def handle_gcroot_marker(self, line): + def _visit_gcroot_marker(self, line): match = r_gcroot_marker.match(line) loc = match.group(1) return InsnGCROOT(loc) + def visit_nop(self, line): + return [] + + NOP_PREFIXES = dict.fromkeys(['cmp', 'test', 'set', + 'f', # floating-point operations + ]) + def visit_addl(self, line, sign=+1): match = r_binaryinsn.match(line) target = match.group(2) @@ -363,29 +353,63 @@ def visit_subl(self, line): return self.visit_addl(line, sign=-1) - def visit_movl(self, line): + def unary_insn(self, line): + match = r_unaryinsn.match(line) + target = match.group(1) + if r_localvar.match(target): + return InsnSetLocal(Value(), target) + else: + raise UnrecognizedOperation(line) + + visit_incl = unary_insn + + def binary_insn(self, line): match = r_binaryinsn.match(line) - source = match.group(1) target = match.group(2) if r_localvar.match(target): + return InsnSetLocal(Value(), target) + else: + raise UnrecognizedOperation(line) + + visit_xorl = binary_insn + visit_movzbl = binary_insn + visit_leal = binary_insn + visit_imull = binary_insn + + def insns_for_copy(self, source, target): + if r_localvar.match(target): if r_localvar.match(source): - return InsnCopyLocal(source, target) + return [InsnCopyLocal(source, target)] else: - return InsnSetLocal(Value(), target) + return [InsnSetLocal(Value(), target)] elif target == '%esp': raise UnrecognizedOperation else: - return no_op + return [] + + def visit_movl(self, line): + match = r_binaryinsn.match(line) + source = match.group(1) + target = match.group(2) + return self.insns_for_copy(source, target) + + def visit_pushl(self, line): + match = r_unaryinsn.match(line) + source = match.group(1) + return [InsnStackAdjust(-4)] + self.insns_for_copy(source, '(%esp)') + + def visit_popl(self, line): + match = r_unaryinsn.match(line) + target = match.group(1) + return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)] def visit_ret(self, line): return InsnRet() def visit_jmp(self, line): - xxx - if self.in_APP: - return # ignore jumps inside a #APP/#NO_APP block match = r_jmp_switch.match(line) if match: + xxx # this is a jmp *Label(%index), used for table-based switches. # Assume that the table is just a list of lines looking like # .long LABEL or .long 0, ending in a .text. @@ -401,7 +425,7 @@ raise LeaveBasicBlock if r_unaryinsn_star.match(line): # that looks like an indirect tail-call. - raise LeaveBasicBlock + return InsnStop() try: self.conditional_jump(line) except KeyError: @@ -409,16 +433,17 @@ match = r_unaryinsn.match(line) target = match.group(1) assert not target.startswith('.') - raise LeaveBasicBlock + return InsnStop() + + def register_jump_to(self, label): + currentpos = len(self.insns) + self.jumpsto[label].append(currentpos) def conditional_jump(self, line): - xxx - if self.in_APP: - return # ignore jumps inside a #APP/#NO_APP block match = r_jump.match(line) label = match.group(1) - targetlin = self.labels[label] - self.propagate_state_to(targetlin) + self.register_jump_to(label) + return [] visit_je = conditional_jump visit_jne = conditional_jump @@ -445,7 +470,7 @@ target = match.group(1) if target in FUNCTIONS_NOT_RETURNING: return InsnStop() - return InsnCall() + return InsnCall(self.currentlineno) def visit_pypygetframeaddress(self, line): xxx @@ -501,10 +526,6 @@ self.arguments[localvar] = Value() return self.arguments[localvar] -class NoOp(Insn): - pass -no_op = NoOp() - class InsnSetLocal(Insn): _args_ = ['value', 'target'] _locals_ = ['target'] @@ -542,8 +563,8 @@ return dict(zip(CALLEE_SAVE_REGISTERS, CALLEE_SAVE_REGISTERS)) class InsnCall(Insn): - _args_ = ['gcroots'] - def __init__(self): + _args_ = ['lineno', 'gcroots'] + def __init__(self, lineno): # 'gcroots' is a dict built by side-effect during the call to # FunctionGcRootTracker.trackgcroots(). Its meaning is as follows: # the keys are the location that contain gc roots (either register @@ -565,6 +586,8 @@ # epilogue). # self.gcroots = {} + self.lineno = lineno + def source_of(self, localvar, tag): self.gcroots[localvar] = tag return localvar @@ -587,7 +610,7 @@ if __name__ == '__main__': - tracker = GcRootTracker(verbose=True) + tracker = GcRootTracker(verbose=sys.maxint) for fn in sys.argv[1:]: tmpfn = fn + '.TMP' f = open(fn, 'r') From fijal at codespeak.net Wed Jan 2 21:42:25 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jan 2008 21:42:25 +0100 (CET) Subject: [pypy-svn] r50267 - pypy/dist/pypy/module/rctime Message-ID: <20080102204225.919431684E9@codespeak.net> Author: fijal Date: Wed Jan 2 21:42:24 2008 New Revision: 50267 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: Fix 64bit, step one. setintfield instead of fixed int_w 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 Wed Jan 2 21:42:24 2008 @@ -206,18 +206,18 @@ "length 9, not %d" % len(tup_w))) y = space.int_w(tup_w[0]) - glob_buf.c_tm_mon = space.int_w(tup_w[1]) - glob_buf.c_tm_mday = space.int_w(tup_w[2]) - glob_buf.c_tm_hour = space.int_w(tup_w[3]) - glob_buf.c_tm_min = space.int_w(tup_w[4]) - glob_buf.c_tm_sec = space.int_w(tup_w[5]) - glob_buf.c_tm_wday = space.int_w(tup_w[6]) - glob_buf.c_tm_yday = space.int_w(tup_w[7]) - glob_buf.c_tm_isdst = space.int_w(tup_w[8]) + rffi.setintfield(glob_buf, 'c_tm_mon', space.int_w(tup_w[1])) + rffi.setintfield(glob_buf, 'c_tm_mday', space.int_w(tup_w[2])) + rffi.setintfield(glob_buf, 'c_tm_hour', space.int_w(tup_w[3])) + rffi.setintfield(glob_buf, 'c_tm_min', space.int_w(tup_w[4])) + rffi.setintfield(glob_buf, 'c_tm_sec', space.int_w(tup_w[5])) + rffi.setintfield(glob_buf, 'c_tm_wday', space.int_w(tup_w[6])) + rffi.setintfield(glob_buf, 'c_tm_yday', space.int_w(tup_w[7])) + rffi.setintfield(glob_buf, 'c_tm_isdst', space.int_w(tup_w[8])) if _POSIX: # actually never happens, but makes annotator happy glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) - glob_buf.c_tm_gmtoff = 0 + rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) From fijal at codespeak.net Wed Jan 2 21:47:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jan 2008 21:47:09 +0100 (CET) Subject: [pypy-svn] r50268 - pypy/dist/pypy/module/rctime Message-ID: <20080102204709.3AB9E1684F3@codespeak.net> Author: fijal Date: Wed Jan 2 21:47:08 2008 New Revision: 50268 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: Another round of using rffi.setintfield when possible 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 Wed Jan 2 21:47:08 2008 @@ -239,10 +239,10 @@ raise OperationError(space.w_ValueError, space.wrap("day of week out of range")) - glob_buf.c_tm_year = y - 1900 - glob_buf.c_tm_mon = glob_buf.c_tm_mon - 1 - glob_buf.c_tm_wday = (glob_buf.c_tm_wday + 1) % 7 - glob_buf.c_tm_yday = glob_buf.c_tm_yday - 1 + rffi.setintfield(glob_buf, 'c_tm_year', y - 1900) + rffi.setintfield(glob_buf, 'c_tm_mon', glob_buf.c_tm_mon - 1) + rffi.setintfield(glob_buf, 'c_tm_wday', (glob_buf.c_tm_wday + 1) % 7) + rffi.setintfield(glob_buf, 'c_tm_yday', glob_buf.c_tm_yday - 1) return glob_buf From fijal at codespeak.net Wed Jan 2 21:53:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jan 2008 21:53:51 +0100 (CET) Subject: [pypy-svn] r50269 - pypy/dist/pypy/config Message-ID: <20080102205351.6E45F16851E@codespeak.net> Author: fijal Date: Wed Jan 2 21:53:51 2008 New Revision: 50269 Modified: pypy/dist/pypy/config/pypyoption.py Log: Add zipimport to allworkingmodules. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Wed Jan 2 21:53:51 2008 @@ -24,7 +24,7 @@ working_modules.update(dict.fromkeys( ["_socket", "unicodedata", "mmap", "fcntl", "rctime", "select", "crypt", "signal", "dyngram", "readline", "termios", "zlib", - "struct", "md5", "sha", "bz2" + "struct", "md5", "sha", "bz2", "zipimport", ] )) From fijal at codespeak.net Wed Jan 2 22:00:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jan 2008 22:00:58 +0100 (CET) Subject: [pypy-svn] r50270 - pypy/dist/pypy/rlib Message-ID: <20080102210058.7D366168516@codespeak.net> Author: fijal Date: Wed Jan 2 22:00:57 2008 New Revision: 50270 Modified: pypy/dist/pypy/rlib/rposix.py Log: Oops, perform intmask on errno. Always. Modified: pypy/dist/pypy/rlib/rposix.py ============================================================================== --- pypy/dist/pypy/rlib/rposix.py (original) +++ pypy/dist/pypy/rlib/rposix.py Wed Jan 2 22:00:57 2008 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable from pypy.rpython.lltypesystem import lltype, ll2ctypes from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.rarithmetic import intmask class CConstantErrno(CConstant): # these accessors are used when calling get_errno() or set_errno() @@ -20,6 +21,8 @@ includes=['errno.h'] ) -get_errno, set_errno = CExternVariable(lltype.Signed, 'errno', errno_eci, - CConstantErrno, sandboxsafe=True) +_get_errno, set_errno = CExternVariable(lltype.Signed, 'errno', errno_eci, + CConstantErrno, sandboxsafe=True) +def get_errno(): + return intmask(_get_errno()) From fijal at codespeak.net Wed Jan 2 22:07:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 2 Jan 2008 22:07:35 +0100 (CET) Subject: [pypy-svn] r50271 - pypy/dist/pypy/rlib Message-ID: <20080102210735.DF5C316851E@codespeak.net> Author: fijal Date: Wed Jan 2 22:07:33 2008 New Revision: 50271 Modified: pypy/dist/pypy/rlib/rposix.py Log: errno is really rffi.INT, not lltype.Signed, sigh Modified: pypy/dist/pypy/rlib/rposix.py ============================================================================== --- pypy/dist/pypy/rlib/rposix.py (original) +++ pypy/dist/pypy/rlib/rposix.py Wed Jan 2 22:07:33 2008 @@ -1,4 +1,4 @@ -from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable +from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT from pypy.rpython.lltypesystem import lltype, ll2ctypes from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rarithmetic import intmask @@ -21,7 +21,7 @@ includes=['errno.h'] ) -_get_errno, set_errno = CExternVariable(lltype.Signed, 'errno', errno_eci, +_get_errno, set_errno = CExternVariable(INT, 'errno', errno_eci, CConstantErrno, sandboxsafe=True) def get_errno(): From exarkun at codespeak.net Wed Jan 2 22:52:28 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 2 Jan 2008 22:52:28 +0100 (CET) Subject: [pypy-svn] r50273 - in pypy/dist/pypy/module/zipimport: . test Message-ID: <20080102215228.B2CA916851B@codespeak.net> Author: exarkun Date: Wed Jan 2 22:52:27 2008 New Revision: 50273 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: Change zipimport.zipimporter.archive to refer to the zipfile, rather than whatever string was passed to __init__ Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Wed Jan 2 22:52:27 2008 @@ -184,7 +184,9 @@ is_package.unwrap_spec = ['self', ObjSpace, str] def getarchive(space, self): - return space.wrap(self.name) + space = self.space + return space.getattr(self.w_dir, space.wrap('filename')) + def descr_new_zipimporter(space, w_type, name): w_zip_cache = space.getattr(space.getbuiltinmodule('zipimport'), Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Wed Jan 2 22:52:27 2008 @@ -214,5 +214,22 @@ assert z.get_source('xx') == "5" assert z.archive == self.zipfile + def test_archive(self): + """ + The archive attribute of zipimport.zipimporter gives the path to the + zipfile itself. + """ + import os + import zipimport + self.writefile( + self, os.sep.join(("directory", "package", "__init__.py")), "") + importer = zipimport.zipimporter(self.zipfile + "/directory") + # Grab this so if the assertion fails, py.test will display its + # value. Not sure why it doesn't the assertion uses import.archive + # directly. -exarkun + archive = importer.archive + assert archive == self.zipfile + + class AppTestZipimportDeflated(AppTestZipimport): compression = ZIP_DEFLATED From fijal at codespeak.net Thu Jan 3 10:21:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jan 2008 10:21:05 +0100 (CET) Subject: [pypy-svn] r50277 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080103092105.C4A5B1684C4@codespeak.net> Author: fijal Date: Thu Jan 3 10:21:04 2008 New Revision: 50277 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Log: My dates. Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Thu Jan 3 10:21:04 2008 @@ -13,6 +13,7 @@ Armin Rigo -- private Carl Friedrich Bolz 12th-19th? Ermina Antonio Cuni 14th-19th? Ermina +Maciej Fijalkowski 11th-20th Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -40,7 +41,6 @@ Samuele Pedroni ? ? Michael Hudson ? ? Niko Matsakis ? ? -Maciej Fijalkowski ? ? Eric van Riet Paap ? ? Jacob Hallen ? ? Laura Creighton ? ? From arigo at codespeak.net Thu Jan 3 10:37:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 10:37:38 +0100 (CET) Subject: [pypy-svn] r50278 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103093738.93BC81684C4@codespeak.net> Author: arigo Date: Thu Jan 3 10:37:37 2008 New Revision: 50278 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Intermediate check-in. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 10:37:37 2008 @@ -177,7 +177,10 @@ if match: if not in_APP: opname = match.group(1) - meth = getattr(self, 'visit_' + opname) + try: + meth = getattr(self, 'visit_' + opname) + except AttributeError: + meth = self.find_missing_visit_method(opname) insn = meth(line) elif r_gcroot_marker.match(line): insn = self._visit_gcroot_marker(line) @@ -192,6 +195,17 @@ self.insns.append(insn) del self.currentlineno + def find_missing_visit_method(self, opname): + # only for operations that are no-ops as far as we are concerned + prefix = opname + while prefix not in self.IGNORE_OPS_WITH_PREFIXES: + prefix = prefix[:-1] + if not prefix: + raise UnrecognizedOperation(opname) + visit_nop = FunctionGcRootTracker.__dict__['visit_nop'] + setattr(FunctionGcRootTracker, 'visit_' + opname, visit_nop) + return self.visit_nop + def makeprevmap(self): # builds the prevmap, which only accounts for jumps. Each insn node # has an implicit previous node, which is (obviously) the previous @@ -255,7 +269,7 @@ def walker(i, insn, loc): source = insn.source_of(loc, tag) - if isinstance(source, Value): + if source is somenewvalue: pass # done else: yield source @@ -334,9 +348,27 @@ def visit_nop(self, line): return [] - NOP_PREFIXES = dict.fromkeys(['cmp', 'test', 'set', - 'f', # floating-point operations - ]) + IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([ + 'cmp', 'test', 'set', 'sahf', + 'f', # floating-point operations + ]) + + visit_movb = visit_nop + visit_movw = visit_nop + visit_addb = visit_nop + visit_addw = visit_nop + visit_subb = visit_nop + visit_subw = visit_nop + visit_incb = visit_nop + visit_incw = visit_nop + visit_decb = visit_nop + visit_decw = visit_nop + visit_xorb = visit_nop + visit_xorw = visit_nop + visit_orb = visit_nop + visit_orw = visit_nop + visit_andb = visit_nop + visit_andw = visit_nop def visit_addl(self, line, sign=+1): match = r_binaryinsn.match(line) @@ -346,7 +378,7 @@ assert count.startswith('$') return InsnStackAdjust(sign * int(count[1:])) elif r_localvar.match(target): - return InsnSetLocal(Value(), target) + return InsnSetLocal(target) else: raise UnrecognizedOperation(line) @@ -357,22 +389,26 @@ match = r_unaryinsn.match(line) target = match.group(1) if r_localvar.match(target): - return InsnSetLocal(Value(), target) + return InsnSetLocal(target) else: raise UnrecognizedOperation(line) visit_incl = unary_insn + visit_decl = unary_insn def binary_insn(self, line): match = r_binaryinsn.match(line) target = match.group(2) if r_localvar.match(target): - return InsnSetLocal(Value(), target) + return InsnSetLocal(target) else: raise UnrecognizedOperation(line) visit_xorl = binary_insn + visit_orl = binary_insn + visit_andl = binary_insn visit_movzbl = binary_insn + visit_movzwl = binary_insn visit_leal = binary_insn visit_imull = binary_insn @@ -381,7 +417,7 @@ if r_localvar.match(source): return [InsnCopyLocal(source, target)] else: - return [InsnSetLocal(Value(), target)] + return [InsnSetLocal(target)] elif target == '%esp': raise UnrecognizedOperation else: @@ -489,16 +525,10 @@ class UnrecognizedOperation(Exception): pass +class SomeNewValue(object): + pass +somenewvalue = SomeNewValue() -class Value(object): - Count = 0 - def __repr__(self): - try: - n = self.n - except AttributeError: - n = self.n = Value.Count - Value.Count += 1 - return '' % n class Insn(object): _args_ = [] @@ -517,25 +547,23 @@ def __init__(self): self.arguments = {} for reg in CALLEE_SAVE_REGISTERS: - self.arguments[reg] = Value() + self.arguments[reg] = somenewvalue def source_of(self, localvar, tag): if localvar not in self.arguments: assert isinstance(localvar, int) and localvar > 0, ( "must come from an argument to the function, got %r" % (localvar,)) - self.arguments[localvar] = Value() + self.arguments[localvar] = somenewvalue return self.arguments[localvar] class InsnSetLocal(Insn): - _args_ = ['value', 'target'] + _args_ = ['target'] _locals_ = ['target'] - def __init__(self, value, target): - assert value is None or isinstance(value, Value) - self.value = value + def __init__(self, target): self.target = target def source_of(self, localvar, tag): if localvar == self.target: - return self.value + return somenewvalue return localvar class InsnCopyLocal(Insn): From fijal at codespeak.net Thu Jan 3 10:39:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jan 2008 10:39:29 +0100 (CET) Subject: [pypy-svn] r50279 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080103093929.B4ECC1684C4@codespeak.net> Author: fijal Date: Thu Jan 3 10:39:28 2008 New Revision: 50279 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: Implement errorcode for callbacks and print a warning. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Jan 3 10:39:28 2008 @@ -106,7 +106,11 @@ freeme = arg elif isfunctype(TARGET): # XXX pass additional arguments - arg = llhelper(TARGET, _make_wrapper_for(arg)) + if invoke_around_handlers: + arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg, + aroundstate)) + else: + arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg)) else: SOURCE = lltype.typeOf(arg) if SOURCE != TARGET: @@ -139,12 +143,20 @@ return func_with_new_name(wrapper, name) -def _make_wrapper_for(callable, error_code=None): +def _make_wrapper_for(TP, callable, aroundstate=None): """ Function creating wrappers for callbacks. Note that this is cheating as we assume constant callbacks and we just memoize wrappers """ + if hasattr(callable, '_errorcode_'): + errorcode = callable._errorcode_ + else: + errorcode = TP.TO.RESULT._example() def wrapper(*args): - return callable(*args) + try: + return callable(*args) + except Exception, e: + os.write(2, "Warning: uncatched exception: %s" % str(e)) + return errorcode return wrapper _make_wrapper_for._annspecialcase_ = 'specialize:memo' Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Thu Jan 3 10:39:28 2008 @@ -324,7 +324,10 @@ h_source = py.code.Source(""" int eating_callback(int arg, int(*call)(int)) { - return call(arg); + int res = call(arg); + if (res == -1) + return -1; + return res; } """) @@ -370,6 +373,22 @@ assert fn(4) == 4 assert fn(1) == 3 + def test_exception_callback(self): + eating_callback = self.eating_callback() + + def raising(i): + if i > 3: + raise ValueError + else: + return 3 + raising._errorcode_ = -1 + + def f(i): + return eating_callback(i, raising) + + fn = self.compile(f, [int]) + assert fn(13) == -1 + class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) From fijal at codespeak.net Thu Jan 3 10:39:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jan 2008 10:39:48 +0100 (CET) Subject: [pypy-svn] r50280 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080103093948.7FDDF1684C4@codespeak.net> Author: fijal Date: Thu Jan 3 10:39:48 2008 New Revision: 50280 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Be more verbose Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Jan 3 10:39:48 2008 @@ -155,7 +155,7 @@ try: return callable(*args) except Exception, e: - os.write(2, "Warning: uncatched exception: %s" % str(e)) + os.write(2, "Warning: uncatched exception in callback: %s %s" % (callable, str(e))) return errorcode return wrapper _make_wrapper_for._annspecialcase_ = 'specialize:memo' From fijal at codespeak.net Thu Jan 3 10:41:15 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jan 2008 10:41:15 +0100 (CET) Subject: [pypy-svn] r50281 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080103094115.928551684C4@codespeak.net> Author: fijal Date: Thu Jan 3 10:41:15 2008 New Revision: 50281 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Oops. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Jan 3 10:41:15 2008 @@ -155,7 +155,7 @@ try: return callable(*args) except Exception, e: - os.write(2, "Warning: uncatched exception in callback: %s %s" % (callable, str(e))) + os.write(2, "Warning: uncatched exception in callback: %s %s\n" % (str(callable), str(e))) return errorcode return wrapper _make_wrapper_for._annspecialcase_ = 'specialize:memo' From fijal at codespeak.net Thu Jan 3 10:46:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jan 2008 10:46:12 +0100 (CET) Subject: [pypy-svn] r50282 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080103094612.49F1E1684BF@codespeak.net> Author: fijal Date: Thu Jan 3 10:46:11 2008 New Revision: 50282 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: (mwh) typo Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Jan 3 10:46:11 2008 @@ -151,11 +151,24 @@ errorcode = callable._errorcode_ else: errorcode = TP.TO.RESULT._example() + if aroundstate is not None: + before = aroundstate.before + after = aroundstate.after + else: + before = None + after = None def wrapper(*args): try: - return callable(*args) + if before: + before() + result = callable(*args) + if after: + after() + return result except Exception, e: - os.write(2, "Warning: uncatched exception in callback: %s %s\n" % (str(callable), str(e))) + if after: + after() + os.write(2, "Warning: uncaught exception in callback: %s %s\n" % (str(callable), str(e))) return errorcode return wrapper _make_wrapper_for._annspecialcase_ = 'specialize:memo' From arigo at codespeak.net Thu Jan 3 11:02:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 11:02:05 +0100 (CET) Subject: [pypy-svn] r50283 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080103100205.BC7DB168480@codespeak.net> Author: arigo Date: Thu Jan 3 11:02:05 2008 New Revision: 50283 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Log: A note about late arrival. Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Thu Jan 3 11:02:05 2008 @@ -7,14 +7,14 @@ available yet from them. -==================== ============== ===================== +==================== ============== ======================= Name Arrive/Depart Accomodation -==================== ============== ===================== +==================== ============== ======================= Armin Rigo -- private Carl Friedrich Bolz 12th-19th? Ermina Antonio Cuni 14th-19th? Ermina -Maciej Fijalkowski 11th-20th Ermina -==================== ============== ===================== +Maciej Fijalkowski 11th-20th Ermina (arrive at 10pm) +==================== ============== ======================= People on the following list were present at previous sprints: From arigo at codespeak.net Thu Jan 3 11:26:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 11:26:09 +0100 (CET) Subject: [pypy-svn] r50284 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103102609.BF41C1684CB@codespeak.net> Author: arigo Date: Thu Jan 3 11:26:03 2008 New Revision: 50284 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: In-progress. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 11:26:03 2008 @@ -20,18 +20,16 @@ r_localvar = re.compile(LOCALVAR) r_localvar_esp = re.compile(r"(\d*)[(]%esp[)]") -# for sanity-checking, %esp should only appear as a way to access locals, -# i.e. inside parenthesis, except if explicitly recognized otherwise -r_esp_outside_paren = re.compile(r"(.+[)])?[^(]*[%]esp") - class GcRootTracker(object): def __init__(self, verbose=0): self.gcmaptable = [] self.verbose = verbose + self.seen_main = False def dump(self, output): + assert self.seen_main shapes = {} print >> output, '\t.data' print >> output, '\t.align\t4' @@ -80,8 +78,6 @@ def process_function(self, lines, newfile, entrypoint, filename): tracker = FunctionGcRootTracker(lines) - if tracker.funcname == entrypoint: - tracker.can_use_frame_pointer = True if self.verbose: print >> sys.stderr, '[trackgcroot:%s] %s' % (filename, tracker.funcname) @@ -89,13 +85,9 @@ if self.verbose > 1: for label, state in table: print >> sys.stderr, label, '\t', state - if tracker.can_use_frame_pointer: - # XXX for now we have no logic to track the gc roots of - # functions using %ebp - for label, state in table: - assert len(state) == 1, ( - "XXX for now the entry point should not have any gc roots") if tracker.funcname == entrypoint: + self.seen_main = True + xxx table = [(label, (-1,)) for label, _ in table] # ^^^ we set the framesize of the entry point to -1 as a marker # (the code in asmgcroot.py actually takes any odd-valued number @@ -113,28 +105,30 @@ assert self.funcname == match.group(1) assert self.funcname == match.group(2) self.lines = lines - self.inconsistent_state = {} - self.can_use_frame_pointer = False # unless changed by caller def computegcmaptable(self, verbose=0): self.findlabels() self.parse_instructions() - if not self.enumerate_call_insns(): - return [] - self.makeprevmap() - self.findframesize() - self.fixlocalvars() - self.trackgcroots() - self.extend_calls_with_labels() - if verbose > 2: - self.dump() + try: + if not self.list_call_insns(): + return [] + self.findprevinsns() + self.findframesize() + self.fixlocalvars() + self.trackgcroots() + self.extend_calls_with_labels() + finally: + if verbose > 2: + self.dump() return self.gettable() def gettable(self): "Returns a list [(label_after_call, (framesize, gcroot0, gcroot1,..))]" table = [] - for i, insn in self.enumerate_call_insns(): - info = [self.framesize[i]] + for insn in self.list_call_insns(): + if not hasattr(insn, 'framesize'): + continue # calls that never end up reaching a RET + info = [insn.framesize] # the first gcroots are always the ones corresponding to # the callee-saved registers for reg in CALLEE_SAVE_REGISTERS: @@ -154,25 +148,20 @@ return table def findlabels(self): - self.labels = {} # {name: line number} - for i, line in enumerate(self.lines): + self.labels = {} # {name: Label()} + for line in self.lines: match = r_label.match(line) if match: label = match.group(1) assert label not in self.labels, "duplicate label" - self.labels[label] = i + self.labels[label] = Label(label) def parse_instructions(self): - self.jumpsto = {} # {label: [list-of-source-node-indices]} - for label in self.labels: - self.jumpsto[label] = [] self.insns = [InsnFunctionStart()] - self.line2nodeindex = {0: 0} in_APP = False - for lin in range(1, len(self.lines)): - self.currentlineno = lin + for lineno, line in enumerate(self.lines): + self.currentlineno = lineno insn = [] - line = self.lines[lin] match = r_insn.match(line) if match: if not in_APP: @@ -188,7 +177,10 @@ in_APP = True elif line == '#NO_APP\n': in_APP = False - self.line2nodeindex.setdefault(lin, len(self.insns)) + else: + match = r_label.match(line) + if match: + insn = self.labels[match.group(1)] if isinstance(insn, list): self.insns.extend(insn) else: @@ -206,111 +198,107 @@ setattr(FunctionGcRootTracker, 'visit_' + opname, visit_nop) return self.visit_nop - def makeprevmap(self): - # builds the prevmap, which only accounts for jumps. Each insn node - # has an implicit previous node, which is (obviously) the previous - # one in self.insns -- unless the previous one is an InsnStop. - self.prevmap = {} # {node-index: [list-of-previous-node-indices]} - for label, sourceindices in self.jumpsto.items(): - line = self.labels[label] - while line not in self.line2nodeindex: - assert line < len(self.lines), ( - "no Insn found after label %r" % (label,)) - line += 1 - self.prevmap[self.line2nodeindex[line]] = sourceindices - - def enumerate_call_insns(self): - return [(i, insn) for (i, insn) in enumerate(self.insns) - if isinstance(insn, InsnCall)] + def findprevinsns(self): + # builds the previous_insns of each Insn. For Labels, all jumps + # to them are already registered; all that is left to do is to + # make each Insn point to the Insn just before it. + for i in range(len(self.insns)-1): + previnsn = self.insns[i] + nextinsn = self.insns[i+1] + try: + lst = nextinsn.previous_insns + except AttributeError: + lst = nextinsn.previous_insns = [] + if not isinstance(previnsn, InsnStop): + lst.append(previnsn) + + def list_call_insns(self): + return [insn for insn in self.insns if isinstance(insn, InsnCall)] def findframesize(self): - self.framesize = {0: 0} + self.insns[0].framesize = 0 - def walker(i, insn, size_delta): - check = deltas.setdefault(i, size_delta) + def walker(insn, size_delta): + check = deltas.setdefault(insn, size_delta) assert check == size_delta, ( - "inconsistent frame size at instruction %d: %s" % (i, insn)) + "inconsistent frame size at instruction %s" % (insn,)) if isinstance(insn, InsnStackAdjust): size_delta -= insn.delta - if i not in self.framesize: + if not hasattr(insn, 'framesize'): yield size_delta # continue walking backwards - for i, insn in enumerate(self.insns): + for insn in self.insns: if insn.requestgcroots(): deltas = {} - self.walk_instructions_backwards(walker, i, 0) + self.walk_instructions_backwards(walker, insn, 0) size_at_insn = [] - for n in deltas: - if n in self.framesize: - size_at_insn.append(self.framesize[n] + deltas[n]) + for insn1, delta1 in deltas.items(): + if hasattr(insn1, 'framesize'): + size_at_insn.append(insn1.framesize + delta1) assert len(size_at_insn) > 0, ( "cannot reach the start of the function??") size_at_insn = size_at_insn[0] - for n in deltas: - size_at_n = size_at_insn - deltas[n] - check = self.framesize.setdefault(n, size_at_n) - assert check == size_at_n, ( - "inconsistent frame size at instruction %d: %s" % ( - n, self.insns[n])) + for insn1, delta1 in deltas.items(): + size_at_insn1 = size_at_insn - delta1 + if hasattr(insn1, 'framesize'): + assert insn1.framesize == size_at_insn1, ( + "inconsistent frame size at instruction %s" % + (insn1,)) + else: + insn1.framesize = size_at_insn1 def fixlocalvars(self): - for i, insn in enumerate(self.insns): - if i in self.framesize: + for insn in self.insns: + if hasattr(insn, 'framesize'): for name in insn._locals_: localvar = getattr(insn, name) match = r_localvar_esp.match(localvar) if match: ofs_from_esp = int(match.group(1) or '0') - localvar = ofs_from_esp - self.framesize[i] + localvar = ofs_from_esp - insn.framesize assert localvar != 0 # that's the return address setattr(insn, name, localvar) def trackgcroots(self): - def walker(i, insn, loc): + def walker(insn, loc): source = insn.source_of(loc, tag) if source is somenewvalue: pass # done else: yield source - for i, insn in enumerate(self.insns): + for insn in self.insns: for loc, tag in insn.requestgcroots().items(): - self.walk_instructions_backwards(walker, i, loc) + self.walk_instructions_backwards(walker, insn, loc) def dump(self): - for n, insn in enumerate(self.insns): - try: - size = self.framesize[n] - except (AttributeError, KeyError): - size = '?' + for insn in self.insns: + size = getattr(insn, 'framesize', '?') print '%4s %s' % (size, insn) - def walk_instructions_backwards(self, walker, initial_i, initial_state): + def walk_instructions_backwards(self, walker, initial_insn, initial_state): pending = [] seen = {} - def schedule(i, state): - assert 0 <= i < len(self.insns) - key = i, state + def schedule(insn, state): + key = insn, state if key not in seen: seen[key] = True pending.append(key) - schedule(initial_i, initial_state) + schedule(initial_insn, initial_state) while pending: - i, state = pending.pop() - for prevstate in walker(i, self.insns[i], state): - if not isinstance(self.insns[i - 1], InsnStop): - schedule(i - 1, prevstate) - if i in self.prevmap: - for previndex in self.prevmap[i]: - schedule(previndex, prevstate) + insn, state = pending.pop() + for prevstate in walker(insn, state): + for previnsn in insn.previous_insns: + schedule(previnsn, prevstate) def extend_calls_with_labels(self): # walk backwards, because inserting the global labels in self.lines # is going to invalidate the lineno of all the InsnCall objects # after the current one. - for i, call in self.enumerate_call_insns()[::-1]: - self.create_global_label(call) + for call in self.list_call_insns()[::-1]: + if hasattr(call, 'framesize'): + self.create_global_label(call) def create_global_label(self, call): # we need a globally-declared label just after the call. @@ -349,8 +337,15 @@ return [] IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([ - 'cmp', 'test', 'set', 'sahf', - 'f', # floating-point operations + 'cmp', 'test', 'set', 'sahf', 'cltd', 'cld', 'std', + 'rep', 'movs', + # floating-point operations cannot produce GC pointers + 'f', + # arithmetic operations should not produce GC pointers + 'inc', 'dec', 'not', 'neg', 'or', 'and', + 'shl', 'shr', 'sal', 'sar', 'mul', 'imul', 'div', 'idiv', + # zero-extending moves should not produce GC pointers + 'movz', ]) visit_movb = visit_nop @@ -359,16 +354,8 @@ visit_addw = visit_nop visit_subb = visit_nop visit_subw = visit_nop - visit_incb = visit_nop - visit_incw = visit_nop - visit_decb = visit_nop - visit_decw = visit_nop visit_xorb = visit_nop visit_xorw = visit_nop - visit_orb = visit_nop - visit_orw = visit_nop - visit_andb = visit_nop - visit_andw = visit_nop def visit_addl(self, line, sign=+1): match = r_binaryinsn.match(line) @@ -380,7 +367,7 @@ elif r_localvar.match(target): return InsnSetLocal(target) else: - raise UnrecognizedOperation(line) + return [] def visit_subl(self, line): return self.visit_addl(line, sign=-1) @@ -391,35 +378,50 @@ if r_localvar.match(target): return InsnSetLocal(target) else: - raise UnrecognizedOperation(line) + return [] - visit_incl = unary_insn - visit_decl = unary_insn +## visit_incl = unary_insn +## visit_decl = unary_insn +## visit_notl = unary_insn +## visit_negl = unary_insn def binary_insn(self, line): match = r_binaryinsn.match(line) + if not match: + raise UnrecognizedOperation(line) target = match.group(2) if r_localvar.match(target): return InsnSetLocal(target) else: raise UnrecognizedOperation(line) - visit_xorl = binary_insn - visit_orl = binary_insn - visit_andl = binary_insn - visit_movzbl = binary_insn - visit_movzwl = binary_insn + visit_xorl = binary_insn # used in "xor reg, reg" to create a NULL GC ptr +## visit_orl = binary_insn +## visit_andl = binary_insn +## visit_movzbl = binary_insn +## visit_movzwl = binary_insn visit_leal = binary_insn - visit_imull = binary_insn + + def unary_or_binary_insn(self, line): + if r_binaryinsn.match(line): + return self.binary_insn(line) + else: + return self.unary_insn(line) + +## visit_shll = unary_or_binary_insn +## visit_shrl = unary_or_binary_insn +## visit_sall = unary_or_binary_insn +## visit_sarl = unary_or_binary_insn +## visit_imull = unary_or_binary_insn def insns_for_copy(self, source, target): - if r_localvar.match(target): + if source == '%esp' or target == '%esp': + raise UnrecognizedOperation('%s -> %s' % (source, target)) + elif r_localvar.match(target): if r_localvar.match(source): return [InsnCopyLocal(source, target)] else: return [InsnSetLocal(target)] - elif target == '%esp': - raise UnrecognizedOperation else: return [] @@ -472,8 +474,7 @@ return InsnStop() def register_jump_to(self, label): - currentpos = len(self.insns) - self.jumpsto[label].append(currentpos) + self.labels[label].previous_insns.append(self.insns[-1]) def conditional_jump(self, line): match = r_jump.match(line) @@ -506,7 +507,8 @@ target = match.group(1) if target in FUNCTIONS_NOT_RETURNING: return InsnStop() - return InsnCall(self.currentlineno) + return [InsnCall(self.currentlineno), + InsnSetLocal('%eax')] # the result is there def visit_pypygetframeaddress(self, line): xxx @@ -543,7 +545,14 @@ def source_of(self, localvar, tag): return localvar +class Label(Insn): + _args_ = ['label'] + def __init__(self, label): + self.label = label + self.previous_insns = [] # all insns that jump (or fallthrough) here + class InsnFunctionStart(Insn): + previous_insns = () def __init__(self): self.arguments = {} for reg in CALLEE_SAVE_REGISTERS: @@ -638,7 +647,12 @@ if __name__ == '__main__': - tracker = GcRootTracker(verbose=sys.maxint) + if sys.argv and sys.argv[1] == '-v': + del sys.argv[1] + verbose = sys.maxint + else: + verbose = 1 + tracker = GcRootTracker(verbose=verbose) for fn in sys.argv[1:]: tmpfn = fn + '.TMP' f = open(fn, 'r') From arigo at codespeak.net Thu Jan 3 12:18:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 12:18:33 +0100 (CET) Subject: [pypy-svn] r50285 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103111833.E23A1168480@codespeak.net> Author: arigo Date: Thu Jan 3 12:18:32 2008 New Revision: 50285 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Parses gcbench. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 12:18:32 2008 @@ -16,9 +16,12 @@ r_jmptable_end = re.compile(r"\t.text\s*$") r_binaryinsn = re.compile(r"\t[a-z]\w*\s+("+OPERAND+"),\s*("+OPERAND+")\s*$") LOCALVAR = r"%eax|%edx|%ecx|%ebx|%esi|%edi|%ebp|\d*[(]%esp[)]" -r_gcroot_marker = re.compile(r"\t/[*] GCROOT ("+LOCALVAR+") [*]/") -r_localvar = re.compile(LOCALVAR) +LOCALVARFP = LOCALVAR + r"|-?\d*[(]%ebp[)]" +r_gcroot_marker = re.compile(r"\t/[*] GCROOT ("+LOCALVARFP+") [*]/") +r_localvarnofp = re.compile(LOCALVAR) +r_localvarfp = re.compile(LOCALVARFP) r_localvar_esp = re.compile(r"(\d*)[(]%esp[)]") +r_localvar_ebp = re.compile(r"(-?\d*)[(]%ebp[)]") class GcRootTracker(object): @@ -87,8 +90,7 @@ print >> sys.stderr, label, '\t', state if tracker.funcname == entrypoint: self.seen_main = True - xxx - table = [(label, (-1,)) for label, _ in table] + table = [(label, (-1,)+info[1:]) for label, info in table] # ^^^ we set the framesize of the entry point to -1 as a marker # (the code in asmgcroot.py actually takes any odd-valued number # as marker.) @@ -105,6 +107,8 @@ assert self.funcname == match.group(1) assert self.funcname == match.group(2) self.lines = lines + self.uses_frame_pointer = False + self.r_localvar = r_localvarnofp def computegcmaptable(self, verbose=0): self.findlabels() @@ -143,7 +147,10 @@ else: regindex = CALLEE_SAVE_REGISTERS.index(tag) info[1 + regindex] = loc - assert None not in info + if None in info: + reg = CALLEE_SAVE_REGISTERS[info.index(None) - 1] + raise AssertionError("cannot track where register %s is saved" + % (reg,)) table.append((insn.global_label, tuple(info))) return table @@ -216,7 +223,6 @@ return [insn for insn in self.insns if isinstance(insn, InsnCall)] def findframesize(self): - self.insns[0].framesize = 0 def walker(insn, size_delta): check = deltas.setdefault(insn, size_delta) @@ -258,6 +264,13 @@ localvar = ofs_from_esp - insn.framesize assert localvar != 0 # that's the return address setattr(insn, name, localvar) + elif self.uses_frame_pointer: + match = r_localvar_ebp.match(localvar) + if match: + ofs_from_ebp = int(match.group(1) or '0') + localvar = ofs_from_ebp - 4 + assert localvar != 0 # that's the return address + setattr(insn, name, localvar) def trackgcroots(self): @@ -281,16 +294,16 @@ pending = [] seen = {} def schedule(insn, state): - key = insn, state - if key not in seen: - seen[key] = True - pending.append(key) + for previnsn in insn.previous_insns: + key = previnsn, state + if key not in seen: + seen[key] = True + pending.append(key) schedule(initial_insn, initial_state) while pending: insn, state = pending.pop() for prevstate in walker(insn, state): - for previnsn in insn.previous_insns: - schedule(previnsn, prevstate) + schedule(insn, prevstate) def extend_calls_with_labels(self): # walk backwards, because inserting the global labels in self.lines @@ -364,7 +377,7 @@ count = match.group(1) assert count.startswith('$') return InsnStackAdjust(sign * int(count[1:])) - elif r_localvar.match(target): + elif self.r_localvar.match(target): return InsnSetLocal(target) else: return [] @@ -375,7 +388,7 @@ def unary_insn(self, line): match = r_unaryinsn.match(line) target = match.group(1) - if r_localvar.match(target): + if self.r_localvar.match(target): return InsnSetLocal(target) else: return [] @@ -390,7 +403,7 @@ if not match: raise UnrecognizedOperation(line) target = match.group(2) - if r_localvar.match(target): + if self.r_localvar.match(target): return InsnSetLocal(target) else: raise UnrecognizedOperation(line) @@ -417,8 +430,8 @@ def insns_for_copy(self, source, target): if source == '%esp' or target == '%esp': raise UnrecognizedOperation('%s -> %s' % (source, target)) - elif r_localvar.match(target): - if r_localvar.match(source): + elif self.r_localvar.match(target): + if self.r_localvar.match(source): return [InsnCopyLocal(source, target)] else: return [InsnSetLocal(target)] @@ -429,6 +442,10 @@ match = r_binaryinsn.match(line) source = match.group(1) target = match.group(2) + if source == '%esp' and target == '%ebp': + return self._visit_prologue() + elif source == '%ebp' and target == '%esp': + return self._visit_epilogue() return self.insns_for_copy(source, target) def visit_pushl(self, line): @@ -436,10 +453,27 @@ source = match.group(1) return [InsnStackAdjust(-4)] + self.insns_for_copy(source, '(%esp)') + def _visit_pop(self, target): + return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)] + def visit_popl(self, line): match = r_unaryinsn.match(line) target = match.group(1) - return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)] + return self._visit_pop(target) + + def _visit_prologue(self): + # for the prologue of functions that use %ebp as frame pointer + self.uses_frame_pointer = True + self.r_localvar = r_localvarfp + return [InsnPrologue()] + + def _visit_epilogue(self): + if not self.uses_frame_pointer: + raise UnrecognizedOperation('epilogue without prologue') + return [InsnEpilogue()] + + def visit_leave(self, line): + return self._visit_epilogue() + self._visit_pop('%ebp') def visit_ret(self, line): return InsnRet() @@ -463,7 +497,7 @@ raise LeaveBasicBlock if r_unaryinsn_star.match(line): # that looks like an indirect tail-call. - return InsnStop() + return InsnRet() # tail-calls are equivalent to RET for us try: self.conditional_jump(line) except KeyError: @@ -471,6 +505,7 @@ match = r_unaryinsn.match(line) target = match.group(1) assert not target.startswith('.') + return InsnRet() # tail-calls are equivalent to RET for us return InsnStop() def register_jump_to(self, label): @@ -552,6 +587,7 @@ self.previous_insns = [] # all insns that jump (or fallthrough) here class InsnFunctionStart(Insn): + framesize = 0 previous_insns = () def __init__(self): self.arguments = {} @@ -596,6 +632,7 @@ pass class InsnRet(InsnStop): + framesize = 0 def requestgcroots(self): return dict(zip(CALLEE_SAVE_REGISTERS, CALLEE_SAVE_REGISTERS)) @@ -631,11 +668,25 @@ class InsnGCROOT(Insn): _args_ = ['loc'] + _locals_ = ['loc'] def __init__(self, loc): self.loc = loc def requestgcroots(self): return {self.loc: None} +class InsnPrologue(Insn): + def __setattr__(self, attr, value): + if attr == 'framesize': + assert value == 4, ("unrecognized function prologue - " + "only supports push %ebp; movl %esp, %ebp") + Insn.__setattr__(self, attr, value) + +class InsnEpilogue(Insn): + framesize = 4 + def requestgcroots(self): + return dict(zip(CALLEE_SAVE_REGISTERS_NOEBP, + CALLEE_SAVE_REGISTERS_NOEBP)) + FUNCTIONS_NOT_RETURNING = { 'abort': None, @@ -643,7 +694,8 @@ '__assert_fail': None, } -CALLEE_SAVE_REGISTERS = ['%ebx', '%esi', '%edi', '%ebp'] +CALLEE_SAVE_REGISTERS_NOEBP = ['%ebx', '%esi', '%edi'] +CALLEE_SAVE_REGISTERS = CALLEE_SAVE_REGISTERS_NOEBP + ['%ebp'] if __name__ == '__main__': From fijal at codespeak.net Thu Jan 3 12:43:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 3 Jan 2008 12:43:13 +0100 (CET) Subject: [pypy-svn] r50286 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080103114313.19C4616845F@codespeak.net> Author: fijal Date: Thu Jan 3 12:43:12 2008 New Revision: 50286 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Kill some dead code Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Jan 3 12:43:12 2008 @@ -182,54 +182,6 @@ aroundstate = AroundState() aroundstate._freeze_() -def _callback(arg, TP): - return lltype.functionptr(TP.TO, arg.func_name, _callable=arg) -_callback._annspecialcase_ = 'specialize:arg(1)' - -class Entry(ExtRegistryEntry): - _about_ = _callback - _CACHE = {} - - def compute_result_annotation(self, s_pbc, s_TP): - assert s_TP.is_constant() - assert s_pbc.is_constant() - # XXX in general this can be non-constant, but get_unique_llfn - # will not work in this case - TP = s_TP.const - bk = self.bookkeeper - args_s = [annmodel.lltype_to_annotation(ll_arg) for ll_arg in TP.TO.ARGS] - res = bk.emulate_pbc_call(s_pbc, s_pbc, args_s) - return annmodel.SomePtr(TP) - - # this is some wrapper creation for handling exceptions. - # I think this is ugly and better way is needed for that, - # but we definitely need a way to express exception raising inside - # the callback function - - #def _get_or_create_wrapper_pbc(self, bk, func): - # try: - # return self._CACHE[func] - # except: - # def wrapper(*args): - # try: - # return func(*args) - # except Exception, e: - # os.write(2, "Unhandled Fatal RPython exception %s in callback" % str(e)) - # return 0 - # # we ignore exception here, we can exit the program as well - # # not sure what is the best way - # s_pbc = annmodel.SomePBC([bk.getdesc(wrapper)]) - # self._CACHE[func] = s_pbc - # return s_pbc - - def specialize_call(self, hop): - #hop.exception_cannot_occur() - ## XXX fish a bit to have a wrapper here, not sure if annmixlevel - ## is not waaaay better here - #repr = hop.rtyper.getrepr(self._CACHE[hop.args_s[0].const]) - repr = hop.args_r[0] - return repr.get_unique_llfn() - # ____________________________________________________________ TYPES = [] From arigo at codespeak.net Thu Jan 3 14:13:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 14:13:33 +0100 (CET) Subject: [pypy-svn] r50287 - in pypy/branch/asmgcroot/pypy: rpython/memory/gctransform translator/c Message-ID: <20080103131333.32BDE16845F@codespeak.net> Author: arigo Date: Thu Jan 3 14:13:31 2008 New Revision: 50287 Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Small progresses. I'm a bit blocked though. Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py Thu Jan 3 14:13:31 2008 @@ -1,5 +1,5 @@ from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython import rmodel from pypy.rpython.rbuiltin import gen_cast @@ -54,11 +54,13 @@ append_static_root = staticmethod(append_static_root) def __init__(self, with_static=True): - self.stack_current = llop.llvm_frameaddress(llmemory.Address) + self.callee_data = lltype.malloc(ASM_STACKWALK, flavor="raw") + self.caller_data = lltype.malloc(ASM_STACKWALK, flavor="raw") + pypy_asm_stackwalk_init(self.caller_data) self.remaining_roots_in_current_frame = 0 # We must walk at least a couple of frames up the stack # *now*, i.e. before we leave __init__, otherwise - # self.stack_current ends up pointing to a dead frame. + # the caller_data ends up pointing to a dead frame. # We can walk until we find a real GC root; then we're # definitely out of the GC code itself. while self.remaining_roots_in_current_frame == 0: @@ -86,77 +88,105 @@ return result def walk_to_parent_frame(self): + if not self.caller_data: + return False # # The gcmap table is a list of pairs of pointers: # void *SafePointAddress; # void *Shape; # # A "safe point" is the return address of a call. - # The "shape" of a safe point records the size of the - # frame of the function containing it, as well as a - # list of the variables that contain gc roots at that - # time. Each variable is described by its offset in - # the frame. - # - callee_frame = self.stack_current - if llmemory.cast_adr_to_int(callee_frame) & 1: - return False # odd bit set here when the callee_frame - # is the frame of main(), i.e. when there - # is nothing more for us in the stack. + # The "shape" of a safe point is a list of integers + # as follows: + # + # * The size of the frame of the function containing the + # call (in theory it can be different from call to call). + # This size includes the return address (see picture + # below). + # + # * Four integers that specify where the function saves + # each of the four callee-saved registers (%ebx, %esi, + # %edi, %ebp). This is a "location", see below. + # + # * The number of live GC roots around the call. + # + # * For each GC root, an integer that specify where the + # GC pointer is stored. This is a "location", see below. + # + # A "location" can be either in the stack or in a register. + # If it is in the stack, it is specified as an integer offset + # from the current frame (so it is typically < 0, as seen + # in the picture below, though it can also be > 0 if the + # location is an input argument to the current function and + # thus lives at the bottom of the caller's frame). + # A "location" can also be in a register; in our context it + # can only be a callee-saved register. This is specified + # as a small odd-valued integer (1=%ebx, 3=%esi, etc.) + + # In the code below, we walk the next older frame on the stack. + # The caller becomes the callee; we swap the two buffers and + # fill in the new caller's data. + callee = self.caller_data + caller = self.callee_data + self.caller_data = caller + self.callee_data = callee # # XXX the details are completely specific to X86!!! # a picture of the stack may help: # ^ ^ ^ # | ... | to older frames # +--------------+ - # | first word | <------ caller_frame (addr of 1st word) - # + + + # | ret addr | <------ caller_frame (addr of retaddr) + # | ... | # | caller frame | # | ... | - # | frame data | <------ frame_data_base - # +--------------+ - # | ret addr | # +--------------+ - # | first word | <------ callee_frame (addr of 1st word) - # + + - # | callee frame | + # | ret addr | <------ callee_frame (addr of retaddr) # | ... | - # | frame data | lower addresses + # | callee frame | + # | ... | lower addresses # +--------------+ v v v # - retaddr = callee_frame.address[1] + callee_frame = callee[FRAME_PTR] + retaddr = callee[RET_ADDR] # # try to locate the caller function based on retaddr. # gcmapstart = llop.llvm_gcmapstart(llmemory.Address) gcmapend = llop.llvm_gcmapend(llmemory.Address) item = binary_search(gcmapstart, gcmapend, retaddr) - if item.address[0] == retaddr: - # - # found! Setup pointers allowing us to - # parse the caller's frame structure... - # - shape = item.address[1] - # XXX assumes that .signed is 32-bit - framesize = shape.signed[0] # odd if it's main() - livecount = shape.signed[1] - caller_frame = callee_frame + 4 + framesize - self.stack_current = caller_frame - self.frame_data_base = callee_frame + 8 - self.remaining_roots_in_current_frame = livecount - self.liveoffsets = shape + 8 - return True - - # retaddr not found! - llop.debug_fatalerror(lltype.Void, "cannot find gc roots!") - return False + if item.address[0] != retaddr: + # retaddr not found! + llop.debug_fatalerror(lltype.Void, "cannot find gc roots!") + return False + + # found! Now we can fill in 'caller'. + shape = item.address[1] + framesize = shape.signed[0] + caller[FRAME_PTR] = callee_frame + framesize + caller[RET_ADDR] = caller[FRAME_PTR].address[0] + reg = 0 + while reg < CALLEE_SAVED_REGS: + caller[reg] = self.read_from_location(shape.signed[1+reg]) + reg += 1 + livecount = shape.signed[1+CALLEE_SAVED_REGS] + self.remaining_roots_in_current_frame = livecount + self.liveoffsets = shape + 4 * (1+CALLEE_SAVED_REGS+1) + return True + + def finished(self): + lltype.free(self.stackwalkcur, flavor='raw') + self.stackwalkcur = lltype.nullptr(ASM_STACKWALK) + lltype.free(self.stackwalknext, flavor='raw') + self.stackwalknext = lltype.nullptr(ASM_STACKWALK) def next_gcroot_from_current_frame(self): i = self.remaining_roots_in_current_frame - 1 self.remaining_roots_in_current_frame = i ll_assert(i >= 0, "bad call to next_gcroot_from_current_frame") liveoffset = self.liveoffsets.signed[i] - return self.frame_data_base + liveoffset + return self.callee_data[FRAME_PTR] + liveoffset + ... return StackRootIterator @@ -206,3 +236,29 @@ scan.address[0] = addr1 scan.address[1] = addr2 next += arrayitemsize + +# +# The special pypy_asm_stackwalk_init(), implemented directly in +# assembler, initializes an ASM_STACKWALK array in order to bootstrap +# the stack walking code. An ASM_STACKWALK is an array of 6 values +# that describe everything we need to know about a stack frame: +# +# - the value that %ebx had when the current function started +# - the value that %esi had when the current function started +# - the value that %edi had when the current function started +# - the value that %ebp had when the current function started +# - frame address (actually the addr of the retaddr of the current function; +# that's the last word of the frame in memory) +# - the return address for when the current function finishes +# (which is usually just the word at "frame address") +# +CALLEE_SAVED_REGS = 4 # there are 4 callee-saved registers +FRAME_PTR = CALLEE_SAVED_REGS +RET_ADDR = CALLEE_SAVED_REGS + 1 +ASM_STACKWALK = lltype.FixedSizeArray(llmemory.Address, CALLEE_SAVED_REGS + 2) + +pypy_asm_stackwalk_init = rffi.llexternal('pypy_asm_stackwalk_init', + [lltype.Ptr(ASM_STACKWALK)], + lltype.Void, + sandboxsafe=True, + _nowrapper=True) Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 14:13:31 2008 @@ -34,6 +34,22 @@ def dump(self, output): assert self.seen_main shapes = {} + print >> output, """\t.text + .globl pypy_asm_stackwalk_init + .type pypy_asm_stackwalk_init, @function + pypy_asm_stackwalk_init: + /* See description in asmgcroot.py */ + movl 4(%esp), %edx /* argument */ + movl %ebx, (%edx) + movl %esi, 4(%edx) + movl %edi, 8(%edx) + movl %ebp, 12(%edx) + movl %esp, 16(%edx) + movl (%esp), %eax + movl %eax, 20(%edx) + ret + .size pypy_asm_stackwalk_init, .-pypy_asm_stackwalk_init + """ print >> output, '\t.data' print >> output, '\t.align\t4' print >> output, '\t.globl\t__gcmapstart' @@ -54,11 +70,13 @@ print >> output, '\t.align\t4' keys = shapes.keys() keys.sort() + FIXED = 1 + len(CALLEE_SAVE_REGISTERS) for state in keys: print >> output, '%s:' % (shapes[state],) - print >> output, '\t.long\t%d' % (state[0],) # frame size - print >> output, '\t.long\t%d' % (len(state)-1,) # gcroot count - for p in state[1:]: + for i in range(FIXED): + print >> output, '\t.long\t%d' % (state[i],) + print >> output, '\t.long\t%d' % (len(state)-FIXED,) + for p in state[FIXED:]: print >> output, '\t.long\t%d' % (p,) # gcroots def process(self, iterlines, newfile, entrypoint='main', filename='?'): @@ -89,14 +107,25 @@ for label, state in table: print >> sys.stderr, label, '\t', state if tracker.funcname == entrypoint: - self.seen_main = True - table = [(label, (-1,)+info[1:]) for label, info in table] - # ^^^ we set the framesize of the entry point to -1 as a marker - # (the code in asmgcroot.py actually takes any odd-valued number - # as marker.) + table = self.fixup_entrypoint_table(table) self.gcmaptable.extend(table) newfile.writelines(tracker.lines) + def fixup_entrypoint_table(self, table): + self.seen_main = True + # we don't need to track where the main() function saved its + # own caller's registers. So as a marker, we set the + # corresponding entries in the shape to -1. The code in + # asmgcroot recognizes these markers as meaning "stop walking + # the stack". + newtable = [] + for label, shape in table: + shape = list(shape) + for i in range(len(CALLEE_SAVE_REGISTERS)): + shape[1+i] = -1 + newtable.append((label, tuple(shape))) + return newtable + class FunctionGcRootTracker(object): @@ -127,31 +156,34 @@ return self.gettable() def gettable(self): - "Returns a list [(label_after_call, (framesize, gcroot0, gcroot1,..))]" + """Returns a list [(label_after_call, shape_tuple)] + where shape_tuple = (framesize, where_is_ebx_saved, ... + ..., where_is_ebp_saved, gcroot0, gcroot1...) + """ table = [] for insn in self.list_call_insns(): if not hasattr(insn, 'framesize'): continue # calls that never end up reaching a RET - info = [insn.framesize] + shape = [insn.framesize + 4] # accounts for the return address # the first gcroots are always the ones corresponding to # the callee-saved registers for reg in CALLEE_SAVE_REGISTERS: - info.append(None) + shape.append(None) for loc, tag in insn.gcroots.items(): if not isinstance(loc, int): # a special representation for a register location, # as an odd-valued number loc = CALLEE_SAVE_REGISTERS.index(loc) * 2 + 1 if tag is None: - info.append(loc) + shape.append(loc) else: regindex = CALLEE_SAVE_REGISTERS.index(tag) - info[1 + regindex] = loc - if None in info: - reg = CALLEE_SAVE_REGISTERS[info.index(None) - 1] + shape[1 + regindex] = loc + if None in shape: + reg = CALLEE_SAVE_REGISTERS[shape.index(None) - 1] raise AssertionError("cannot track where register %s is saved" % (reg,)) - table.append((insn.global_label, tuple(info))) + table.append((insn.global_label, tuple(shape))) return table def findlabels(self): From arigo at codespeak.net Thu Jan 3 15:17:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 15:17:12 +0100 (CET) Subject: [pypy-svn] r50288 - in pypy/branch/asmgcroot/pypy/rpython/memory: . gc gctransform Message-ID: <20080103141712.4DD341684BF@codespeak.net> Author: arigo Date: Thu Jan 3 15:17:10 2008 New Revision: 50288 Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gc/base.py pypy/branch/asmgcroot/pypy/rpython/memory/gc/generation.py pypy/branch/asmgcroot/pypy/rpython/memory/gc/semispace.py pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/stacklessframework.py pypy/branch/asmgcroot/pypy/rpython/memory/gcwrapper.py Log: Yet Another intermediate check-in... Thinking about changing the approach. Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gc/base.py Thu Jan 3 15:17:10 2008 @@ -29,6 +29,9 @@ self.varsize_offsets_to_gcpointers_in_var_part = varsize_offsets_to_gcpointers_in_var_part self.weakpointer_offset = weakpointer_offset + def set_root_walker(self, root_walker): + self.root_walker = root_walker + def write_barrier(self, oldvalue, newvalue, addr_struct): pass Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gc/generation.py Thu Jan 3 15:17:10 2008 @@ -33,12 +33,10 @@ def __init__(self, AddressLinkedList, nursery_size=128, space_size=4096, - max_space_size=sys.maxint//2+1, - get_roots=None): + max_space_size=sys.maxint//2+1): SemiSpaceGC.__init__(self, AddressLinkedList, space_size = space_size, - max_space_size = max_space_size, - get_roots = get_roots) + max_space_size = max_space_size) self.nursery_size = nursery_size assert nursery_size <= space_size // 2 @@ -239,19 +237,15 @@ # if a prebuilt GcStruct contains a pointer to a young object, # then the write_barrier must have ensured that the prebuilt # GcStruct is in the list self.old_objects_pointing_to_young. - roots = self.get_roots(with_static=False) - count = 0 - while 1: - root = roots.pop() - if root == NULL: - break - count += 1 - obj = root.address[0] - if self.is_in_nursery(obj): - root.address[0] = self.copy(obj) - if DEBUG_PRINT: - llop.debug_print(lltype.Void, "collect_roots_in_nursery", count) - free_non_gc_object(roots) + self.root_walker.walk_roots( + GenerationGC._collect_root_in_nursery, # stack roots + GenerationGC._collect_root_in_nursery, # static in prebuilt non-gc + None) # static in prebuilt gc + + def _collect_root_in_nursery(self, root): + obj = root.address[0] + if self.is_in_nursery(obj): + root.address[0] = self.copy(obj) def scan_objects_just_copied_out_of_nursery(self, scan): while scan < self.free: @@ -296,7 +290,7 @@ self.remember_young_pointer(addr_struct, newvalue) def append_to_static_roots(self, pointer, arg): - self.get_roots.append_static_root(pointer) + self.root_walker.append_static_root(pointer) def move_to_static_roots(self, addr_struct): objhdr = self.header(addr_struct) Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gc/semispace.py Thu Jan 3 15:17:10 2008 @@ -28,12 +28,10 @@ ('tid', lltype.Signed)) def __init__(self, AddressLinkedList, space_size=4096, - max_space_size=sys.maxint//2+1, - get_roots=None): + max_space_size=sys.maxint//2+1): MovingGCBase.__init__(self) self.space_size = space_size self.max_space_size = max_space_size - self.get_roots = get_roots self.gcheaderbuilder = GCHeaderBuilder(self.HDR) self.AddressLinkedList = AddressLinkedList @@ -228,13 +226,13 @@ return scan def collect_roots(self): - roots = self.get_roots() - while 1: - root = roots.pop() - if root == NULL: - break - root.address[0] = self.copy(root.address[0]) - free_non_gc_object(roots) + self.root_walker.walk_roots( + SemiSpaceGC._collect_root, # stack roots + SemiSpaceGC._collect_root, # static in prebuilt non-gc structures + SemiSpaceGC._collect_root) # static in prebuilt gc objects + + def _collect_root(self, root): + root.address[0] = self.copy(root.address[0]) def copy(self, obj): # Objects not living the GC heap have all been initialized by Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py Thu Jan 3 15:17:10 2008 @@ -28,13 +28,14 @@ for var in livevars: hop.genop("asm_gcroot", [var]) - def build_stack_root_iterator(self): + def build_root_walker(self): gcdata = self.gcdata + gc = gcdata.gc - class StackRootIterator: + class RootWalker: _alloc_flavor_ = 'raw' - def setup_root_stack(): + def setup_root_stack(self): # The gcmap table is a list of pairs of pointers: # void *SafePointAddress; # void *Shape; @@ -44,7 +45,6 @@ gcmapstart = llop.llvm_gcmapstart(llmemory.Address) gcmapend = llop.llvm_gcmapend(llmemory.Address) insertion_sort(gcmapstart, gcmapend) - setup_root_stack = staticmethod(setup_root_stack) need_root_stack = False @@ -52,8 +52,12 @@ gcdata.static_root_end.address[0] = adr gcdata.static_root_end += sizeofaddr append_static_root = staticmethod(append_static_root) - - def __init__(self, with_static=True): + + def walk_roots(self, collect_stack_root, + collect_static_in_prebuilt_nongc, + collect_static_in_prebuilt_gc, + collect_finished): + ... self.callee_data = lltype.malloc(ASM_STACKWALK, flavor="raw") self.caller_data = lltype.malloc(ASM_STACKWALK, flavor="raw") pypy_asm_stackwalk_init(self.caller_data) @@ -186,10 +190,8 @@ ll_assert(i >= 0, "bad call to next_gcroot_from_current_frame") liveoffset = self.liveoffsets.signed[i] return self.callee_data[FRAME_PTR] + liveoffset - ... - - return StackRootIterator + return RootWalker() sizeofaddr = llmemory.sizeof(llmemory.Address) Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py Thu Jan 3 15:17:10 2008 @@ -133,15 +133,16 @@ sizeofaddr = llmemory.sizeof(llmemory.Address) - StackRootIterator = self.build_stack_root_iterator() - gcdata.gc = GCClass(AddressLinkedList, get_roots=StackRootIterator, **GC_PARAMS) + gcdata.gc = GCClass(AddressLinkedList, **GC_PARAMS) + root_walker = self.build_root_walker() gcdata.set_query_functions(gcdata.gc) + gcdata.set_root_walker(gcdata.gc, root_walker) self.num_pushs = 0 self.write_barrier_calls = 0 def frameworkgc_setup(): # run-time initialization code - StackRootIterator.setup_root_stack() + root_walker.setup_root_stack() gcdata.gc.setup() bk = self.translator.annotator.bookkeeper @@ -172,19 +173,19 @@ self.frameworkgc_setup_ptr = getfn(frameworkgc_setup, [], annmodel.s_None) - if StackRootIterator.need_root_stack: - #self.pop_root_ptr = getfn(StackRootIterator.pop_root, [], + if RootWalker.need_root_stack: + #self.pop_root_ptr = getfn(RootWalker.pop_root, [], # annmodel.SomeAddress(), # inline = True) - #self.push_root_ptr = getfn(StackRootIterator.push_root, + #self.push_root_ptr = getfn(RootWalker.push_root, # [annmodel.SomeAddress()], # annmodel.s_None, # inline = True) - self.incr_stack_ptr = getfn(StackRootIterator.incr_stack, + self.incr_stack_ptr = getfn(RootWalker.incr_stack, [annmodel.SomeInteger()], annmodel.SomeAddress(), inline = True) - self.decr_stack_ptr = getfn(StackRootIterator.decr_stack, + self.decr_stack_ptr = getfn(RootWalker.decr_stack, [annmodel.SomeInteger()], annmodel.SomeAddress(), inline = True) @@ -350,12 +351,12 @@ FLDTYPE = getattr(HDR, fldname) fields.append(('_' + fldname, FLDTYPE)) - def build_stack_root_iterator(self): + def build_root_walker(self): gcdata = self.gcdata sizeofaddr = llmemory.sizeof(llmemory.Address) rootstacksize = sizeofaddr * self.root_stack_depth - class StackRootIterator: + class RootWalker: _alloc_flavor_ = 'raw' def setup_root_stack(): stackbase = llmemory.raw_malloc(rootstacksize) Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/stacklessframework.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/stacklessframework.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/stacklessframework.py Thu Jan 3 15:17:10 2008 @@ -37,6 +37,7 @@ ## self.inline_helpers(graph) def build_stack_root_iterator(self): + xxx from pypy.rlib.rstack import stack_capture sizeofaddr = llmemory.sizeof(llmemory.Address) gcdata = self.gcdata Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gcwrapper.py Thu Jan 3 15:17:10 2008 @@ -11,13 +11,10 @@ def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}): self.AddressLinkedList = get_address_linked_list(10) self.gc = gc_class(self.AddressLinkedList, **GC_PARAMS) - def my_get_roots(with_static=True): - return self.get_roots_from_llinterp(with_static) - self.gc.get_roots = my_get_roots + self.gc.set_root_walker(LLInterpRootWalker(self)) self.llinterp = llinterp self.prepare_graphs(flowgraphs) self.gc.setup() - my_get_roots.append_static_root = self.constantroots.append def prepare_graphs(self, flowgraphs): layoutbuilder = DirectRunLayoutBuilder(self.llinterp) @@ -32,21 +29,6 @@ self.constantroots = list(layoutbuilder.addresses_of_static_ptrs) self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc - def get_roots_from_llinterp(self, with_static=True): - sizeofaddr = llmemory.sizeof(llmemory.Address) - ll = [llmemory.NULL] # end marker - if with_static: - for addrofaddr in self.constantroots: - if addrofaddr.address[0]: - ll.append(addrofaddr) - for addrofaddr in self.constantrootsnongc: - if addrofaddr.address[0]: - ll.append(addrofaddr) - for addrofaddr in self.llinterp.find_roots(): - if addrofaddr.address[0]: - ll.append(addrofaddr) - return RootLinkedList(ll) - # ____________________________________________________________ # # Interface for the llinterp @@ -120,14 +102,34 @@ return self.gc.id(ptr) - # ____________________________________________________________ +# ____________________________________________________________ -class RootLinkedList(object): +class LLInterpRootWalker: _alloc_flavor_ = 'raw' - def __init__(self, lst): - self._lst = lst - self.pop = lst.pop + def __init__(self, gcheap): + self.gcheap = gcheap + + def append_static_root(self, pointer): + self.gcheap.constantroots.append(pointer) + + def walk_roots(self, collect_stack_root, + collect_static_in_prebuilt_nongc, + collect_static_in_prebuilt_gc): + gcheap = self.gcheap + gc = gcheap.gc + if collect_static_in_prebuilt_gc: + for addrofaddr in gcheap.constantroots: + if addrofaddr.address[0]: + collect_static_in_prebuilt_gc(gc, addrofaddr) + if collect_static_in_prebuilt_nongc: + for addrofaddr in gcheap.constantrootsnongc: + if addrofaddr.address[0]: + collect_static_in_prebuilt_nongc(gc, addrofaddr) + if collect_stack_root: + for addrofaddr in gcheap.llinterp.find_roots(): + if addrofaddr.address[0]: + collect_stack_root(gc, addrofaddr) class DirectRunLayoutBuilder(gctypelayout.TypeLayoutBuilder): From arigo at codespeak.net Thu Jan 3 17:36:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 17:36:57 +0100 (CET) Subject: [pypy-svn] r50290 - in pypy/branch/asmgcroot/pypy: rpython/memory/gctransform translator/c Message-ID: <20080103163657.B68CF1684C7@codespeak.net> Author: arigo Date: Thu Jan 3 17:36:56 2008 New Revision: 50290 Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Invoke the GC root walking via a callback. This allows us to save and restore all the callee-saved registers into the stack at a single clear place: pypy_asm_stackwalk(). Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py Thu Jan 3 17:36:56 2008 @@ -1,8 +1,8 @@ from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer +from pypy.rpython.memory.gctransform.framework import BaseRootWalker from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rpython import rmodel -from pypy.rpython.rbuiltin import gen_cast +from pypy.rpython.annlowlevel import llhelper from pypy.rlib.debug import ll_assert @@ -29,170 +29,174 @@ hop.genop("asm_gcroot", [var]) def build_root_walker(self): - gcdata = self.gcdata - gc = gcdata.gc + return AsmStackRootWalker(self) + + +class AsmStackRootWalker(BaseRootWalker): + + def __init__(self, gctransformer): + BaseRootWalker.__init__(self, gctransformer) + + def _asm_callback(initialframedata): + self.walk_stack_from(initialframedata) + self._asm_callback = _asm_callback + + def setup_root_walker(self): + # The gcmap table is a list of pairs of pointers: + # void *SafePointAddress; + # void *Shape; + # Here, i.e. when the program starts, we sort it + # in-place on the SafePointAddress to allow for more + # efficient searches. + gcmapstart = llop.llvm_gcmapstart(llmemory.Address) + gcmapend = llop.llvm_gcmapend(llmemory.Address) + insertion_sort(gcmapstart, gcmapend) - class RootWalker: - _alloc_flavor_ = 'raw' + def walk_stack_roots(self, collect_stack_root): + gcdata = self.gcdata + gcdata._gc_collect_stack_root = collect_stack_root + pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback)) - def setup_root_stack(self): - # The gcmap table is a list of pairs of pointers: - # void *SafePointAddress; - # void *Shape; - # Here, i.e. when the program starts, we sort it - # in-place on the SafePointAddress to allow for more - # efficient searches. - gcmapstart = llop.llvm_gcmapstart(llmemory.Address) - gcmapend = llop.llvm_gcmapend(llmemory.Address) - insertion_sort(gcmapstart, gcmapend) - - need_root_stack = False - - def append_static_root(adr): - gcdata.static_root_end.address[0] = adr - gcdata.static_root_end += sizeofaddr - append_static_root = staticmethod(append_static_root) - - def walk_roots(self, collect_stack_root, - collect_static_in_prebuilt_nongc, - collect_static_in_prebuilt_gc, - collect_finished): - ... - self.callee_data = lltype.malloc(ASM_STACKWALK, flavor="raw") - self.caller_data = lltype.malloc(ASM_STACKWALK, flavor="raw") - pypy_asm_stackwalk_init(self.caller_data) - self.remaining_roots_in_current_frame = 0 - # We must walk at least a couple of frames up the stack - # *now*, i.e. before we leave __init__, otherwise - # the caller_data ends up pointing to a dead frame. - # We can walk until we find a real GC root; then we're - # definitely out of the GC code itself. - while self.remaining_roots_in_current_frame == 0: - if not self.walk_to_parent_frame(): - break # not a single GC root? unlikely but not - # impossible I guess - if with_static: - self.static_current = gcdata.static_root_end - else: - self.static_current = gcdata.static_root_nongcend - - def pop(self): - while self.static_current != gcdata.static_root_start: - self.static_current -= sizeofaddr - result = self.static_current.address[0] - if result.address[0] != llmemory.NULL: - return result - - while True: - while self.remaining_roots_in_current_frame == 0: - if not self.walk_to_parent_frame(): - return llmemory.NULL - result = self.next_gcroot_from_current_frame() - if result.address[0] != llmemory.NULL: - return result - - def walk_to_parent_frame(self): - if not self.caller_data: - return False - # - # The gcmap table is a list of pairs of pointers: - # void *SafePointAddress; - # void *Shape; - # - # A "safe point" is the return address of a call. - # The "shape" of a safe point is a list of integers - # as follows: - # - # * The size of the frame of the function containing the - # call (in theory it can be different from call to call). - # This size includes the return address (see picture - # below). - # - # * Four integers that specify where the function saves - # each of the four callee-saved registers (%ebx, %esi, - # %edi, %ebp). This is a "location", see below. - # - # * The number of live GC roots around the call. - # - # * For each GC root, an integer that specify where the - # GC pointer is stored. This is a "location", see below. - # - # A "location" can be either in the stack or in a register. - # If it is in the stack, it is specified as an integer offset - # from the current frame (so it is typically < 0, as seen - # in the picture below, though it can also be > 0 if the - # location is an input argument to the current function and - # thus lives at the bottom of the caller's frame). - # A "location" can also be in a register; in our context it - # can only be a callee-saved register. This is specified - # as a small odd-valued integer (1=%ebx, 3=%esi, etc.) - - # In the code below, we walk the next older frame on the stack. - # The caller becomes the callee; we swap the two buffers and - # fill in the new caller's data. - callee = self.caller_data - caller = self.callee_data - self.caller_data = caller - self.callee_data = callee - # - # XXX the details are completely specific to X86!!! - # a picture of the stack may help: - # ^ ^ ^ - # | ... | to older frames - # +--------------+ - # | ret addr | <------ caller_frame (addr of retaddr) - # | ... | - # | caller frame | - # | ... | - # +--------------+ - # | ret addr | <------ callee_frame (addr of retaddr) - # | ... | - # | callee frame | - # | ... | lower addresses - # +--------------+ v v v - # - callee_frame = callee[FRAME_PTR] - retaddr = callee[RET_ADDR] - # - # try to locate the caller function based on retaddr. - # - gcmapstart = llop.llvm_gcmapstart(llmemory.Address) - gcmapend = llop.llvm_gcmapend(llmemory.Address) - item = binary_search(gcmapstart, gcmapend, retaddr) - if item.address[0] != retaddr: - # retaddr not found! - llop.debug_fatalerror(lltype.Void, "cannot find gc roots!") - return False - - # found! Now we can fill in 'caller'. - shape = item.address[1] - framesize = shape.signed[0] - caller[FRAME_PTR] = callee_frame + framesize - caller[RET_ADDR] = caller[FRAME_PTR].address[0] - reg = 0 - while reg < CALLEE_SAVED_REGS: - caller[reg] = self.read_from_location(shape.signed[1+reg]) - reg += 1 - livecount = shape.signed[1+CALLEE_SAVED_REGS] - self.remaining_roots_in_current_frame = livecount - self.liveoffsets = shape + 4 * (1+CALLEE_SAVED_REGS+1) - return True - - def finished(self): - lltype.free(self.stackwalkcur, flavor='raw') - self.stackwalkcur = lltype.nullptr(ASM_STACKWALK) - lltype.free(self.stackwalknext, flavor='raw') - self.stackwalknext = lltype.nullptr(ASM_STACKWALK) - - def next_gcroot_from_current_frame(self): - i = self.remaining_roots_in_current_frame - 1 - self.remaining_roots_in_current_frame = i - ll_assert(i >= 0, "bad call to next_gcroot_from_current_frame") - liveoffset = self.liveoffsets.signed[i] - return self.callee_data[FRAME_PTR] + liveoffset + def walk_stack_from(self, initialframedata): + curframe = lltype.malloc(WALKFRAME, flavor='raw') + otherframe = lltype.malloc(WALKFRAME, flavor='raw') + self.fill_initial_frame(curframe, initialframedata) + # Loop over all the frames in the stack + while self.walk_to_parent_frame(curframe, otherframe): + swap = curframe + curframe = otherframe # caller becomes callee + otherframe = swap + lltype.free(otherframe, flavor='raw') + lltype.free(curframe, flavor='raw') + + def fill_initial_frame(self, curframe, initialframedata): + # Read the information provided by initialframedata + reg = 0 + while reg < CALLEE_SAVED_REGS: + # NB. 'initialframedata' stores the actual values of the + # registers %ebx etc., and if these values are modified + # they are reloaded by pypy_asm_stackwalk(). By contrast, + # 'regs_stored_at' merely points to the actual values + # from the 'initialframedata'. + curframe.regs_stored_at[reg] = initialframedata + reg*sizeofaddr + reg += 1 + curframe.frame_address = initialframedata.address[CALLEE_SAVED_REGS] + + def walk_to_parent_frame(self, callee, caller): + """Starting from 'callee', walk the next older frame on the stack + and fill 'caller' accordingly. Also invokes the collect_stack_root() + callback from the GC code for each GC root found in 'caller'. + """ + # + # The gcmap table is a list of pairs of pointers: + # void *SafePointAddress; + # void *Shape; + # + # A "safe point" is the return address of a call. + # The "shape" of a safe point is a list of integers + # as follows: + # + # * The size of the frame of the function containing the + # call (in theory it can be different from call to call). + # This size includes the return address (see picture + # below). + # + # * Four integers that specify where the function saves + # each of the four callee-saved registers (%ebx, %esi, + # %edi, %ebp). This is a "location", see below. + # + # * The number of live GC roots around the call. + # + # * For each GC root, an integer that specify where the + # GC pointer is stored. This is a "location", see below. + # + # A "location" can be either in the stack or in a register. + # If it is in the stack, it is specified as an integer offset + # from the current frame (so it is typically < 0, as seen + # in the picture below, though it can also be > 0 if the + # location is an input argument to the current function and + # thus lives at the bottom of the caller's frame). + # A "location" can also be in a register; in our context it + # can only be a callee-saved register. This is specified + # as a small odd-valued integer (1=%ebx, 3=%esi, etc.) + # + # XXX the details are completely specific to X86!!! + # a picture of the stack may help: + # ^ ^ ^ + # | ... | to older frames + # +--------------+ + # | ret addr | <------ caller_frame (addr of retaddr) + # | ... | + # | caller frame | + # | ... | + # +--------------+ + # | ret addr | <------ callee_frame (addr of retaddr) + # | ... | + # | callee frame | + # | ... | lower addresses + # +--------------+ v v v + # + + retaddr = callee.frame_address.address[0] + # + # try to locate the caller function based on retaddr. + # + gcmapstart = llop.llvm_gcmapstart(llmemory.Address) + gcmapend = llop.llvm_gcmapend(llmemory.Address) + item = binary_search(gcmapstart, gcmapend, retaddr) + if item.address[0] != retaddr: + # retaddr not found! + llop.debug_fatalerror(lltype.Void, "cannot find gc roots!") + return False + # + # found! Now we can go to the caller_frame. + # + shape = item.address[1] + framesize = shape.signed[0] + caller.frame_address = callee.frame_address + framesize + # + # enumerate the GC roots in the caller frame + # + collect_stack_root = self.gcdata._gc_collect_stack_root + gc = self.gc + LIVELOCS = 1 + CALLEE_SAVED_REGS + 1 # index of the first gc root loc + livecount = shape.signed[LIVELOCS-1] + while livecount > 0: + livecount -= 1 + location = shape.signed[LIVELOCS + livecount] + addr = self.getlocation(callee, caller, location) + if addr.address[0] != llmemory.NULL: + collect_stack_root(gc, addr) + # + # track where the caller_frame saved the registers from its own + # caller + # + if shape.signed[1] == -1: # a marker that means "I'm the frame + return False # of the entry point, stop walking" + reg = 0 + while reg < CALLEE_SAVED_REGS: + location = shape.signed[1+reg] + addr = self.getlocation(callee, caller, location) + caller.regs_stored_at[reg] = addr + reg += 1 + return True + + def getlocation(self, callee, caller, location): + """Get the location in the 'caller' frame of a variable, based + on the integer 'location' that describes it. The 'callee' is + only used if the location is in a register that was saved in the + callee. + """ + if location & 1: # register + reg = location >> 1 + ll_assert(0 <= reg < CALLEE_SAVED_REGS, "bad register location") + return callee.regs_stored_at[reg] + else: + # in the stack frame + return caller.frame_address + location - return RootWalker() +# ____________________________________________________________ sizeofaddr = llmemory.sizeof(llmemory.Address) arrayitemsize = 2 * sizeofaddr @@ -239,11 +243,14 @@ scan.address[1] = addr2 next += arrayitemsize +# ____________________________________________________________ + # -# The special pypy_asm_stackwalk_init(), implemented directly in -# assembler, initializes an ASM_STACKWALK array in order to bootstrap -# the stack walking code. An ASM_STACKWALK is an array of 6 values -# that describe everything we need to know about a stack frame: +# The special pypy_asm_stackwalk(), implemented directly in +# assembler, fills information about the current stack top in an +# ASM_FRAMEDATA array and invokes an RPython callback with it. +# An ASM_FRAMEDATA is an array of 5 values that describe everything +# we need to know about a stack frame: # # - the value that %ebx had when the current function started # - the value that %esi had when the current function started @@ -251,16 +258,23 @@ # - the value that %ebp had when the current function started # - frame address (actually the addr of the retaddr of the current function; # that's the last word of the frame in memory) -# - the return address for when the current function finishes -# (which is usually just the word at "frame address") # CALLEE_SAVED_REGS = 4 # there are 4 callee-saved registers -FRAME_PTR = CALLEE_SAVED_REGS -RET_ADDR = CALLEE_SAVED_REGS + 1 -ASM_STACKWALK = lltype.FixedSizeArray(llmemory.Address, CALLEE_SAVED_REGS + 2) - -pypy_asm_stackwalk_init = rffi.llexternal('pypy_asm_stackwalk_init', - [lltype.Ptr(ASM_STACKWALK)], - lltype.Void, - sandboxsafe=True, - _nowrapper=True) +FRAME_PTR = CALLEE_SAVED_REGS # the frame is at index 4 in the array + +ASM_CALLBACK_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], + lltype.Void)) + +# used internally by walk_stack_from() +WALKFRAME = lltype.Struct('WALKFRAME', + ('regs_stored_at', # address of where the registers have been saved + lltype.FixedSizeArray(llmemory.Address, CALLEE_SAVED_REGS)), + ('frame_address', + llmemory.Address), + ) + +pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', + [ASM_CALLBACK_PTR], + lltype.Void, + sandboxsafe=True, + _nowrapper=True) Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py Thu Jan 3 17:36:56 2008 @@ -131,18 +131,16 @@ self.gcdata = gcdata self.malloc_fnptr_cache = {} - sizeofaddr = llmemory.sizeof(llmemory.Address) - gcdata.gc = GCClass(AddressLinkedList, **GC_PARAMS) root_walker = self.build_root_walker() gcdata.set_query_functions(gcdata.gc) - gcdata.set_root_walker(gcdata.gc, root_walker) + gcdata.gc.set_root_walker(root_walker) self.num_pushs = 0 self.write_barrier_calls = 0 def frameworkgc_setup(): # run-time initialization code - root_walker.setup_root_stack() + root_walker.setup_root_walker() gcdata.gc.setup() bk = self.translator.annotator.bookkeeper @@ -173,25 +171,16 @@ self.frameworkgc_setup_ptr = getfn(frameworkgc_setup, [], annmodel.s_None) - if RootWalker.need_root_stack: - #self.pop_root_ptr = getfn(RootWalker.pop_root, [], - # annmodel.SomeAddress(), - # inline = True) - #self.push_root_ptr = getfn(RootWalker.push_root, - # [annmodel.SomeAddress()], - # annmodel.s_None, - # inline = True) - self.incr_stack_ptr = getfn(RootWalker.incr_stack, + if root_walker.need_root_stack: + self.incr_stack_ptr = getfn(root_walker.incr_stack, [annmodel.SomeInteger()], annmodel.SomeAddress(), inline = True) - self.decr_stack_ptr = getfn(RootWalker.decr_stack, + self.decr_stack_ptr = getfn(root_walker.decr_stack, [annmodel.SomeInteger()], annmodel.SomeAddress(), inline = True) else: - #self.push_root_ptr = None - #self.pop_root_ptr = None self.incr_stack_ptr = None self.decr_stack_ptr = None self.weakref_deref_ptr = self.inittime_helper( @@ -352,71 +341,7 @@ fields.append(('_' + fldname, FLDTYPE)) def build_root_walker(self): - gcdata = self.gcdata - sizeofaddr = llmemory.sizeof(llmemory.Address) - rootstacksize = sizeofaddr * self.root_stack_depth - - class RootWalker: - _alloc_flavor_ = 'raw' - def setup_root_stack(): - stackbase = llmemory.raw_malloc(rootstacksize) - ll_assert(bool(stackbase), "could not allocate root stack") - llmemory.raw_memclear(stackbase, rootstacksize) - gcdata.root_stack_top = stackbase - gcdata.root_stack_base = stackbase - setup_root_stack = staticmethod(setup_root_stack) - - need_root_stack = True - - def incr_stack(n): - top = gcdata.root_stack_top - gcdata.root_stack_top = top + n*sizeofaddr - return top - incr_stack = staticmethod(incr_stack) - - def append_static_root(adr): - gcdata.static_root_end.address[0] = adr - gcdata.static_root_end += sizeofaddr - append_static_root = staticmethod(append_static_root) - - def decr_stack(n): - top = gcdata.root_stack_top - n*sizeofaddr - gcdata.root_stack_top = top - return top - decr_stack = staticmethod(decr_stack) - - def push_root(addr): - top = gcdata.root_stack_top - top.address[0] = addr - gcdata.root_stack_top = top + sizeofaddr - push_root = staticmethod(push_root) - - def pop_root(): - top = gcdata.root_stack_top - sizeofaddr - gcdata.root_stack_top = top - return top.address[0] - pop_root = staticmethod(pop_root) - - def __init__(self, with_static=True): - self.stack_current = gcdata.root_stack_top - if with_static: - self.static_current = gcdata.static_root_end - else: - self.static_current = gcdata.static_root_nongcend - - def pop(self): - while self.static_current != gcdata.static_root_start: - self.static_current -= sizeofaddr - result = self.static_current.address[0] - if result.address[0] != llmemory.NULL: - return result - while self.stack_current != gcdata.root_stack_base: - self.stack_current -= sizeofaddr - if self.stack_current.address[0] != llmemory.NULL: - return self.stack_current - return llmemory.NULL - - return StackRootIterator + return ShadowStackRootWalker(self) def consider_constant(self, TYPE, value): self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc) @@ -830,3 +755,87 @@ [v] + previous_steps + [c_name, c_null]) elif isinstance(FIELD, lltype.Struct): gen_zero_gc_pointers(FIELD, v, llops, previous_steps + [c_name]) + +# ____________________________________________________________ + + +sizeofaddr = llmemory.sizeof(llmemory.Address) + + +class BaseRootWalker: + need_root_stack = False + + def __init__(self, gctransformer): + self.gcdata = gctransformer.gcdata + self.gc = self.gcdata.gc + + def _freeze_(self): + return True + + def setup_root_walker(self): + pass + + def append_static_root(self, adr): + self.gcdata.static_root_end.address[0] = adr + self.gcdata.static_root_end += sizeofaddr + + def walk_roots(self, collect_stack_root, + collect_static_in_prebuilt_nongc, + collect_static_in_prebuilt_gc): + gcdata = self.gcdata + gc = self.gc + if collect_static_in_prebuilt_nongc: + addr = gcdata.static_root_start + end = gcdata.static_root_nongcend + while addr != end: + if addr.address[0] != llmemory.NULL: + collect_static_in_prebuilt_nongc(gc, addr) + addr += sizeofaddr + if collect_static_in_prebuilt_gc: + addr = gcdata.static_root_nongcend + end = gcdata.static_root_end + while addr != end: + if addr.address[0] != llmemory.NULL: + collect_static_in_prebuilt_gc(gc, addr) + addr += sizeofaddr + if collect_stack_root: + self.walk_stack_roots(collect_stack_root) # abstract + + +class ShadowStackRootWalker(BaseRootWalker): + need_root_stack = True + + def __init__(self, gctransformer): + BaseRootWalker.__init__(self, gctransformer) + self.rootstacksize = sizeofaddr * gctransformer.root_stack_depth + # NB. 'self' is frozen, but we can use self.gcdata to store state + gcdata = self.gcdata + + def incr_stack(n): + top = gcdata.root_stack_top + gcdata.root_stack_top = top + n*sizeofaddr + return top + self.incr_stack = incr_stack + + def decr_stack(n): + top = gcdata.root_stack_top - n*sizeofaddr + gcdata.root_stack_top = top + return top + self.decr_stack = decr_stack + + def setup_root_walker(self): + stackbase = llmemory.raw_malloc(self.rootstacksize) + ll_assert(bool(stackbase), "could not allocate root stack") + llmemory.raw_memclear(stackbase, self.rootstacksize) + self.gcdata.root_stack_top = stackbase + self.gcdata.root_stack_base = stackbase + + def walk_stack_roots(self, collect_stack_root): + gcdata = self.gcdata + gc = self.gc + addr = gcdata.root_stack_base + end = gcdata.root_stack_top + while addr != end: + if addr.address[0] != llmemory.NULL: + collect_stack_root(gc, addr) + addr += sizeofaddr Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 17:36:56 2008 @@ -35,18 +35,26 @@ assert self.seen_main shapes = {} print >> output, """\t.text - .globl pypy_asm_stackwalk_init - .type pypy_asm_stackwalk_init, @function - pypy_asm_stackwalk_init: + .globl pypy_asm_stackwalk + .type pypy_asm_stackwalk, @function + pypy_asm_stackwalk: /* See description in asmgcroot.py */ - movl 4(%esp), %edx /* argument */ - movl %ebx, (%edx) - movl %esi, 4(%edx) - movl %edi, 8(%edx) - movl %ebp, 12(%edx) - movl %esp, 16(%edx) - movl (%esp), %eax - movl %eax, 20(%edx) + movl 4(%esp), %edx /* my argument, which is the callback */ + movl (%esp), %eax /* my return address */ + pushl %eax /* ASM_FRAMEDATA[4] */ + pushl %ebp /* ASM_FRAMEDATA[3] */ + pushl %edi /* ASM_FRAMEDATA[2] */ + pushl %esi /* ASM_FRAMEDATA[1] */ + pushl %ebx /* ASM_FRAMEDATA[0] */ + movl %esp, %eax /* address of ASM_FRAMEDATA */ + pushl %eax + call *%edx /* invoke the callback */ + popl %eax + popl %ebx /* restore from ASM_FRAMEDATA[0] */ + popl %esi /* restore from ASM_FRAMEDATA[1] */ + popl %edi /* restore from ASM_FRAMEDATA[2] */ + popl %ebp /* restore from ASM_FRAMEDATA[3] */ + popl %eax ret .size pypy_asm_stackwalk_init, .-pypy_asm_stackwalk_init """ From arigo at codespeak.net Thu Jan 3 18:31:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 18:31:08 +0100 (CET) Subject: [pypy-svn] r50292 - pypy/branch/asmgcroot/pypy/rpython/memory/gctransform Message-ID: <20080103173108.9DCAA1684CE@codespeak.net> Author: arigo Date: Thu Jan 3 18:31:06 2008 New Revision: 50292 Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py Log: Just lost an hour debugging this stupid typo. Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/framework.py Thu Jan 3 18:31:06 2008 @@ -788,15 +788,17 @@ addr = gcdata.static_root_start end = gcdata.static_root_nongcend while addr != end: - if addr.address[0] != llmemory.NULL: - collect_static_in_prebuilt_nongc(gc, addr) + result = addr.address[0] + if result.address[0] != llmemory.NULL: + collect_static_in_prebuilt_nongc(gc, result) addr += sizeofaddr if collect_static_in_prebuilt_gc: addr = gcdata.static_root_nongcend end = gcdata.static_root_end while addr != end: - if addr.address[0] != llmemory.NULL: - collect_static_in_prebuilt_gc(gc, addr) + result = addr.address[0] + if result.address[0] != llmemory.NULL: + collect_static_in_prebuilt_gc(gc, result) addr += sizeofaddr if collect_stack_root: self.walk_stack_roots(collect_stack_root) # abstract From arigo at codespeak.net Thu Jan 3 18:58:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 18:58:04 +0100 (CET) Subject: [pypy-svn] r50293 - in pypy/branch/asmgcroot/pypy: rpython/memory/gctransform translator/c Message-ID: <20080103175804.EB1B116845A@codespeak.net> Author: arigo Date: Thu Jan 3 18:58:04 2008 New Revision: 50293 Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: targetgcbench runs! Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py Thu Jan 3 18:58:04 2008 @@ -153,7 +153,12 @@ # shape = item.address[1] framesize = shape.signed[0] - caller.frame_address = callee.frame_address + framesize + if framesize == 0: + # frame size not known, use %ebp to find the frame address + caller_ebp = callee.regs_stored_at[INDEX_OF_EBP].address[0] + caller.frame_address = caller_ebp + 4 + else: + caller.frame_address = callee.frame_address + framesize # # enumerate the GC roots in the caller frame # @@ -171,8 +176,8 @@ # track where the caller_frame saved the registers from its own # caller # - if shape.signed[1] == -1: # a marker that means "I'm the frame - return False # of the entry point, stop walking" + if framesize == 0: # a marker that means "I'm the frame + return False # of the entry point, stop walking" reg = 0 while reg < CALLEE_SAVED_REGS: location = shape.signed[1+reg] @@ -260,6 +265,7 @@ # that's the last word of the frame in memory) # CALLEE_SAVED_REGS = 4 # there are 4 callee-saved registers +INDEX_OF_EBP = 3 FRAME_PTR = CALLEE_SAVED_REGS # the frame is at index 4 in the array ASM_CALLBACK_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 18:58:04 2008 @@ -40,7 +40,7 @@ pypy_asm_stackwalk: /* See description in asmgcroot.py */ movl 4(%esp), %edx /* my argument, which is the callback */ - movl (%esp), %eax /* my return address */ + movl %esp, %eax /* my frame top address */ pushl %eax /* ASM_FRAMEDATA[4] */ pushl %ebp /* ASM_FRAMEDATA[3] */ pushl %edi /* ASM_FRAMEDATA[2] */ @@ -107,6 +107,7 @@ def process_function(self, lines, newfile, entrypoint, filename): tracker = FunctionGcRootTracker(lines) + tracker.is_main = tracker.funcname == entrypoint if self.verbose: print >> sys.stderr, '[trackgcroot:%s] %s' % (filename, tracker.funcname) @@ -114,24 +115,21 @@ if self.verbose > 1: for label, state in table: print >> sys.stderr, label, '\t', state - if tracker.funcname == entrypoint: + if tracker.is_main: + assert tracker.uses_frame_pointer table = self.fixup_entrypoint_table(table) self.gcmaptable.extend(table) newfile.writelines(tracker.lines) def fixup_entrypoint_table(self, table): self.seen_main = True - # we don't need to track where the main() function saved its - # own caller's registers. So as a marker, we set the - # corresponding entries in the shape to -1. The code in - # asmgcroot recognizes these markers as meaning "stop walking - # the stack". + # the main() function contains strange code that aligns the stack + # pointer to a multiple of 16, which messes up our framesize + # computation. So just for this function, and as an end marker, + # we use a frame size of 0. newtable = [] for label, shape in table: - shape = list(shape) - for i in range(len(CALLEE_SAVE_REGISTERS)): - shape[1+i] = -1 - newtable.append((label, tuple(shape))) + newtable.append((label, (0,) + shape[1:])) return newtable @@ -146,6 +144,7 @@ self.lines = lines self.uses_frame_pointer = False self.r_localvar = r_localvarnofp + self.is_main = False def computegcmaptable(self, verbose=0): self.findlabels() @@ -274,7 +273,7 @@ yield size_delta # continue walking backwards for insn in self.insns: - if insn.requestgcroots(): + if isinstance(insn, (InsnRet, InsnEpilogue, InsnGCROOT)): deltas = {} self.walk_instructions_backwards(walker, insn, 0) size_at_insn = [] @@ -433,11 +432,6 @@ else: return [] -## visit_incl = unary_insn -## visit_decl = unary_insn -## visit_notl = unary_insn -## visit_negl = unary_insn - def binary_insn(self, line): match = r_binaryinsn.match(line) if not match: @@ -449,11 +443,34 @@ raise UnrecognizedOperation(line) visit_xorl = binary_insn # used in "xor reg, reg" to create a NULL GC ptr -## visit_orl = binary_insn -## visit_andl = binary_insn -## visit_movzbl = binary_insn -## visit_movzwl = binary_insn - visit_leal = binary_insn + visit_orl = binary_insn + + def visit_andl(self, line): + match = r_binaryinsn.match(line) + target = match.group(2) + if target == '%esp': + # only for andl $-16, %esp used to align the stack in main(). + # gcc should not use %esp-relative addressing in such a function + # so we can just ignore it + assert self.is_main + return [] + else: + return self.binary_insn(line) + + def visit_leal(self, line): + match = r_binaryinsn.match(line) + target = match.group(2) + if target == '%esp': + # only for leal -12(%ebp), %esp in function epilogues + source = match.group(1) + match = r_localvar_ebp.match(source) + if not match: + raise UnrecognizedOperation(line) + ofs_from_ebp = int(match.group(1) or '0') + assert ofs_from_ebp < 0 + return InsnEpilogue(framesize = 4 - ofs_from_ebp) + else: + return self.binary_insn(line) def unary_or_binary_insn(self, line): if r_binaryinsn.match(line): @@ -461,12 +478,6 @@ else: return self.unary_insn(line) -## visit_shll = unary_or_binary_insn -## visit_shrl = unary_or_binary_insn -## visit_sall = unary_or_binary_insn -## visit_sarl = unary_or_binary_insn -## visit_imull = unary_or_binary_insn - def insns_for_copy(self, source, target): if source == '%esp' or target == '%esp': raise UnrecognizedOperation('%s -> %s' % (source, target)) @@ -507,10 +518,10 @@ self.r_localvar = r_localvarfp return [InsnPrologue()] - def _visit_epilogue(self): + def _visit_epilogue(self, framesize=4): if not self.uses_frame_pointer: raise UnrecognizedOperation('epilogue without prologue') - return [InsnEpilogue()] + return [InsnEpilogue(framesize)] def visit_leave(self, line): return self._visit_epilogue() + self._visit_pop('%ebp') @@ -722,10 +733,8 @@ Insn.__setattr__(self, attr, value) class InsnEpilogue(Insn): - framesize = 4 - def requestgcroots(self): - return dict(zip(CALLEE_SAVE_REGISTERS_NOEBP, - CALLEE_SAVE_REGISTERS_NOEBP)) + def __init__(self, framesize=4): + self.framesize = framesize FUNCTIONS_NOT_RETURNING = { From arigo at codespeak.net Thu Jan 3 19:04:41 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 19:04:41 +0100 (CET) Subject: [pypy-svn] r50294 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103180441.CBACB16845E@codespeak.net> Author: arigo Date: Thu Jan 3 19:04:41 2008 New Revision: 50294 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Support for "operation source, (memory target)" Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 19:04:41 2008 @@ -439,8 +439,10 @@ target = match.group(2) if self.r_localvar.match(target): return InsnSetLocal(target) - else: + elif target == '%esp': raise UnrecognizedOperation(line) + else: + return [] visit_xorl = binary_insn # used in "xor reg, reg" to create a NULL GC ptr visit_orl = binary_insn @@ -472,12 +474,6 @@ else: return self.binary_insn(line) - def unary_or_binary_insn(self, line): - if r_binaryinsn.match(line): - return self.binary_insn(line) - else: - return self.unary_insn(line) - def insns_for_copy(self, source, target): if source == '%esp' or target == '%esp': raise UnrecognizedOperation('%s -> %s' % (source, target)) From arigo at codespeak.net Thu Jan 3 19:18:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 19:18:14 +0100 (CET) Subject: [pypy-svn] r50295 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103181814.CB2181684D5@codespeak.net> Author: arigo Date: Thu Jan 3 19:18:13 2008 New Revision: 50295 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Clean-ups. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 19:18:13 2008 @@ -373,7 +373,7 @@ if label not in self.labels: break k += 1 - self.labels[label] = call.lineno+1 + self.labels[label] = None self.lines.insert(call.lineno+1, '%s:\n' % (label,)) self.lines.insert(call.lineno+1, '\t.globl\t%s\n' % (label,)) call.global_label = label @@ -592,19 +592,6 @@ return [InsnCall(self.currentlineno), InsnSetLocal('%eax')] # the result is there - def visit_pypygetframeaddress(self, line): - xxx - # this is a pseudo-instruction that is emitted to find the first - # frame address on the stack. We cannot just use - # __builtin_frame_address(0) - apparently, gcc thinks it can - # return %ebp even if -fomit-frame-pointer is specified, which - # doesn't work. - match = r_unaryinsn.match(line) - reg = match.group(1) - newline = '\tleal\t%d(%%esp), %s\t/* pypygetframeaddress */\n' % ( - self.framesize-4, reg) - self.lines[self.currentlinenum] = newline - class UnrecognizedOperation(Exception): pass From arigo at codespeak.net Thu Jan 3 19:24:46 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 19:24:46 +0100 (CET) Subject: [pypy-svn] r50296 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103182446.7C9D91684D0@codespeak.net> Author: arigo Date: Thu Jan 3 19:24:45 2008 New Revision: 50296 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: targetprologstandalone works. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 19:24:45 2008 @@ -195,12 +195,12 @@ def findlabels(self): self.labels = {} # {name: Label()} - for line in self.lines: + for lineno, line in enumerate(self.lines): match = r_label.match(line) if match: label = match.group(1) assert label not in self.labels, "duplicate label" - self.labels[label] = Label(label) + self.labels[label] = Label(label, lineno) def parse_instructions(self): self.insns = [InsnFunctionStart()] @@ -394,7 +394,7 @@ # floating-point operations cannot produce GC pointers 'f', # arithmetic operations should not produce GC pointers - 'inc', 'dec', 'not', 'neg', 'or', 'and', + 'inc', 'dec', 'not', 'neg', 'or', 'and', 'sbb', 'adc', 'shl', 'shr', 'sal', 'sar', 'mul', 'imul', 'div', 'idiv', # zero-extending moves should not produce GC pointers 'movz', @@ -528,20 +528,18 @@ def visit_jmp(self, line): match = r_jmp_switch.match(line) if match: - xxx # this is a jmp *Label(%index), used for table-based switches. # Assume that the table is just a list of lines looking like # .long LABEL or .long 0, ending in a .text. tablelabel = match.group(1) - tablelin = self.labels[tablelabel] + 1 + tablelin = self.labels[tablelabel].lineno + 1 while not r_jmptable_end.match(self.lines[tablelin]): match = r_jmptable_item.match(self.lines[tablelin]) label = match.group(1) if label != '0': - targetlin = self.labels[label] - self.propagate_state_to(targetlin) + self.register_jump_to(label) tablelin += 1 - raise LeaveBasicBlock + return InsnStop() if r_unaryinsn_star.match(line): # that looks like an indirect tail-call. return InsnRet() # tail-calls are equivalent to RET for us @@ -615,9 +613,10 @@ return localvar class Label(Insn): - _args_ = ['label'] - def __init__(self, label): + _args_ = ['label', 'lineno'] + def __init__(self, label, lineno): self.label = label + self.lineno = lineno self.previous_insns = [] # all insns that jump (or fallthrough) here class InsnFunctionStart(Insn): From cfbolz at codespeak.net Thu Jan 3 20:28:12 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 3 Jan 2008 20:28:12 +0100 (CET) Subject: [pypy-svn] r50297 - pypy/branch/astcompilertests/pypy/interpreter/pyparser Message-ID: <20080103192812.3969C16845F@codespeak.net> Author: cfbolz Date: Thu Jan 3 20:28:10 2008 New Revision: 50297 Modified: pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonlexer.py Log: kill dead code Modified: pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonlexer.py Thu Jan 3 20:28:10 2008 @@ -154,15 +154,8 @@ pos = pos + 1 if pos == max: break - if line[pos] in '#\r\n': # skip comments or blank lines - if line[pos] == '#': - tok = Token(parser, parser.tokens['COMMENT'], line[pos:]) - last_comment = line[pos:] - else: - tok = Token(parser, parser.tokens['NL'], line[pos:]) - last_comment = '' - # XXX Skip NL and COMMENT Tokens - # token_list.append((tok, line, lnum, pos)) + if line[pos] in '#\r\n': + # skip comments or blank lines continue if column > indents[-1]: # count indents or dedents @@ -203,21 +196,15 @@ token_list.append((tok, line, lnum, pos)) last_comment = '' elif initial in '\r\n': - if parenlev > 0: - tok = Token(parser, parser.tokens['NL'], token) - last_comment = '' - # XXX Skip NL - else: + if parenlev <= 0: tok = Token(parser, parser.tokens['NEWLINE'], token) # XXX YUCK ! tok.value = last_comment token_list.append((tok, line, lnum, pos)) - last_comment = '' + last_comment = '' elif initial == '#': - tok = Token(parser, parser.tokens['COMMENT'], token) + # skip comment last_comment = token - # XXX Skip # token_list.append((tok, line, lnum, pos)) - # token_list.append((COMMENT, token, spos, epos, line)) elif token in triple_quoted: endDFA = endDFAs[token] endmatch = endDFA.recognize(line, pos) From arigo at codespeak.net Thu Jan 3 20:46:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 20:46:13 +0100 (CET) Subject: [pypy-svn] r50298 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080103194613.92D0B16844A@codespeak.net> Author: arigo Date: Thu Jan 3 20:46:13 2008 New Revision: 50298 Modified: pypy/dist/pypy/rpython/memory/gc/base.py Log: Update a comment with an "XXX maybe that's wrong after all" Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Thu Jan 3 20:46:13 2008 @@ -161,6 +161,12 @@ # more non-prebuild GC objects; this is fine because the # internal GC ptr in the prebuilt list or dict is found by # gctypelayout and listed in addresses_of_static_ptrs. + + # XXX I'm not sure any more about the warning above. The fields + # of 'self' are found by gctypelayout and added to + # addresses_of_static_ptrs_in_nongc, so in principle they could + # be mutated and still be found by collect(). + self.wr_to_objects_with_id = [] self.object_id_dict = {} self.object_id_dict_ends_at = 0 From arigo at codespeak.net Thu Jan 3 21:51:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 3 Jan 2008 21:51:36 +0100 (CET) Subject: [pypy-svn] r50299 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080103205136.1CEE316847A@codespeak.net> Author: arigo Date: Thu Jan 3 21:51:33 2008 New Revision: 50299 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Progress translating pypy-c-faassen. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Thu Jan 3 21:51:33 2008 @@ -13,7 +13,7 @@ r_unaryinsn_star= re.compile(r"\t[a-z]\w*\s+([*]"+OPERAND+")\s*$") r_jmp_switch = re.compile(r"\tjmp\t[*]([.]?\w+)[(]") r_jmptable_item = re.compile(r"\t.long\t([.]?\w+)\s*$") -r_jmptable_end = re.compile(r"\t.text\s*$") +r_jmptable_end = re.compile(r"\t.text|\t.section\s+.text") r_binaryinsn = re.compile(r"\t[a-z]\w*\s+("+OPERAND+"),\s*("+OPERAND+")\s*$") LOCALVAR = r"%eax|%edx|%ecx|%ebx|%esi|%edi|%ebp|\d*[(]%esp[)]" LOCALVARFP = LOCALVAR + r"|-?\d*[(]%ebp[)]" @@ -390,12 +390,12 @@ IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([ 'cmp', 'test', 'set', 'sahf', 'cltd', 'cld', 'std', - 'rep', 'movs', + 'rep', 'movs', 'lods', 'stos', 'scas', # floating-point operations cannot produce GC pointers 'f', # arithmetic operations should not produce GC pointers 'inc', 'dec', 'not', 'neg', 'or', 'and', 'sbb', 'adc', - 'shl', 'shr', 'sal', 'sar', 'mul', 'imul', 'div', 'idiv', + 'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'mul', 'imul', 'div', 'idiv', # zero-extending moves should not produce GC pointers 'movz', ]) @@ -455,6 +455,7 @@ # gcc should not use %esp-relative addressing in such a function # so we can just ignore it assert self.is_main + self.uses_frame_pointer = True return [] else: return self.binary_insn(line) @@ -467,10 +468,12 @@ source = match.group(1) match = r_localvar_ebp.match(source) if not match: - raise UnrecognizedOperation(line) - ofs_from_ebp = int(match.group(1) or '0') - assert ofs_from_ebp < 0 - return InsnEpilogue(framesize = 4 - ofs_from_ebp) + framesize = None # strange instruction + else: + ofs_from_ebp = int(match.group(1) or '0') + assert ofs_from_ebp < 0 + framesize = 4 - ofs_from_ebp + return InsnEpilogue(framesize) else: return self.binary_insn(line) @@ -514,10 +517,10 @@ self.r_localvar = r_localvarfp return [InsnPrologue()] - def _visit_epilogue(self, framesize=4): + def _visit_epilogue(self): if not self.uses_frame_pointer: raise UnrecognizedOperation('epilogue without prologue') - return [InsnEpilogue(framesize)] + return [InsnEpilogue(4)] def visit_leave(self, line): return self._visit_epilogue() + self._visit_pop('%ebp') @@ -530,11 +533,13 @@ if match: # this is a jmp *Label(%index), used for table-based switches. # Assume that the table is just a list of lines looking like - # .long LABEL or .long 0, ending in a .text. + # .long LABEL or .long 0, ending in a .text or .section .text.hot. tablelabel = match.group(1) tablelin = self.labels[tablelabel].lineno + 1 while not r_jmptable_end.match(self.lines[tablelin]): match = r_jmptable_item.match(self.lines[tablelin]) + if not match: + raise NoPatternMatch(self.lines[tablelin]) label = match.group(1) if label != '0': self.register_jump_to(label) @@ -594,6 +599,9 @@ class UnrecognizedOperation(Exception): pass +class NoPatternMatch(Exception): + pass + class SomeNewValue(object): pass somenewvalue = SomeNewValue() @@ -715,8 +723,9 @@ Insn.__setattr__(self, attr, value) class InsnEpilogue(Insn): - def __init__(self, framesize=4): - self.framesize = framesize + def __init__(self, framesize=None): + if framesize is not None: + self.framesize = framesize FUNCTIONS_NOT_RETURNING = { From cfbolz at codespeak.net Thu Jan 3 23:26:04 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 3 Jan 2008 23:26:04 +0100 (CET) Subject: [pypy-svn] r50300 - pypy/branch/astcompilertests/pypy/interpreter/pyparser Message-ID: <20080103222604.12760168513@codespeak.net> Author: cfbolz Date: Thu Jan 3 23:26:03 2008 New Revision: 50300 Modified: pypy/branch/astcompilertests/pypy/interpreter/pyparser/grammar.py pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonparse.py Log: kill dead code Modified: pypy/branch/astcompilertests/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/pyparser/grammar.py Thu Jan 3 23:26:03 2008 @@ -73,32 +73,6 @@ ###################################################################### - -def build_first_sets(rules): - """XXX : dead - builds the real first tokens set for each rule in - - Because a rule can be recursive (directly or indirectly), the - *simplest* algorithm to build each first set is to recompute them - until Computation(N) = Computation(N-1), N being the number of rounds. - As an example, on Python2.3's grammar, we need 19 cycles to compute - full first sets. - """ - changed = True - while changed: - # loop while one first set is changed - changed = False - for rule in rules: - # For each rule, recompute first set - size = len(rule.first_set) - rule.calc_first_set() - new_size = len(rule.first_set) - if new_size != size: - changed = True - for r in rules: - assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r - r.reorder_rule() - class AbstractContext(object): """Abstract base class. derived objects put some attributes here that users can use to save Modified: pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonparse.py Thu Jan 3 23:26:03 2008 @@ -174,21 +174,3 @@ parser.build_first_sets() parser.keywords = builder.keywords return 0 - - -## XXX BROKEN -## def parse_grammar(space, w_src): -## """Loads the grammar using the 'dynamic' rpython parser""" -## src = space.str_w( w_src ) -## ebnfbuilder = ebnfparse.parse_grammar_text( src ) -## ebnfbuilder.resolve_rules() -## grammar.build_first_sets(ebnfbuilder.all_rules) -## return space.wrap( ebnfbuilder.root_rules ) - -# XXX Unused? -def grammar_rules( space ): - w_rules = space.newdict() - parser = make_pyparser(space.config.objspace.pyversion) - for key, value in parser.rules.iteritems(): - space.setitem(w_rules, space.wrap(key), space.wrap(value)) - return w_rules From cfbolz at codespeak.net Fri Jan 4 00:16:03 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Jan 2008 00:16:03 +0100 (CET) Subject: [pypy-svn] r50302 - pypy/branch/parser-playground Message-ID: <20080103231603.B36BE168450@codespeak.net> Author: cfbolz Date: Fri Jan 4 00:16:02 2008 New Revision: 50302 Added: pypy/branch/parser-playground/ - copied from r50301, pypy/branch/astcompilertests/ Log: branch off armin's parser branch to play around with the parser in general From cfbolz at codespeak.net Fri Jan 4 00:18:41 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Jan 2008 00:18:41 +0100 (CET) Subject: [pypy-svn] r50303 - in pypy/branch/parser-playground/pypy: interpreter interpreter/pyparser module/dyngram module/recparser/test Message-ID: <20080103231841.793DD16840B@codespeak.net> Author: cfbolz Date: Fri Jan 4 00:18:40 2008 New Revision: 50303 Removed: pypy/branch/parser-playground/pypy/module/dyngram/ pypy/branch/parser-playground/pypy/module/recparser/test/test_dyn_grammarrules.py Modified: pypy/branch/parser-playground/pypy/interpreter/baseobjspace.py pypy/branch/parser-playground/pypy/interpreter/pycompiler.py pypy/branch/parser-playground/pypy/interpreter/pyparser/pythonparse.py Log: kill support for dynamic grammar modifications Modified: pypy/branch/parser-playground/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/parser-playground/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/parser-playground/pypy/interpreter/baseobjspace.py Fri Jan 4 00:18:40 2008 @@ -433,11 +433,9 @@ except AttributeError: if self.config.objspace.compiler == 'cpython': compiler = CPythonCompiler(self) - elif self.config.objspace.compiler == 'ast': - compiler = PythonAstCompiler(self) else: - raise ValueError('unknown --compiler option value: %r' % ( - self.config.objspace.compiler,)) + assert self.config.objspace.compiler == 'ast' + compiler = PythonAstCompiler(self) self.default_compiler = compiler return compiler Modified: pypy/branch/parser-playground/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/parser-playground/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/parser-playground/pypy/interpreter/pycompiler.py Fri Jan 4 00:18:40 2008 @@ -219,7 +219,6 @@ PyCodeCompiler.__init__(self, space) self.grammar_version = override_version or space.config.objspace.pyversion self.parser = make_pyparser(self.grammar_version) - self.additional_rules = {} if self.grammar_version >= '2.5': self.futureFlags = future.futureFlags_2_5 else: @@ -244,9 +243,6 @@ space = self.space try: builder = AstBuilder(self.parser, self.grammar_version, space=space) - for rulename, buildfunc in self.additional_rules.iteritems(): - assert isinstance(buildfunc, Function) - builder.user_build_rules[rulename] = buildfunc flags |= getFutures(self.futureFlags, source) self.parser.parse_source(source, mode, builder, flags) ast_tree = builder.rule_stack[-1] @@ -291,27 +287,3 @@ # raise OperationError( space.w_TypeError( space.wrap( "must have a callable" ) ) space.default_compiler.w_compile_hook = w_callable -def insert_grammar_rule(space, w_rule, w_buildfuncs): - """inserts new grammar rules to the default compiler""" - from pypy.interpreter import function - rule = space.str_w(w_rule) - #buildfuncs_w = w_buildfuncs.content - buildfuncs = {} - #for w_name, w_func in buildfuncs_w.iteritems(): - # buildfuncs[space.str_w(w_name)] = space.unwrap(w_func) - w_iter = space.iter(w_buildfuncs) - while 1: - try: - w_key = space.next(w_iter) - w_func = space.getitem(w_buildfuncs, w_key) - buildfuncs[space.str_w(w_key)] = space.interp_w(function.Function, w_func) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - break - space.default_compiler.additional_rules = buildfuncs - space.default_compiler.parser.insert_rule(rule) - -# XXX cyclic import -#from pypy.interpreter.baseobjspace import ObjSpace -#insert_grammar_rule.unwrap_spec = [ObjSpace, str, dict] Modified: pypy/branch/parser-playground/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/parser-playground/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/parser-playground/pypy/interpreter/pyparser/pythonparse.py Fri Jan 4 00:18:40 2008 @@ -131,33 +131,9 @@ # return None return builder - def update_rules_references(self): - """update references to old rules""" - # brute force algorithm - for rule in self.all_rules: - for i in range(len(rule.args)): - arg = rule.args[i] - if arg.codename in self.root_rules: - real_rule = self.root_rules[arg.codename] - # This rule has been updated - if real_rule is not rule.args[i]: - rule.args[i] = real_rule - - - def insert_rule(self, ruledef): - """parses and inserts corresponding rules in the parser""" - # parse the ruledef(s) - source = GrammarSource(GRAMMAR_GRAMMAR, ruledef) - builder = ebnfparse.EBNFBuilder(GRAMMAR_GRAMMAR, dest_parser=self) - GRAMMAR_GRAMMAR.root_rules['grammar'].match(source, builder) - # remove proxy objects if any - builder.resolve_rules() - # update keywords - self.keywords.extend(builder.keywords) - # update old references in case an existing rule was modified - self.update_rules_references() - # recompute first sets - self.build_first_sets() +# XXX kill? +# GrammarProxy +# resolve_rules def make_pyparser(version): From cfbolz at codespeak.net Fri Jan 4 00:21:34 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Jan 2008 00:21:34 +0100 (CET) Subject: [pypy-svn] r50304 - pypy/branch/parser-playground/pypy/module/recparser Message-ID: <20080103232134.C8B5A16847D@codespeak.net> Author: cfbolz Date: Fri Jan 4 00:21:34 2008 New Revision: 50304 Removed: pypy/branch/parser-playground/pypy/module/recparser/README Log: kill completely outdated readme file From cfbolz at codespeak.net Fri Jan 4 01:27:13 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Jan 2008 01:27:13 +0100 (CET) Subject: [pypy-svn] r50305 - pypy/branch/parser-playground/pypy/module/symbol Message-ID: <20080104002713.D271B168446@codespeak.net> Author: cfbolz Date: Fri Jan 4 01:27:12 2008 New Revision: 50305 Modified: pypy/branch/parser-playground/pypy/module/symbol/__init__.py Log: be less insane here. should go to dist too, I think Modified: pypy/branch/parser-playground/pypy/module/symbol/__init__.py ============================================================================== --- pypy/branch/parser-playground/pypy/module/symbol/__init__.py (original) +++ pypy/branch/parser-playground/pypy/module/symbol/__init__.py Fri Jan 4 01:27:12 2008 @@ -14,30 +14,18 @@ class Module(MixedModule): """Non-terminal symbols of Python grammar.""" appleveldefs = {} - interpleveldefs = {} # see below + interpleveldefs = {} - def __init__(self, space, w_name): - MixedModule.__init__(self, space, w_name) - _init_symbols(space.config.objspace.pyversion) - - -# Export the values from our custom symbol module. -# Skip negative values (the corresponding symbols are not visible in -# pure Python). -sym_name = {} - -def _init_symbols(grammar_version): - global sym_name - - sym_name = {} - from pypy.interpreter.pyparser.pythonparse import make_pyparser - parser = make_pyparser(grammar_version) - - for name, val in parser.symbols.items(): - if val >= 0: - Module.interpleveldefs[name] = 'space.wrap(%d)' % val - sym_name[val] = name - Module.interpleveldefs['sym_name'] = 'space.wrap(%r)' % (sym_name,) - -# This is very evil -_init_symbols('2.4') + def setup_after_space_initialization(self): + from pypy.interpreter.pyparser.pythonparse import make_pyparser + space = self.space + grammar_version = space.config.objspace.pyversion + parser = make_pyparser(grammar_version) + sym_name = {} + for name, val in parser.symbols.items(): + # Skip negative values (the corresponding symbols are not visible in + # pure Python). + if val >= 0: + space.setattr(self, space.wrap(name), space.wrap(val)) + sym_name[val] = name + space.setattr(self, space.wrap('sym_name'), space.wrap(sym_name)) From arigo at codespeak.net Fri Jan 4 12:05:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jan 2008 12:05:38 +0100 (CET) Subject: [pypy-svn] r50307 - in pypy/branch/asmgcroot/pypy: config rpython/memory/gctransform translator/c translator/c/src Message-ID: <20080104110538.49F2F168447@codespeak.net> Author: arigo Date: Fri Jan 4 12:05:36 2008 New Revision: 50307 Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py pypy/branch/asmgcroot/pypy/translator/c/src/mem.h pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Some support for --asmgcroot in --llvm-via-c. This still needs a bit of hand-tweaking of the C file generated by llvm. More precisely, the function pypy_asm_gcroot() must be removed and replaced by the macro defined in translator/c/src/mem.h. Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py ============================================================================== --- pypy/branch/asmgcroot/pypy/config/translationoption.py (original) +++ pypy/branch/asmgcroot/pypy/config/translationoption.py Fri Jan 4 12:05:36 2008 @@ -68,8 +68,7 @@ ("translation.backend", "llvm")]), BoolOption("asmgcroot", "Use the 'trackgcroot' asm hack to find roots", default=False, cmdline="--asmgcroot", - requires=[("translation.gctransformer", "framework"), - ("translation.backend", "c")]), + requires=[("translation.gctransformer", "framework")]), BoolOption("thread", "enable use of threading primitives", default=False, cmdline="--thread", requires=[("translation.gc", "boehm")]), Modified: pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py Fri Jan 4 12:05:36 2008 @@ -2,7 +2,9 @@ from pypy.rpython.memory.gctransform.framework import BaseRootWalker from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.rbuiltin import gen_cast from pypy.rpython.annlowlevel import llhelper +from pypy.objspace.flow.model import Constant from pypy.rlib.debug import ll_assert @@ -26,7 +28,15 @@ return # mark the values as gc roots for var in livevars: - hop.genop("asm_gcroot", [var]) + if 0: + # uses direct support in genc - more compact code, + # but it's probably not changing anything + hop.genop("asm_gcroot", [var]) + else: + v_adr = gen_cast(hop.llops, llmemory.Address, var) + v_newaddr = hop.genop("direct_call", [c_asm_gcroot, v_adr], + resulttype=llmemory.Address) + hop.genop("gc_reload_possibly_moved", [v_newaddr, var]) def build_root_walker(self): return AsmStackRootWalker(self) @@ -176,8 +186,8 @@ # track where the caller_frame saved the registers from its own # caller # - if framesize == 0: # a marker that means "I'm the frame - return False # of the entry point, stop walking" + if shape.signed[1] == -1: # a marker that means "I'm the frame + return False # of the entry point, stop walking" reg = 0 while reg < CALLEE_SAVED_REGS: location = shape.signed[1+reg] @@ -284,3 +294,10 @@ lltype.Void, sandboxsafe=True, _nowrapper=True) + +pypy_asm_gcroot = rffi.llexternal('pypy_asm_gcroot', + [llmemory.Address], + llmemory.Address, + sandboxsafe=True, + _nowrapper=True) +c_asm_gcroot = Constant(pypy_asm_gcroot, lltype.typeOf(pypy_asm_gcroot)) Modified: pypy/branch/asmgcroot/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/src/mem.h (original) +++ pypy/branch/asmgcroot/pypy/translator/c/src/mem.h Fri Jan 4 12:05:36 2008 @@ -13,6 +13,10 @@ extern char* __gcmap_frame_address(void); #define PYPY_GCROOT(p) asm ("/* GCROOT %0 */" : "=g" (p) : "0" (p) : "memory") +#define pypy_asm_gcroot(p) ({void*_r; \ + asm ("/* GCROOT %0 */" : "=g" (_r) : "0" (p) : "memory"); \ + _r; }) + #define OP_LLVM_GCMAPSTART(r) r = &__gcmapstart #define OP_LLVM_GCMAPEND(r) r = &__gcmapend #define OP_LLVM_FRAMEADDRESS(r) asm ("pypygetframeaddress %0" : "=r" (r)) Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Fri Jan 4 12:05:36 2008 @@ -67,7 +67,7 @@ lst = ['__gcmap_shape'] for n in state: if n < 0: - n = 'minus%d' % (-n,) + n = 'm%d' % (-n,) lst.append(str(n)) shapes[state] = '_'.join(lst) print >> output, '\t.long\t%s' % (label,) @@ -116,21 +116,31 @@ for label, state in table: print >> sys.stderr, label, '\t', state if tracker.is_main: - assert tracker.uses_frame_pointer - table = self.fixup_entrypoint_table(table) + fp = tracker.uses_frame_pointer + table = self.fixup_entrypoint_table(table, fp) self.gcmaptable.extend(table) newfile.writelines(tracker.lines) - def fixup_entrypoint_table(self, table): + def fixup_entrypoint_table(self, table, uses_frame_pointer): self.seen_main = True - # the main() function contains strange code that aligns the stack - # pointer to a multiple of 16, which messes up our framesize - # computation. So just for this function, and as an end marker, - # we use a frame size of 0. + # as an end marker, set the CALLEE_SAVE_REGISTERS locations to -1. + # this info is not useful because we don't go to main()'s caller. newtable = [] + MARKERS = (-1, -1, -1, -1) for label, shape in table: - newtable.append((label, (0,) + shape[1:])) - return newtable + newtable.append((label, shape[:1] + MARKERS + shape[5:])) + table = newtable + + if uses_frame_pointer: + # the main() function may contain strange code that aligns the + # stack pointer to a multiple of 16, which messes up our framesize + # computation. So just for this function, we use a frame size + # of 0 to ask asmgcroot to read %ebp to find the frame pointer. + newtable = [] + for label, shape in table: + newtable.append((label, (0,) + shape[1:])) + table = newtable + return table class FunctionGcRootTracker(object): @@ -452,10 +462,14 @@ target = match.group(2) if target == '%esp': # only for andl $-16, %esp used to align the stack in main(). - # gcc should not use %esp-relative addressing in such a function - # so we can just ignore it + # If gcc compiled main() with a frame pointer, then it should use + # %ebp-relative addressing and not %esp-relative addressing + # and asmgcroot will read %ebp to find the frame. If main() + # is compiled without a frame pointer, the total frame size that + # we compute ends up being bogus but that's ok because gcc has + # to use %esp-relative addressing only and we don't need to walk + # to caller frames because it's main(). assert self.is_main - self.uses_frame_pointer = True return [] else: return self.binary_insn(line) From arigo at codespeak.net Fri Jan 4 14:34:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jan 2008 14:34:13 +0100 (CET) Subject: [pypy-svn] r50309 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20080104133413.8D84E16844B@codespeak.net> Author: arigo Date: Fri Jan 4 14:34:11 2008 New Revision: 50309 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/std/objspace.py Log: Move the shortcut for getindex_w() to a place where it can be more efficient. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Jan 4 14:34:11 2008 @@ -836,10 +836,6 @@ If w_exception is None, silently clamp in case of overflow; else raise w_exception. """ - # shortcut for int objects - if self.is_w(self.type(w_obj), self.w_int): - return self.int_w(w_obj) - try: w_index = self.index(w_obj) except OperationError, err: Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Jan 4 14:34:11 2008 @@ -621,6 +621,14 @@ else: self.setitem(w_obj, w_key, w_value) + def getindex_w(self, w_obj, w_exception, objdescr=None): + # performance shortcut for W_IntObject + # XXX we should also have one for W_SmallIntObject, I guess + if type(w_obj) is W_IntObject: + return w_obj.intval + else: + return ObjSpace.getindex_w(self, w_obj, w_exception, objdescr) + def call_method(self, w_obj, methname, *arg_w): if self.config.objspace.opcodes.CALL_METHOD: from pypy.objspace.std.callmethod import call_method_opt From arigo at codespeak.net Fri Jan 4 16:27:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jan 2008 16:27:44 +0100 (CET) Subject: [pypy-svn] r50314 - pypy/dist/pypy/objspace/std Message-ID: <20080104152744.583F6168446@codespeak.net> Author: arigo Date: Fri Jan 4 16:27:41 2008 New Revision: 50314 Modified: pypy/dist/pypy/objspace/std/listmultiobject.py pypy/dist/pypy/objspace/std/listobject.py Log: Kill dead code. Modified: pypy/dist/pypy/objspace/std/listmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/listmultiobject.py Fri Jan 4 16:27:41 2008 @@ -1003,11 +1003,6 @@ i += 1 return space.w_True -def _min(a, b): - if a < b: - return a - return b - def lessthan_impls(space, impl1, impl2): # needs to be safe against eq_w() mutating the w_lists behind our back # Search for the first index where items are different Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jan 4 16:27:41 2008 @@ -131,11 +131,6 @@ i += 1 return space.w_True -def _min(a, b): - if a < b: - return a - return b - def lessthan_unwrappeditems(space, items1_w, items2_w): # needs to be safe against eq_w() mutating the w_lists behind our back # Search for the first index where items are different From arigo at codespeak.net Fri Jan 4 17:29:29 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jan 2008 17:29:29 +0100 (CET) Subject: [pypy-svn] r50315 - pypy/dist/pypy/module/__builtin__ Message-ID: <20080104162929.7B81F168449@codespeak.net> Author: arigo Date: Fri Jan 4 17:29:28 2008 New Revision: 50315 Modified: pypy/dist/pypy/module/__builtin__/__init__.py pypy/dist/pypy/module/__builtin__/operation.py Log: Kill dead code. Modified: pypy/dist/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/__init__.py (original) +++ pypy/dist/pypy/module/__builtin__/__init__.py Fri Jan 4 17:29:28 2008 @@ -104,7 +104,6 @@ 'hasattr' : 'operation.hasattr', 'iter' : 'operation.iter', 'id' : 'operation.id', - '_seqiter' : 'operation._seqiter', 'intern' : 'operation.intern', 'callable' : 'operation.callable', Modified: pypy/dist/pypy/module/__builtin__/operation.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/operation.py (original) +++ pypy/dist/pypy/module/__builtin__/operation.py Fri Jan 4 17:29:28 2008 @@ -196,9 +196,6 @@ else: return iter_sentinel(space, w_collection_or_callable, w_sentinel) -def _seqiter(space, w_obj): - return space.newseqiter(w_obj) - def ord(space, w_val): """Return the integer ordinal of a character.""" return space.ord(w_val) From fijal at codespeak.net Fri Jan 4 17:40:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Jan 2008 17:40:20 +0100 (CET) Subject: [pypy-svn] r50316 - pypy/dist/pypy/module/zipimport/test Message-ID: <20080104164020.31508168450@codespeak.net> Author: fijal Date: Fri Jan 4 17:40:17 2008 New Revision: 50316 Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: Fix tests. Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Fri Jan 4 17:40:17 2008 @@ -156,7 +156,7 @@ m0 ^= 0x04 test_pyc = chr(m0) + self.test_pyc[1:] self.writefile(self, "uu.pyc", test_pyc) - raises(zipimport.ZipImportError, + raises(ImportError "__import__('uu', globals(), locals(), [])") assert 'uu' not in sys.modules From arigo at codespeak.net Fri Jan 4 17:51:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jan 2008 17:51:37 +0100 (CET) Subject: [pypy-svn] r50318 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080104165137.670F8168440@codespeak.net> Author: arigo Date: Fri Jan 4 17:51:37 2008 New Revision: 50318 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: Tests and fix for a bug found by test_ll_thread.py. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Fri Jan 4 17:51:37 2008 @@ -31,12 +31,23 @@ def lltype(self): return self.TP -def isfunctype(TP): +def _isfunctype(TP): """ Evil hack to get rid of flow objspace inability to accept .TO when TP is not a pointer """ return isinstance(TP, lltype.Ptr) and isinstance(TP.TO, lltype.FuncType) -isfunctype._annspecialcase_ = 'specialize:memo' +_isfunctype._annspecialcase_ = 'specialize:memo' + +def _isllptr(p): + """ Second evil hack to detect if 'p' is a low-level pointer or not """ + return isinstance(p, lltype._ptr) +class _IsLLPtrEntry(ExtRegistryEntry): + _about_ = _isllptr + def compute_result_annotation(self, s_p): + result = isinstance(s_p, annmodel.SomePtr) + return self.bookkeeper.immutablevalue(result) + def specialize_call(self, hop): + return hop.inputconst(lltype.Bool, hop.s_result.const) def llexternal(name, args, result, _callable=None, compilation_info=ExternalCompilationInfo(), @@ -104,7 +115,7 @@ # XXX leaks if a str2charp() fails with MemoryError # and was not the first in this function freeme = arg - elif isfunctype(TARGET): + elif _isfunctype(TARGET) and not _isllptr(arg): # XXX pass additional arguments if invoke_around_handlers: arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg, Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Fri Jan 4 17:51:37 2008 @@ -389,6 +389,18 @@ fn = self.compile(f, [int]) assert fn(13) == -1 + def test_callback_already_llptr(self): + eating_callback = self.eating_callback() + def g(i): + return i + 3 + G = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)) + + def f(): + return eating_callback(3, llhelper(G, g)) + + fn = self.compile(f, []) + assert fn() == 6 + class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) From arigo at codespeak.net Fri Jan 4 19:01:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 4 Jan 2008 19:01:28 +0100 (CET) Subject: [pypy-svn] r50330 - pypy/dist/pypy/objspace/std Message-ID: <20080104180128.23E9A168444@codespeak.net> Author: arigo Date: Fri Jan 4 19:01:27 2008 New Revision: 50330 Modified: pypy/dist/pypy/objspace/std/iterobject.py pypy/dist/pypy/objspace/std/itertype.py pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/objspace/std/tupleobject.py Log: A W_FastSeqIterObject that is a lot more efficient than the W_SeqIterObject for lists and tuples. Modified: pypy/dist/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/iterobject.py (original) +++ pypy/dist/pypy/objspace/std/iterobject.py Fri Jan 4 19:01:27 2008 @@ -7,13 +7,26 @@ from pypy.objspace.std.objspace import * -class W_SeqIterObject(W_Object): +class W_AbstractSeqIterObject(W_Object): from pypy.objspace.std.itertype import iter_typedef as typedef def __init__(w_self, w_seq, index=0): + if index < 0: + index = 0 w_self.w_seq = w_seq w_self.index = index +class W_SeqIterObject(W_AbstractSeqIterObject): + """Sequence iterator implementation for general sequences.""" + +class W_FastSeqIterObject(W_AbstractSeqIterObject): + """Sequence iterator specialized for lists or tuples, accessing + directly their RPython-level list of wrapped objects. + """ + def __init__(w_self, w_seq, wrappeditems): + W_AbstractSeqIterObject.__init__(w_self, w_seq) + w_self.wrappeditems = wrappeditems + class W_ReverseSeqIterObject(W_Object): from pypy.objspace.std.itertype import reverse_iter_typedef as typedef @@ -24,6 +37,7 @@ registerimplementation(W_SeqIterObject) +registerimplementation(W_FastSeqIterObject) registerimplementation(W_ReverseSeqIterObject) def iter__SeqIter(space, w_seqiter): @@ -52,6 +66,33 @@ w_len = space.wrap(0) return w_len + +def iter__FastSeqIter(space, w_seqiter): + return w_seqiter + +def next__FastSeqIter(space, w_seqiter): + if w_seqiter.wrappeditems is None: + raise OperationError(space.w_StopIteration, space.w_None) + index = w_seqiter.index + try: + w_item = w_seqiter.wrappeditems[index] + except IndexError: + w_seqiter.wrappeditems = None + w_seqiter.w_seq = None + raise OperationError(space.w_StopIteration, space.w_None) + w_seqiter.index = index + 1 + return w_item + +def len__FastSeqIter(space, w_seqiter): + if w_seqiter.wrappeditems is None: + return space.wrap(0) + totallength = len(w_seqiter.wrappeditems) + remaining = totallength - w_seqiter.index + if remaining < 0: + remaining = 0 + return space.wrap(remaining) + + def iter__ReverseSeqIter(space, w_seqiter): return w_seqiter Modified: pypy/dist/pypy/objspace/std/itertype.py ============================================================================== --- pypy/dist/pypy/objspace/std/itertype.py (original) +++ pypy/dist/pypy/objspace/std/itertype.py Fri Jan 4 19:01:27 2008 @@ -7,8 +7,8 @@ XXX to do: remove this __reduce__ method and do a registration with copy_reg, instead. """ - from pypy.objspace.std.iterobject import W_SeqIterObject - assert isinstance(w_self, W_SeqIterObject) + from pypy.objspace.std.iterobject import W_AbstractSeqIterObject + assert isinstance(w_self, W_AbstractSeqIterObject) from pypy.interpreter.mixedmodule import MixedModule w_mod = space.getbuiltinmodule('_pickle_support') mod = space.interp_w(MixedModule, w_mod) @@ -44,9 +44,11 @@ __reduce__ = gateway.interp2app(descr_seqiter__reduce__, unwrap_spec=[gateway.W_Root, gateway.ObjSpace]), ) +iter_typedef.acceptable_as_base_class = False reverse_iter_typedef = StdTypeDef("reversesequenceiterator", __reduce__ = gateway.interp2app(descr_reverseseqiter__reduce__, unwrap_spec=[gateway.W_Root, gateway.ObjSpace]), ) +reverse_iter_typedef.acceptable_as_base_class = False Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jan 4 19:01:27 2008 @@ -33,10 +33,26 @@ w_iterable, = __args__.parse('list', (['sequence'], None, None), # signature [EMPTY_LIST]) # default argument - if w_iterable is EMPTY_LIST: - w_list.wrappeditems = [] - else: - w_list.wrappeditems = space.unpackiterable(w_iterable) + # + # this is the old version of the loop at the end of this function: + # + # w_list.wrappeditems = space.unpackiterable(w_iterable) + # + # This is commented out to avoid assigning a new RPython list to + # 'wrappeditems', which defeats the W_FastSeqIterObject optimization. + # + items_w = w_list.wrappeditems + del items_w[:] + if w_iterable is not EMPTY_LIST: + w_iterator = space.iter(w_iterable) + while True: + try: + w_item = space.next(w_iterator) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break # done + items_w.append(w_item) def len__List(space, w_list): result = len(w_list.wrappeditems) @@ -76,7 +92,7 @@ def iter__List(space, w_list): from pypy.objspace.std import iterobject - return iterobject.W_SeqIterObject(w_list) + return iterobject.W_FastSeqIterObject(w_list, w_list.wrappeditems) def add__List_List(space, w_list1, w_list2): return W_ListObject(w_list1.wrappeditems + w_list2.wrappeditems) Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Fri Jan 4 19:01:27 2008 @@ -103,6 +103,7 @@ longobject.W_LongObject: [], noneobject.W_NoneObject: [], iterobject.W_SeqIterObject: [], + iterobject.W_FastSeqIterObject: [], iterobject.W_ReverseSeqIterObject: [], unicodeobject.W_UnicodeObject: [], dictproxyobject.W_DictProxyObject: [], Modified: pypy/dist/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/tupleobject.py Fri Jan 4 19:01:27 2008 @@ -60,7 +60,7 @@ def iter__Tuple(space, w_tuple): from pypy.objspace.std import iterobject - return iterobject.W_SeqIterObject(w_tuple) + return iterobject.W_FastSeqIterObject(w_tuple, w_tuple.wrappeditems) def add__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems From fijal at codespeak.net Fri Jan 4 21:19:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Jan 2008 21:19:09 +0100 (CET) Subject: [pypy-svn] r50338 - pypy/dist/pypy/module/zipimport/test Message-ID: <20080104201909.B92CE16844E@codespeak.net> Author: fijal Date: Fri Jan 4 21:19:08 2008 New Revision: 50338 Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: (xoraxax) fix syntax error Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Fri Jan 4 21:19:08 2008 @@ -156,8 +156,7 @@ m0 ^= 0x04 test_pyc = chr(m0) + self.test_pyc[1:] self.writefile(self, "uu.pyc", test_pyc) - raises(ImportError - "__import__('uu', globals(), locals(), [])") + raises(ImportError, "__import__('uu', globals(), locals(), [])") assert 'uu' not in sys.modules def test_force_py(self): From fijal at codespeak.net Fri Jan 4 21:44:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Jan 2008 21:44:59 +0100 (CET) Subject: [pypy-svn] r50339 - pypy/branch/applevel-ctypes/pypy/module/_ffi Message-ID: <20080104204459.4674A168456@codespeak.net> Author: fijal Date: Fri Jan 4 21:44:57 2008 New Revision: 50339 Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Log: One needed fix. Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Fri Jan 4 21:44:57 2008 @@ -144,7 +144,8 @@ return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) def descr_new_structure_instance(space, w_type, w_shape, w_adr, w_fieldinits): - return W_StructureInstance(space, w_shape, w_adr, w_fieldinits) + fieldinits_w = space.unpackiterable(w_fieldinits) + return W_StructureInstance(space, w_shape, w_adr, fieldinits_w) W_StructureInstance.typedef = TypeDef( 'StructureInstance', From fijal at codespeak.net Fri Jan 4 23:19:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Jan 2008 23:19:41 +0100 (CET) Subject: [pypy-svn] r50340 - pypy/branch/applevel-ctypes/pypy/module/_ffi Message-ID: <20080104221941.97C3D168427@codespeak.net> Author: fijal Date: Fri Jan 4 23:19:39 2008 New Revision: 50340 Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Log: Kill the __new__ of structure instance. Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Fri Jan 4 23:19:39 2008 @@ -76,8 +76,8 @@ raise OperationError( space.w_TypeError, space.wrap("Keyword arguments not allowed when passing address argument")) - return W_StructureInstance(space, self, args_w[0], None) - return W_StructureInstance(space, self, None, kwargs_w) + return space.wrap(W_StructureInstance(space, self, args_w[0], None)) + return space.wrap(W_StructureInstance(space, self, None, kwargs_w)) def descr_new_structure(space, w_type, w_fields): return W_Structure(space, w_fields) @@ -143,13 +143,8 @@ def getbuffer(space, self): return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) -def descr_new_structure_instance(space, w_type, w_shape, w_adr, w_fieldinits): - fieldinits_w = space.unpackiterable(w_fieldinits) - return W_StructureInstance(space, w_shape, w_adr, fieldinits_w) - W_StructureInstance.typedef = TypeDef( 'StructureInstance', - __new__ = interp2app(descr_new_structure_instance), __getattr__ = interp2app(W_StructureInstance.getattr), __setattr__ = interp2app(W_StructureInstance.setattr), buffer = GetSetProperty(W_StructureInstance.getbuffer), From fijal at codespeak.net Fri Jan 4 23:33:40 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 4 Jan 2008 23:33:40 +0100 (CET) Subject: [pypy-svn] r50341 - pypy/branch/applevel-ctypes/pypy/module/_ffi/test Message-ID: <20080104223340.0434716844E@codespeak.net> Author: fijal Date: Fri Jan 4 23:33:40 2008 New Revision: 50341 Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py Log: Make test fail more obviously Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py Fri Jan 4 23:33:40 2008 @@ -211,6 +211,10 @@ inner = lib.ptr("inner_struct_elem", ['P'], 'c') X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) x = X(next=X(next=None, x3='x'), x1=1, x2=2, x3='x') + print X(x.next).x3 + print X(x.next).x3 + print X(x.next).x3 + print X(x.next).x3 assert X(x.next).x3 == 'x' assert inner(x) == 'x' create_double_struct = lib.ptr("create_double_struct", [], 'P') From cfbolz at codespeak.net Fri Jan 4 23:43:49 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Jan 2008 23:43:49 +0100 (CET) Subject: [pypy-svn] r50342 - pypy/dist/pypy/rlib/parsing/test Message-ID: <20080104224349.6530F16844E@codespeak.net> Author: cfbolz Date: Fri Jan 4 23:43:48 2008 New Revision: 50342 Modified: pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py Log: move closer to what the tokenize module does. I won't try to mirror it completely just yet, since I am not sure our parser needs a complete mirror anyway. Modified: pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pythonlexer.py Fri Jan 4 23:43:48 2008 @@ -1,6 +1,6 @@ import py from pypy.rlib.parsing.regexparse import parse_regex, make_runner -from pypy.rlib.parsing.lexer import Lexer +from pypy.rlib.parsing.lexer import Lexer, Token, SourcePos # attempts at writing a Python-lexer @@ -14,7 +14,7 @@ #____________________________________________________________ # Numbers -Hexnumber = r'0[xX][0-9a-fA-F]*[lL]?' +Hexnumber = r'0[xX][0-9a-fA-F]*[lL]?' #XXX this parses 0xl, but shouldn't Octnumber = r'0[0-7]*[lL]?' Decnumber = r'[1-9][0-9]*[lL]?' Intnumber = group(Hexnumber, Octnumber, Decnumber) @@ -85,7 +85,8 @@ Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=", r"//=?", r"[\+\-\*\/\%\&\|\^\=\<\>]=?", - r"~") + r"~", + Special) OpenBracket = r'[\[\(\{]' CloseBracket = r'[\]\)\}]' @@ -93,7 +94,7 @@ #____________________________________________________________ # all tokens -tokens = ["Number", "String", "Name", "Ignore", "Special", "Indent", +tokens = ["Number", "String", "Name", "Ignore", "Indent", "OpenBracket", "CloseBracket", "Operator"] def make_lexer(): @@ -117,12 +118,20 @@ token.name = "Operator" output_tokens.append(token) elif token.name == "Indent": + token.name = "Newline" if parenthesis_level == 0: s = token.source length = len(s) - pos = 1 + pos = 0 column = 0 - while pos < length: # measure leading whitespace + # the token looks like this: \r?\n[ \f\t]* + if s[0] == '\n': + pos = 1 + start = 1 + else: + pos = 2 + start = 2 + while pos < length: # count the indentation depth of the whitespace c = s[pos] if c == ' ': column = column + 1 @@ -130,16 +139,25 @@ column = (column // tabsize + 1) * tabsize elif c == '\f': column = 0 - else: - break pos = pos + 1 + # split the token in two: one for the newline and one for the + output_tokens.append(Token("Newline", s[:start], token.source_pos)) if column > indentation_levels[-1]: # count indents or dedents indentation_levels.append(column) token.name = "Indent" - while column < indentation_levels[-1]: - indentation_levels.pop() - token.name = "Dedent" - output_tokens.append(token) + else: + dedented = False + while column < indentation_levels[-1]: + dedented = True + indentation_levels.pop() + if dedented: + token.name = "Dedent" + if token.name != "Newline": + token.source = s[start:] + token.source_pos.i += 1 + token.source_pos.lineno += 1 + token.source_pos.columnno = 0 + output_tokens.append(token) else: pass # implicit line-continuations within parenthesis elif token.name == "Ignore": @@ -223,9 +241,9 @@ d e""" tokens = pythonlex(s) - assert [t.name for t in tokens] == ["Name", "Indent", "Name", "Indent", - "Name", "Indent", "Name", "Dedent", - "Name"] + assert [t.name for t in tokens] == ["Name", "Newline", "Name", "Newline", + "Indent", "Name", "Newline", "Indent", + "Name", "Newline", "Dedent", "Name"] def test_linecont(): s = "a + \\\n b" @@ -237,3 +255,21 @@ tokens = pythonlex(s) assert [t.name for t in tokens] == ["Operator", "Name", "Operator", "Name", "Operator"] + +def dont_test_self_full(): + equivalents = { + "nl": "newline", + "comment": "newline", + "op": "operator", + } + import tokenize, token + s = py.magic.autopath().read() + tokens = pythonlex(s) + print [t.name for t in tokens][:20] + tokens2 = list(tokenize.generate_tokens(iter(s.splitlines(True)).next)) + print [token.tok_name[t[0]] for t in tokens2][:20] + for i, (t1, t2) in enumerate(zip(tokens, tokens2)): + n1 = t1.name.lower() + n2 = token.tok_name[t2[0]].lower() + n2 = equivalents.get(n2, n2) + assert n1 == n2 From cfbolz at codespeak.net Fri Jan 4 23:45:01 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 4 Jan 2008 23:45:01 +0100 (CET) Subject: [pypy-svn] r50343 - pypy/dist/pypy/rlib/parsing Message-ID: <20080104224501.83DF516844E@codespeak.net> Author: cfbolz Date: Fri Jan 4 23:45:01 2008 New Revision: 50343 Modified: pypy/dist/pypy/rlib/parsing/lexer.py Log: some refactoring to the lexing code to be a bit more flexible. My Python lexer needs this. Modified: pypy/dist/pypy/rlib/parsing/lexer.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/lexer.py (original) +++ pypy/dist/pypy/rlib/parsing/lexer.py Fri Jan 4 23:45:01 2008 @@ -89,15 +89,14 @@ self.ignore = ignore self.matcher = matcher -class LexingDFARunner(deterministic.DFARunner): +class AbstractLexingDFARunner(deterministic.DFARunner): i = 0 - def __init__(self, matcher, automaton, text, ignore, eof=False): + def __init__(self, matcher, automaton, text, eof=False): self.automaton = automaton self.state = 0 self.text = text self.last_matched_state = 0 self.last_matched_index = -1 - self.ignore = ignore self.eof = eof self.matcher = matcher self.lineno = 0 @@ -112,8 +111,7 @@ if i == len(self.text): if self.eof: self.last_matched_index += 1 - return Token("EOF", "EOF", - SourcePos(i, self.lineno, self.columnno)) + return self.make_token(i, -1, "", eof=True) else: raise StopIteration if i >= len(self.text) + 1: @@ -128,25 +126,22 @@ stop = self.last_matched_index + 1 assert stop >= 0 source = self.text[start: stop] - lineno, columnno = self.adjust_position(source) - if self.automaton.names[self.last_matched_state] in self.ignore: + result = self.make_token(start, self.last_matched_index, source) + self.adjust_position(source) + if self.ignore_token(self.last_matched_state): continue - source_pos = SourcePos(start, lineno, columnno) - return Token(self.automaton.names[self.last_matched_state], - source, source_pos) + return result if self.last_matched_index == i - 1: - token = self.text[start: ] - lineno, columnno = self.adjust_position(token) - if self.automaton.names[self.last_matched_state] in self.ignore: + source = self.text[start: ] + result = self.make_token(start, self.last_matched_index, source) + self.adjust_position(source) + if self.ignore_token(self.last_matched_state): if self.eof: self.last_matched_index += 1 - return Token("EOF", "EOF", - SourcePos(i, self.lineno, self.columnno)) + return self.make_token(i, -1, "", eof=True) else: raise StopIteration - return Token(self.automaton.names[self.last_matched_state], - self.text[start:], - SourcePos(start, lineno, columnno)) + return result source_pos = SourcePos(i - 1, self.lineno, self.columnno) raise deterministic.LexerError(self.text, self.state, source_pos) @@ -158,7 +153,6 @@ self.columnno += len(token) else: self.columnno = token.rfind("\n") - return lineno, columnno # def inner_loop(self, i): # while i < len(self.text): @@ -184,3 +178,17 @@ def __iter__(self): return self +class LexingDFARunner(AbstractLexingDFARunner): + def __init__(self, matcher, automaton, text, ignore, eof=False): + AbstractLexingDFARunner.__init__(self, matcher, automaton, text, eof) + self.ignore = ignore + + def ignore_token(self, state): + return self.automaton.names[self.last_matched_state] in self.ignore + + def make_token(self, index, state, text, eof=False): + source_pos = SourcePos(index, self.lineno, self.columnno) + if eof: + return Token("EOF", "EOF", source_pos) + return Token(self.automaton.names[self.last_matched_state], + text, source_pos) From fijal at codespeak.net Sat Jan 5 11:15:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 11:15:23 +0100 (CET) Subject: [pypy-svn] r50345 - in pypy/branch/applevel-ctypes/pypy/rpython/memory: . gc gctransform gctransform/test test Message-ID: <20080105101523.D1C1E168487@codespeak.net> Author: fijal Date: Sat Jan 5 11:15:22 2008 New Revision: 50345 Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py Log: Merge the gc from dist, as translation is now broken on this branch. Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/base.py Sat Jan 5 11:15:22 2008 @@ -6,6 +6,7 @@ moving_gc = False needs_write_barrier = False needs_zero_gc_pointers = True + prebuilt_gc_objects_are_static_roots = True def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, @@ -160,6 +161,12 @@ # more non-prebuild GC objects; this is fine because the # internal GC ptr in the prebuilt list or dict is found by # gctypelayout and listed in addresses_of_static_ptrs. + + # XXX I'm not sure any more about the warning above. The fields + # of 'self' are found by gctypelayout and added to + # addresses_of_static_ptrs_in_nongc, so in principle they could + # be mutated and still be found by collect(). + self.wr_to_objects_with_id = [] self.object_id_dict = {} self.object_id_dict_ends_at = 0 Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/generation.py Sat Jan 5 11:15:22 2008 @@ -11,7 +11,11 @@ # in the nursery. It is initially set on all prebuilt and old objects, # and gets cleared by the write_barrier() when we write in them a # pointer to a young object. -GCFLAG_NO_YOUNG_PTRS = 2 << GCFLAGSHIFT +GCFLAG_NO_YOUNG_PTRS = 1 << (GCFLAGSHIFT+1) + +# The following flag is set for static roots which are not on the list +# of static roots yet, but will appear with write barrier +GCFLAG_NO_HEAP_PTRS = 1 << (GCFLAGSHIFT+2) DEBUG_PRINT = False @@ -22,7 +26,9 @@ list, chained to each other via their 'forw' header field. """ inline_simple_malloc = True + inline_simple_malloc_varsize = True needs_write_barrier = True + prebuilt_gc_objects_are_static_roots = False def __init__(self, AddressLinkedList, nursery_size=128, @@ -135,7 +141,8 @@ def init_gc_object(self, addr, typeid, flags=GCFLAG_NO_YOUNG_PTRS): SemiSpaceGC.init_gc_object(self, addr, typeid, flags) - def init_gc_object_immortal(self, addr, typeid, flags=GCFLAG_NO_YOUNG_PTRS): + def init_gc_object_immortal(self, addr, typeid, + flags=GCFLAG_NO_YOUNG_PTRS|GCFLAG_NO_HEAP_PTRS): SemiSpaceGC.init_gc_object_immortal(self, addr, typeid, flags) def semispace_collect(self, size_changing=False): @@ -288,12 +295,22 @@ if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) + def append_to_static_roots(self, pointer, arg): + self.get_roots.append_static_root(pointer) + + def move_to_static_roots(self, addr_struct): + objhdr = self.header(addr_struct) + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.trace(addr_struct, self.append_to_static_roots, None) + def remember_young_pointer(self, addr_struct, addr): ll_assert(not self.is_in_nursery(addr_struct), "nursery object with GCFLAG_NO_YOUNG_PTRS") + oldhdr = self.header(addr_struct) if self.is_in_nursery(addr): - oldhdr = self.header(addr_struct) oldhdr.forw = self.old_objects_pointing_to_young self.old_objects_pointing_to_young = addr_struct oldhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS - remember_young_pointer.dont_inline = True + if oldhdr.tid & GCFLAG_NO_HEAP_PTRS: + self.move_to_static_roots(addr_struct) + remember_young_pointer._dont_inline_ = True Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/marksweep.py Sat Jan 5 11:15:22 2008 @@ -102,7 +102,7 @@ #llop.debug_print(lltype.Void, 'malloc typeid', typeid, # '->', llmemory.cast_adr_to_int(result)) return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) - malloc_fixedsize.dont_inline = True + malloc_fixedsize._dont_inline_ = True def malloc_fixedsize_clear(self, typeid, size, can_collect, has_finalizer=False, contains_weakptr=False): @@ -136,7 +136,7 @@ #llop.debug_print(lltype.Void, 'malloc typeid', typeid, # '->', llmemory.cast_adr_to_int(result)) return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) - malloc_fixedsize_clear.dont_inline = True + malloc_fixedsize_clear._dont_inline_ = True def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length, can_collect, has_finalizer=False): @@ -171,7 +171,7 @@ # 'typeid', typeid, # '->', llmemory.cast_adr_to_int(result)) return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) - malloc_varsize.dont_inline = True + malloc_varsize._dont_inline_ = True def malloc_varsize_clear(self, typeid, length, size, itemsize, offset_to_length, can_collect, @@ -208,7 +208,7 @@ # 'typeid', typeid, # '->', llmemory.cast_adr_to_int(result)) return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) - malloc_varsize_clear.dont_inline = True + malloc_varsize_clear._dont_inline_ = True def collect(self): # 1. mark from the roots, and also the objects that objects-with-del @@ -483,8 +483,9 @@ hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) hdr.typeid = typeid << 1 - def init_gc_object_immortal(self, addr, typeid): + def init_gc_object_immortal(self, addr, typeid, flags=0): # prebuilt gc structures always have the mark bit set + # ignore flags hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) hdr.typeid = (typeid << 1) | 1 Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gc/semispace.py Sat Jan 5 11:15:22 2008 @@ -21,6 +21,7 @@ class SemiSpaceGC(MovingGCBase): _alloc_flavor_ = "raw" inline_simple_malloc = True + inline_simple_malloc_varsize = True needs_zero_gc_pointers = False HDR = lltype.Struct('header', ('forw', llmemory.Address), @@ -107,7 +108,7 @@ if not self.try_obtain_free_space(needed): raise memoryError return self.free - obtain_free_space.dont_inline = True + obtain_free_space._dont_inline_ = True def try_obtain_free_space(self, needed): # XXX for bonus points do big objects differently Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/boehm.py Sat Jan 5 11:15:22 2008 @@ -108,7 +108,7 @@ " v = cast_adr_to_ptr(addr, PTR_TYPE)\n" "%s\n")%(static_body,) exec src in d - fptr = self.annotate_helper(d['ll_finalizer'], [llmemory.Address], lltype.Void) + fptr = self.annotate_finalizer(d['ll_finalizer'], [llmemory.Address], lltype.Void) elif destrptr: EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value def ll_finalizer(addr): @@ -116,7 +116,7 @@ v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v) llop.gc_restore_exception(lltype.Void, exc_instance) - fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) + fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void) else: fptr = lltype.nullptr(self.FINALIZER_PTR.TO) Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/framework.py Sat Jan 5 11:15:22 2008 @@ -17,6 +17,7 @@ from pypy.rpython.memory.gctypelayout import convert_weakref_to, WEAKREFPTR from pypy.rpython.memory.gctransform.log import log from pypy.tool.sourcetools import func_with_new_name +from pypy.rpython.lltypesystem.lloperation import llop import sys @@ -87,8 +88,8 @@ mallocvars = {target.inputargs[index]: True} mallocnum += 1 find_in_block(target, mallocvars) - if result: - print "found %s initializing stores in %s" % (len(result), graph.name) + #if result: + # print "found %s initializing stores in %s" % (len(result), graph.name) return result class FrameworkGCTransformer(GCTransformer): @@ -113,16 +114,19 @@ self.get_type_id = self.layoutbuilder.get_type_id # set up dummy a table, to be overwritten with the real one in finish() - type_info_table = lltype.malloc(gctypelayout.GCData.TYPE_INFO_TABLE, 0, - immortal=True) + type_info_table = lltype._ptr( + lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE), + "delayed!type_info_table", solid=True) gcdata = gctypelayout.GCData(type_info_table) # initialize the following two fields with a random non-NULL address, # to make the annotator happy. The fields are patched in finish() - # to point to a real array (not 'type_info_table', another one). - a_random_address = llmemory.cast_ptr_to_adr(type_info_table) + # to point to a real array. + foo = lltype.malloc(lltype.FixedSizeArray(llmemory.Address, 1), + immortal=True, zero=True) + a_random_address = llmemory.cast_ptr_to_adr(foo) gcdata.static_root_start = a_random_address # patched in finish() - gcdata.static_root_nongcstart = a_random_address # patched in finish() + gcdata.static_root_nongcend = a_random_address # patched in finish() gcdata.static_root_end = a_random_address # patched in finish() self.gcdata = gcdata self.malloc_fnptr_cache = {} @@ -143,16 +147,13 @@ bk = self.translator.annotator.bookkeeper # the point of this little dance is to not annotate - # self.gcdata.type_info_table as a constant. + # self.gcdata.static_root_xyz as constants. XXX is it still needed?? data_classdef = bk.getuniqueclassdef(gctypelayout.GCData) data_classdef.generalize_attr( - 'type_info_table', - annmodel.SomePtr(lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE))) - data_classdef.generalize_attr( 'static_root_start', annmodel.SomeAddress()) data_classdef.generalize_attr( - 'static_root_nongcstart', + 'static_root_nongcend', annmodel.SomeAddress()) data_classdef.generalize_attr( 'static_root_end', @@ -256,6 +257,28 @@ else: self.malloc_fast_ptr = None + # in some GCs we can also inline the common case of + # malloc_varsize(typeid, length, (3 constant sizes), True, False) + if getattr(GCClass, 'inline_simple_malloc_varsize', False): + # make a copy of this function so that it gets annotated + # independently and the constants are folded inside + malloc_varsize_clear_fast = func_with_new_name( + GCClass.malloc_varsize_clear.im_func, + "malloc_varsize_clear_fast") + s_False = annmodel.SomeBool(); s_False.const = False + s_True = annmodel.SomeBool(); s_True .const = True + self.malloc_varsize_clear_fast_ptr = getfn( + malloc_varsize_clear_fast, + [s_gc, annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True), + s_True, s_False], s_gcref, + inline = True) + else: + self.malloc_varsize_clear_fast_ptr = None + if GCClass.moving_gc: self.id_ptr = getfn(GCClass.id.im_func, [s_gc, s_gcref], annmodel.SomeInteger(), @@ -349,6 +372,11 @@ gcdata.root_stack_top = top + n*sizeofaddr return top incr_stack = staticmethod(incr_stack) + + def append_static_root(adr): + gcdata.static_root_end.address[0] = adr + gcdata.static_root_end += sizeofaddr + append_static_root = staticmethod(append_static_root) def decr_stack(n): top = gcdata.root_stack_top - n*sizeofaddr @@ -371,16 +399,16 @@ def __init__(self, with_static=True): self.stack_current = gcdata.root_stack_top if with_static: - self.static_current = gcdata.static_root_start + self.static_current = gcdata.static_root_end else: - self.static_current = gcdata.static_root_nongcstart + self.static_current = gcdata.static_root_nongcend def pop(self): - while self.static_current != gcdata.static_root_end: - result = self.static_current - self.static_current += sizeofaddr - if result.address[0].address[0] != llmemory.NULL: - return result.address[0] + while self.static_current != gcdata.static_root_start: + self.static_current -= sizeofaddr + result = self.static_current.address[0] + if result.address[0] != llmemory.NULL: + return result while self.stack_current != gcdata.root_stack_base: self.stack_current -= sizeofaddr if self.stack_current.address[0] != llmemory.NULL: @@ -418,9 +446,10 @@ # replace the type_info_table pointer in gcdata -- at this point, # the database is in principle complete, so it has already seen - # the old (empty) array. We need to force it to consider the new - # array now. It's a bit hackish as the old empty array will also - # be generated in the C source, but that's a rather minor problem. + # the delayed pointer. We need to force it to consider the new + # array now. + + self.gcdata.type_info_table._become(table) # XXX because we call inputconst already in replace_malloc, we can't # modify the instance, we have to modify the 'rtyped instance' @@ -430,24 +459,24 @@ self.gcdata) r_gcdata = self.translator.rtyper.getrepr(s_gcdata) ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value - ll_instance.inst_type_info_table = table - #self.gcdata.type_info_table = table addresses_of_static_ptrs = ( - self.layoutbuilder.addresses_of_static_ptrs + - self.layoutbuilder.addresses_of_static_ptrs_in_nongc) + self.layoutbuilder.addresses_of_static_ptrs_in_nongc + + self.layoutbuilder.addresses_of_static_ptrs) log.info("found %s static roots" % (len(addresses_of_static_ptrs), )) + additional_ptrs = self.layoutbuilder.additional_roots_sources + log.info("additional %d potential static roots" % additional_ptrs) ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address), - len(addresses_of_static_ptrs), + len(addresses_of_static_ptrs) + + additional_ptrs, immortal=True) for i in range(len(addresses_of_static_ptrs)): ll_static_roots_inside[i] = addresses_of_static_ptrs[i] ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr(ll_static_roots_inside) + llmemory.ArrayItemsOffset(lltype.Array(llmemory.Address)) - ll_instance.inst_static_root_nongcstart = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(self.layoutbuilder.addresses_of_static_ptrs) - ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(ll_static_roots_inside) + ll_instance.inst_static_root_nongcend = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(self.layoutbuilder.addresses_of_static_ptrs_in_nongc) + ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(addresses_of_static_ptrs) newgcdependencies = [] - newgcdependencies.append(table) newgcdependencies.append(ll_static_roots_inside) self.write_typeid_list() return newgcdependencies @@ -514,11 +543,11 @@ v_length = op.args[-1] c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - malloc_ptr = self.malloc_varsize_clear_ptr -## if op.opname.startswith('zero'): -## malloc_ptr = self.malloc_varsize_clear_ptr -## else: -## malloc_ptr = self.malloc_varsize_clear_ptr + if (self.malloc_varsize_clear_fast_ptr is not None and + c_can_collect.value and not c_has_finalizer.value): + malloc_ptr = self.malloc_varsize_clear_fast_ptr + else: + malloc_ptr = self.malloc_varsize_clear_ptr args = [self.c_const_gc, c_type_id, v_length, c_size, c_varitemsize, c_ofstolength, c_can_collect, c_has_finalizer] @@ -772,9 +801,9 @@ def ll_finalizer(addr): v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v) - fptr = self.transformer.annotate_helper(ll_finalizer, - [llmemory.Address], - lltype.Void) + fptr = self.transformer.annotate_finalizer(ll_finalizer, + [llmemory.Address], + lltype.Void) else: fptr = lltype.nullptr(gctypelayout.GCData.FINALIZERTYPE.TO) return fptr Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/refcounting.py Sat Jan 5 11:15:22 2008 @@ -115,8 +115,8 @@ self.dynamic_deallocator_funcptrs = {} self.queryptr2dynamic_deallocator_funcptr = {} - def finish_helpers(self): - GCTransformer.finish_helpers(self) + def finish_helpers(self, **kwds): + GCTransformer.finish_helpers(self, **kwds) from pypy.translator.backendopt.malloc import remove_mallocs seen = {} graphs = [] @@ -247,7 +247,7 @@ 'HDRPTR':lltype.Ptr(self.HDR)} exec src in d this = d['ll_deallocator'] - fptr = self.annotate_helper(this, [llmemory.Address], lltype.Void) + fptr = self.annotate_finalizer(this, [llmemory.Address], lltype.Void) self.static_deallocator_funcptrs[TYPE] = fptr for p in find_gc_ptrs_in_type(TYPE): self.static_deallocation_funcptr_for_type(p.TO) Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/test/test_refcounting.py Sat Jan 5 11:15:22 2008 @@ -127,7 +127,7 @@ transformer = cls(t) fptr = getattr(transformer, attr)(TYPE) transformer.transform_graph(graphof(t, f)) - transformer.finish() + transformer.finish(backendopt=False) if conftest.option.view: t.view() if fptr: Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctransform/transform.py Sat Jan 5 11:15:22 2008 @@ -111,6 +111,7 @@ self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping() self.graphs_to_inline = {} self.graph_dependencies = {} + self.ll_finalizers_ptrs = [] if self.MinimalGCTransformer: self.minimalgctransformer = self.MinimalGCTransformer(self) else: @@ -279,24 +280,37 @@ self.need_minimal_transform(graph) if inline: self.graphs_to_inline[graph] = True - return self.mixlevelannotator.graph2delayed(graph) + FUNCTYPE = lltype.FuncType(ll_args, ll_result) + return self.mixlevelannotator.graph2delayed(graph, FUNCTYPE=FUNCTYPE) def inittime_helper(self, ll_helper, ll_args, ll_result, inline=True): ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=inline) return Constant(ptr, lltype.typeOf(ptr)) - def finish_helpers(self): + def annotate_finalizer(self, ll_finalizer, ll_args, ll_result): + fptr = self.annotate_helper(ll_finalizer, ll_args, ll_result) + self.ll_finalizers_ptrs.append(fptr) + return fptr + + def finish_helpers(self, backendopt=True): if self.translator is not None: self.mixlevelannotator.finish_annotate() self.finished_helpers = True if self.translator is not None: self.mixlevelannotator.finish_rtype() + if backendopt: + self.mixlevelannotator.backend_optimize() + # Make sure that the database also sees all finalizers now. + # XXX we need to think more about the interaction with stackless... + # It is likely that the finalizers need special support there + newgcdependencies = self.ll_finalizers_ptrs + return newgcdependencies def finish_tables(self): pass - def finish(self): - self.finish_helpers() + def finish(self, backendopt=True): + self.finish_helpers(backendopt=backendopt) self.finish_tables() def transform_generic_set(self, hop): @@ -415,7 +429,7 @@ except OverflowError: raise MemoryError() return tot_size - _ll_compute_size._inline_ = True + _ll_compute_size._always_inline_ = True def _ll_malloc_varsize_no_length(length, size, itemsize): tot_size = _ll_compute_size(length, size, itemsize) Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gctypelayout.py Sat Jan 5 11:15:22 2008 @@ -159,21 +159,14 @@ ARRAY = TYPE._flds[TYPE._arrayfld] ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld) info.ofstolength = ofs1 + llmemory.ArrayLengthOffset(ARRAY) - if ARRAY.OF != lltype.Void: - info.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0) - else: - info.fixedsize = ofs1 + llmemory.sizeof(lltype.Signed) + info.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0) # XXX we probably don't need isrpystring any more if ARRAY._hints.get('isrpystring'): info.fixedsize = llmemory.sizeof(TYPE, 1) else: ARRAY = TYPE info.ofstolength = llmemory.ArrayLengthOffset(ARRAY) - if ARRAY.OF != lltype.Void: - info.ofstovar = llmemory.itemoffsetof(TYPE, 0) - else: - info.fixedsize = (llmemory.ArrayLengthOffset(ARRAY) + - llmemory.sizeof(lltype.Signed)) + info.ofstovar = llmemory.itemoffsetof(TYPE, 0) assert isinstance(ARRAY, lltype.Array) if ARRAY.OF != lltype.Void: offsets = offsets_to_gc_pointers(ARRAY.OF) @@ -203,6 +196,10 @@ self.addresses_of_static_ptrs = [] # this lists contains pointers in raw Structs and Arrays self.addresses_of_static_ptrs_in_nongc = [] + # if not gc.prebuilt_gc_objects_are_static_roots, then + # additional_roots_sources counts the number of locations + # within prebuilt GC objects that are of type Ptr(Gc) + self.additional_roots_sources = 0 self.finalizer_funcptrs = {} self.offsettable_cache = {} self.next_typeid_cache = {} @@ -272,7 +269,8 @@ return fptr def make_finalizer_funcptr_for_type(self, TYPE): - return None # must be overridden for proper finalizer support + # must be overridden for proper finalizer support + return lltype.nullptr(GCData.ADDRESS_VOID_FUNC) def initialize_gc_query_function(self, gc): return GCData(self.type_info_list).set_query_functions(gc) @@ -296,10 +294,15 @@ # they could be changed later to point to GC heap objects. adr = llmemory.cast_ptr_to_adr(value._as_ptr()) if TYPE._gckind == "gc": - appendto = self.addresses_of_static_ptrs + if not gc.prebuilt_gc_objects_are_static_roots: + for a in gc_pointers_inside(value, adr): + self.additional_roots_sources += 1 + return + else: + appendto = self.addresses_of_static_ptrs else: appendto = self.addresses_of_static_ptrs_in_nongc - for a in mutable_gc_pointers_inside(value, adr): + for a in gc_pointers_inside(value, adr, mutable_only=True): appendto.append(a) # ____________________________________________________________ @@ -338,28 +341,30 @@ return llmemory.offsetof(WEAKREF, "weakptr") return -1 -def mutable_gc_pointers_inside(v, adr): +def gc_pointers_inside(v, adr, mutable_only=False): t = lltype.typeOf(v) if isinstance(t, lltype.Struct): - if t._hints.get('immutable'): + if mutable_only and t._hints.get('immutable'): return for n, t2 in t._flds.iteritems(): if isinstance(t2, lltype.Ptr) and t2.TO._gckind == 'gc': yield adr + llmemory.offsetof(t, n) elif isinstance(t2, (lltype.Array, lltype.Struct)): - for a in mutable_gc_pointers_inside(getattr(v, n), - adr + llmemory.offsetof(t, n)): + for a in gc_pointers_inside(getattr(v, n), + adr + llmemory.offsetof(t, n), + mutable_only): yield a elif isinstance(t, lltype.Array): - if t._hints.get('immutable'): + if mutable_only and t._hints.get('immutable'): return if isinstance(t.OF, lltype.Ptr) and t.OF.TO._gckind == 'gc': for i in range(len(v.items)): yield adr + llmemory.itemoffsetof(t, i) elif isinstance(t.OF, lltype.Struct): for i in range(len(v.items)): - for a in mutable_gc_pointers_inside(v.items[i], - adr + llmemory.itemoffsetof(t, i)): + for a in gc_pointers_inside(v.items[i], + adr + llmemory.itemoffsetof(t, i), + mutable_only): yield a def zero_gc_pointers(p): Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/gcwrapper.py Sat Jan 5 11:15:22 2008 @@ -11,10 +11,13 @@ def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}): self.AddressLinkedList = get_address_linked_list(10) self.gc = gc_class(self.AddressLinkedList, **GC_PARAMS) - self.gc.get_roots = self.get_roots_from_llinterp + def my_get_roots(with_static=True): + return self.get_roots_from_llinterp(with_static) + self.gc.get_roots = my_get_roots self.llinterp = llinterp self.prepare_graphs(flowgraphs) self.gc.setup() + my_get_roots.append_static_root = self.constantroots.append def prepare_graphs(self, flowgraphs): layoutbuilder = DirectRunLayoutBuilder(self.llinterp) @@ -26,7 +29,7 @@ TYPE = lltype.typeOf(obj) layoutbuilder.consider_constant(TYPE, obj, self.gc) - self.constantroots = layoutbuilder.addresses_of_static_ptrs + self.constantroots = list(layoutbuilder.addresses_of_static_ptrs) self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc def get_roots_from_llinterp(self, with_static=True): Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/support.py Sat Jan 5 11:15:22 2008 @@ -47,14 +47,14 @@ new.length = 0 self.chunk = new return new - enlarge.dont_inline = True + enlarge._dont_inline_ = True def shrink(self): old = self.chunk self.chunk = old.previous unused_chunks.put(old) return self.chunk - shrink.dont_inline = True + shrink._dont_inline_ = True def append(self, addr): if addr == llmemory.NULL: Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_gctypelayout.py Sat Jan 5 11:15:22 2008 @@ -1,4 +1,4 @@ -from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder +from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder, GCData from pypy.rpython.memory.gctypelayout import offsets_to_gc_pointers from pypy.rpython.lltypesystem import lltype @@ -36,6 +36,7 @@ for T1, T2 in [(GC_A, GC_S), (GC_A2, GC_S2), (GC_S3, GC_S2)]: tid1 = layoutbuilder.get_type_id(T1) tid2 = layoutbuilder.get_type_id(T2) - lst1 = layoutbuilder.q_varsize_offsets_to_gcpointers_in_var_part(tid1) - lst2 = layoutbuilder.q_offsets_to_gc_pointers(tid2) + gcdata = GCData(layoutbuilder.type_info_list) + lst1 = gcdata.q_varsize_offsets_to_gcpointers_in_var_part(tid1) + lst2 = gcdata.q_offsets_to_gc_pointers(tid2) assert len(lst1) == len(lst2) Modified: pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/applevel-ctypes/pypy/rpython/memory/test/test_transformed_gc.py Sat Jan 5 11:15:22 2008 @@ -37,7 +37,8 @@ gcpolicy = None stacklessgc = False - def runner(self, f, nbargs=0, statistics=False, **extraconfigopts): + def runner(self, f, nbargs=0, statistics=False, transformer=False, + **extraconfigopts): if nbargs == 2: def entrypoint(args): x = args[0] @@ -84,6 +85,8 @@ def statistics(index): return llinterp.eval_graph(statisticsgraph, [ll_gc, index]) return run, statistics + elif transformer: + return run, db.gctransformer else: return run @@ -862,6 +865,42 @@ run = self.runner(f, nbargs=0) run([]) + def test_immutable_to_old_promotion(self): + T_CHILD = lltype.Ptr(lltype.GcStruct('Child', ('field', lltype.Signed))) + T_PARENT = lltype.Ptr(lltype.GcStruct('Parent', ('sub', T_CHILD))) + child = lltype.malloc(T_CHILD.TO) + child2 = lltype.malloc(T_CHILD.TO) + parent = lltype.malloc(T_PARENT.TO) + parent2 = lltype.malloc(T_PARENT.TO) + parent.sub = child + child.field = 3 + parent2.sub = child2 + child2.field = 8 + + T_ALL = lltype.Ptr(lltype.GcArray(T_PARENT)) + all = lltype.malloc(T_ALL.TO, 2) + all[0] = parent + all[1] = parent2 + + def f(x, y): + res = all[x] + #all[x] = lltype.nullptr(T_PARENT.TO) + return res.sub.field + + run, transformer = self.runner(f, nbargs=2, transformer=True) + run([1, 4]) + assert len(transformer.layoutbuilder.addresses_of_static_ptrs) == 0 + assert transformer.layoutbuilder.additional_roots_sources >= 4 + # NB. Remember that additional_roots_sources does not count + # the number of prebuilt GC objects, but the number of locations + # within prebuilt GC objects that are of type Ptr(Gc). + # At the moment we get additional_roots_sources == 6: + # * all[0] + # * all[1] + # * parent.sub + # * parent2.sub + # * the GcArray pointer from gc.wr_to_objects_with_id + # * the GcArray pointer from gc.object_id_dict. class TestGenerationalNoFullCollectGC(GCTest): # test that nursery is doing its job and that no full collection From fijal at codespeak.net Sat Jan 5 11:22:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 11:22:09 +0100 (CET) Subject: [pypy-svn] r50346 - pypy/branch/applevel-ctypes/pypy/module/_ffi Message-ID: <20080105102209.5CD24168487@codespeak.net> Author: fijal Date: Sat Jan 5 11:22:09 2008 New Revision: 50346 Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Log: be explicit Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Sat Jan 5 11:22:09 2008 @@ -80,7 +80,7 @@ return space.wrap(W_StructureInstance(space, self, None, kwargs_w)) def descr_new_structure(space, w_type, w_fields): - return W_Structure(space, w_fields) + return space.wrap(W_Structure(space, w_fields)) W_Structure.typedef = TypeDef( 'Structure', From fijal at codespeak.net Sat Jan 5 11:22:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 11:22:29 +0100 (CET) Subject: [pypy-svn] r50347 - pypy/branch/applevel-ctypes/pypy/module/_ffi/test Message-ID: <20080105102229.AE548168487@codespeak.net> Author: fijal Date: Sat Jan 5 11:22:29 2008 New Revision: 50347 Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py Log: Fix the test. The problem is that internal structure is not kept alive. I think we should do that. Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py Sat Jan 5 11:22:29 2008 @@ -210,13 +210,10 @@ lib = _ffi.CDLL(self.lib_name) inner = lib.ptr("inner_struct_elem", ['P'], 'c') X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) - x = X(next=X(next=None, x3='x'), x1=1, x2=2, x3='x') - print X(x.next).x3 - print X(x.next).x3 - print X(x.next).x3 - print X(x.next).x3 - assert X(x.next).x3 == 'x' + y = X(next=None, x3='x') + x = X(next=y, x1=1, x2=2, x3='x') assert inner(x) == 'x' + assert X(x.next).x3 == 'x' create_double_struct = lib.ptr("create_double_struct", [], 'P') x = create_double_struct() assert X(X(x).next).x2 == 3 From fijal at codespeak.net Sat Jan 5 11:24:19 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 11:24:19 +0100 (CET) Subject: [pypy-svn] r50348 - in pypy/branch/applevel-ctypes/pypy/module/_ffi: . test Message-ID: <20080105102419.16B14168487@codespeak.net> Author: fijal Date: Sat Jan 5 11:24:19 2008 New Revision: 50348 Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py Log: Insert an explicit keepalive of objects passed as arguments to structure init. Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/structure.py Sat Jan 5 11:24:19 2008 @@ -114,8 +114,11 @@ self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, shape.size, flavor='raw', zero=True) if fieldinits_w: + self.fieldinits_w = fieldinits_w for field, w_value in fieldinits_w.iteritems(): self.setattr(space, field, w_value) + else: + self.fieldinits_w = None def getindex(self, space, attr): try: Modified: pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes/pypy/module/_ffi/test/test__ffi.py Sat Jan 5 11:24:19 2008 @@ -210,9 +210,7 @@ lib = _ffi.CDLL(self.lib_name) inner = lib.ptr("inner_struct_elem", ['P'], 'c') X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) - y = X(next=None, x3='x') - x = X(next=y, x1=1, x2=2, x3='x') - assert inner(x) == 'x' + x = X(next=X(next=None, x3='x'), x1=1, x2=2, x3='x') assert X(x.next).x3 == 'x' create_double_struct = lib.ptr("create_double_struct", [], 'P') x = create_double_struct() From fijal at codespeak.net Sat Jan 5 11:51:44 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 11:51:44 +0100 (CET) Subject: [pypy-svn] r50349 - in pypy/branch/applevel-ctypes/pypy/translator/c: . src test Message-ID: <20080105105144.D616516845A@codespeak.net> Author: fijal Date: Sat Jan 5 11:51:44 2008 New Revision: 50349 Modified: pypy/branch/applevel-ctypes/pypy/translator/c/database.py pypy/branch/applevel-ctypes/pypy/translator/c/funcgen.py pypy/branch/applevel-ctypes/pypy/translator/c/genc.py pypy/branch/applevel-ctypes/pypy/translator/c/node.py pypy/branch/applevel-ctypes/pypy/translator/c/primitive.py pypy/branch/applevel-ctypes/pypy/translator/c/src/stack.h pypy/branch/applevel-ctypes/pypy/translator/c/support.py pypy/branch/applevel-ctypes/pypy/translator/c/test/test_boehm.py pypy/branch/applevel-ctypes/pypy/translator/c/test/test_newgc.py Log: Merge translator/c from trunk as well. Modified: pypy/branch/applevel-ctypes/pypy/translator/c/database.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/database.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/database.py Sat Jan 5 11:51:44 2008 @@ -7,11 +7,10 @@ from pypy.rpython.lltypesystem.rffi import CConstant from pypy.tool.sourcetools import valid_identifier from pypy.translator.c.primitive import PrimitiveName, PrimitiveType -from pypy.translator.c.primitive import PrimitiveErrorValue from pypy.translator.c.node import StructDefNode, ArrayDefNode from pypy.translator.c.node import FixedSizeArrayDefNode, BareBoneArrayDefNode from pypy.translator.c.node import ContainerNodeFactory, ExtTypeOpaqueDefNode -from pypy.translator.c.support import cdecl, CNameManager, ErrorValue +from pypy.translator.c.support import cdecl, CNameManager from pypy.translator.c.support import log, barebonearray from pypy.translator.c.extfunc import do_the_getting from pypy import conftest @@ -164,21 +163,14 @@ self.containerstats[kind] = self.containerstats.get(kind, 0) + 1 self.containerlist.append(node) if self.completed: - assert not node.globalcontainer - # non-global containers are found very late, e.g. _subarrays - # via addresses introduced by the GC transformer + pass # we would like to fail here, but a few containers + # are found very late, e.g. _subarrays via addresses + # introduced by the GC transformer, or the type_info_table return node def get(self, obj): - if isinstance(obj, ErrorValue): - T = obj.TYPE - if isinstance(T, Primitive): - return PrimitiveErrorValue[T] - elif isinstance(T, Ptr): - return 'NULL' - else: - raise Exception("don't know about %r" % (T,)) - else: + # XXX extra indent is preserve svn blame - kind of important IMHO (rxe) + if 1: if isinstance(obj, CConstant): return obj.c_name # without further checks T = typeOf(obj) @@ -195,11 +187,15 @@ n = len('delayed!') if len(name) == n: raise - if id(obj) in self.delayedfunctionnames: - return self.delayedfunctionnames[id(obj)][0] - funcname = name[n:] - funcname = self.namespace.uniquename('g_' + funcname) - self.delayedfunctionnames[id(obj)] = funcname, obj + if isinstance(lltype.typeOf(obj).TO, lltype.FuncType): + if id(obj) in self.delayedfunctionnames: + return self.delayedfunctionnames[id(obj)][0] + funcname = name[n:] + funcname = self.namespace.uniquename('g_'+funcname) + self.delayedfunctionnames[id(obj)] = funcname, obj + else: + funcname = None # can't use the name of a + # delayed non-function ptr self.delayedfunctionptrs.append(obj) return funcname # /hack hack hack @@ -283,11 +279,14 @@ # list: finish_callbacks = [] if self.gctransformer: - finish_callbacks.append(self.gctransformer.finish_helpers) + finish_callbacks.append(('GC transformer: finished helpers', + self.gctransformer.finish_helpers)) if self.stacklesstransformer: - finish_callbacks.append(self.stacklesstransformer.finish) + finish_callbacks.append(('Stackless transformer: finished', + self.stacklesstransformer.finish)) if self.gctransformer: - finish_callbacks.append(self.gctransformer.finish_tables) + finish_callbacks.append(('GC transformer: finished tables', + self.gctransformer.finish_tables)) def add_dependencies(newdependencies): for value in newdependencies: @@ -331,8 +330,9 @@ continue # progress - follow all dependencies again if finish_callbacks: - finish = finish_callbacks.pop(0) + logmsg, finish = finish_callbacks.pop(0) newdependencies = finish() + log.database(logmsg) if newdependencies: add_dependencies(newdependencies) continue # progress - follow all dependencies again @@ -343,6 +343,7 @@ self.completed = True if show_progress: dump() + log.database("Completed") def globalcontainers(self): for node in self.containerlist: Modified: pypy/branch/applevel-ctypes/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/funcgen.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/funcgen.py Sat Jan 5 11:51:44 2008 @@ -1,6 +1,6 @@ from __future__ import generators from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring -from pypy.translator.c.support import cdecl, ErrorValue +from pypy.translator.c.support import cdecl from pypy.translator.c.support import llvalue_from_constant, gen_assignments from pypy.translator.c.support import c_string_constant, barebonearray from pypy.objspace.flow.model import Variable, Constant, Block @@ -37,6 +37,7 @@ oldgraph""".split() def __init__(self, graph, db, exception_policy=None, functionname=None): + graph._seen_by_the_backend = True self.graph = graph self.db = db self.gcpolicy = db.gcpolicy @@ -177,21 +178,6 @@ else: raise TypeError, "expr(%r)" % (v,) - def error_return_value(self): - returnlltype = self.lltypemap(self.graph.getreturnvar()) - return self.db.get(ErrorValue(returnlltype)) - - def return_with_error(self): - if self.exception_policy == "CPython": - assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr - v, exc_cleanup_ops = self.graph.exc_cleanup - vanishing_exc_value = self.expr(v) - yield 'RPyConvertExceptionToCPython(%s);' % vanishing_exc_value - for cleanupop in exc_cleanup_ops: - for line in self.gen_op(cleanupop): - yield line - yield 'return %s; ' % self.error_return_value() - # ____________________________________________________________ def cfunction_declarations(self): @@ -285,7 +271,7 @@ yield 'case %s:' % self.db.get(link.llexitcase) for op in self.gen_link(link): yield '\t' + op - yield 'break;' + # 'break;' not needed, as gen_link ends in a 'goto' # Emit default case yield 'default:' Modified: pypy/branch/applevel-ctypes/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/genc.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/genc.py Sat Jan 5 11:51:44 2008 @@ -14,7 +14,6 @@ from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir from pypy.tool import isolate -from pypy.translator.locality.calltree import CallTree from pypy.translator.c.support import log, c_string_constant from pypy.rpython.typesystem import getfunctionptr from pypy.translator.c import gc @@ -24,18 +23,16 @@ _compiled = False modulename = None - def __init__(self, translator, entrypoint, config, - eci=ExternalCompilationInfo(), gcpolicy=None): + def __init__(self, translator, entrypoint, config, gcpolicy=None): self.translator = translator self.entrypoint = entrypoint self.entrypoint_name = self.entrypoint.func_name self.originalentrypoint = entrypoint - self.gcpolicy = gcpolicy + self.config = config + self.gcpolicy = gcpolicy # for tests only, e.g. rpython/memory/ if gcpolicy is not None and gcpolicy.requires_stackless: config.translation.stackless = True - self.config = config - self.exports = {} - self.eci = eci + self.eci = ExternalCompilationInfo() def build_database(self): translator = self.translator @@ -60,11 +57,7 @@ thread_enabled=self.config.translation.thread, sandbox=self.config.translation.sandbox) self.db = db - - # we need a concrete gcpolicy to do this - self.eci = self.eci.merge(ExternalCompilationInfo( - libraries=db.gcpolicy.gc_libraries())) - + # give the gc a chance to register interest in the start-up functions it # need (we call this for its side-effects of db.get()) list(db.gcpolicy.gc_startup_code()) @@ -72,16 +65,19 @@ # build entrypoint and eventually other things to expose pf = self.getentrypointptr() pfname = db.get(pf) - self.exports[self.entrypoint_name] = pf self.c_entrypoint_name = pfname db.complete() - - self.collect_compilation_info() + + self.collect_compilation_info(db) return db have___thread = None - def collect_compilation_info(self): + def collect_compilation_info(self, db): + # we need a concrete gcpolicy to do this + self.eci = self.eci.merge(ExternalCompilationInfo( + libraries=db.gcpolicy.gc_libraries())) + all = [] for node in self.db.globalcontainers(): eci = getattr(node, 'compilation_info', None) @@ -90,12 +86,12 @@ self.eci = self.eci.merge(*all) def get_gcpolicyclass(self): - if self.gcpolicy is None: - name = self.config.translation.gctransformer - if self.config.translation.stacklessgc: - name = "%s+stacklessgc" % (name,) - return gc.name_to_gcpolicy[name] - return self.gcpolicy + if self.gcpolicy is not None: + return self.gcpolicy # for tests only + name = self.config.translation.gctransformer + if self.config.translation.stacklessgc: + name = "%s+stacklessgc" % (name,) + return gc.name_to_gcpolicy[name] # use generate_source(defines=DEBUG_DEFINES) to force the #definition # of the macros that enable debugging assertions @@ -126,8 +122,7 @@ if not self.standalone: assert not self.config.translation.instrument cfile, extra = gen_source(db, modulename, targetdir, self.eci, - defines = defines, - exports = self.exports) + defines = defines) else: if self.config.translation.instrument: defines['INSTRUMENT'] = 1 @@ -396,11 +391,6 @@ self.funcnodes = funcnodes self.othernodes = othernodes self.path = path - # disabled this for a while, does worsen things -# graph = CallTree(self.funcnodes, self.database) -# graph.simulate() -# graph.optimize() -# self.funcnodes = graph.ordered_funcnodes() def uniquecname(self, name): assert name.endswith('.c') @@ -693,7 +683,7 @@ return filename, sg.getextrafiles() + list(eci.separate_module_files) -def gen_source(database, modulename, targetdir, eci, defines={}, exports={}): +def gen_source(database, modulename, targetdir, eci, defines={}): assert not database.standalone if isinstance(targetdir, str): targetdir = py.path.local(targetdir) @@ -770,7 +760,7 @@ ext_modules = [Extension(name = "%(modulename)s", sources = ["%(modulename)s.c"], extra_compile_args = extra_compile_args, - include_dirs = [PYPY_INCLUDE_DIR] + %(include_dirs)r, + include_dirs = (PYPY_INCLUDE_DIR,) + %(include_dirs)r, library_dirs = %(library_dirs)r, libraries = %(libraries)r)]) ''' Modified: pypy/branch/applevel-ctypes/pypy/translator/c/node.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/node.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/node.py Sat Jan 5 11:51:44 2008 @@ -908,6 +908,7 @@ ptarget = obj._dereference() wrapper = db.gcpolicy.convert_weakref_to(ptarget) container = wrapper._obj + obj._converted_weakref = container # hack for genllvm :-/ return db.getcontainernode(container, _dont_write_c_code=False) Modified: pypy/branch/applevel-ctypes/pypy/translator/c/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/primitive.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/primitive.py Sat Jan 5 11:51:44 2008 @@ -158,20 +158,6 @@ Address: 'void* @', } -PrimitiveErrorValue = { - SignedLongLong: '-1LL', - Signed: '-1', - UnsignedLongLong: '((unsigned long long) -1)', - Unsigned: '((unsigned) -1)', - Float: '-1.0', - SingleFloat: '-1.0f', - Char: '((char) -1)', - UniChar: '((unsigned) -1)', - Bool: '0 /* error */', - Void: '/* error */', - Address: 'NULL', - } - def define_c_primitive(ll_type, c_name): if ll_type in PrimitiveName: return @@ -181,7 +167,6 @@ name_str = '((%s) %%dLL)' % c_name PrimitiveName[ll_type] = lambda value, db: name_str % value PrimitiveType[ll_type] = '%s @'% c_name - PrimitiveErrorValue[ll_type] = '((%s) -1)'% c_name for ll_type, c_name in [(rffi.SIGNEDCHAR, 'signed char'), (rffi.UCHAR, 'unsigned char'), Modified: pypy/branch/applevel-ctypes/pypy/translator/c/src/stack.h ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/src/stack.h (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/src/stack.h Sat Jan 5 11:51:44 2008 @@ -9,7 +9,26 @@ #endif void LL_stack_unwind(void); -int LL_stack_too_big(void); +int LL_stack_too_big_slowpath(void); + +extern volatile char *_LLstacktoobig_stack_base_pointer; +extern long _LLstacktoobig_stack_min; +extern long _LLstacktoobig_stack_max; + +static int LL_stack_too_big(void) +{ + /* The fast path of stack_too_big, called extremely often. + Making it static makes an *inlinable* copy of this small + function's implementation in each compilation unit. */ + char local; + long diff = &local - _LLstacktoobig_stack_base_pointer; + /* common case: we are still in the same thread as last time + we checked, and still in the allowed part of the stack */ + return ((diff < _LLstacktoobig_stack_min || + diff > _LLstacktoobig_stack_max) + /* if not, call the slow path */ + && LL_stack_too_big_slowpath()); +} #ifndef PYPY_NOT_MAIN_FILE #include @@ -33,15 +52,16 @@ return &local - parent; } -int LL_stack_too_big(void) +volatile char *_LLstacktoobig_stack_base_pointer = NULL; +long _LLstacktoobig_stack_min = 0; +long _LLstacktoobig_stack_max = 0; +RPyThreadStaticTLS _LLstacktoobig_stack_base_pointer_key; + +int LL_stack_too_big_slowpath(void) { char local; long diff; char *baseptr; - static volatile char *stack_base_pointer = NULL; - static long stack_min = 0; - static long stack_max = 0; - static RPyThreadStaticTLS stack_base_pointer_key; /* Check that the stack is less than MAX_STACK_SIZE bytes bigger than the value recorded in stack_base_pointer. The base pointer is updated to the current value if it is still NULL @@ -50,41 +70,37 @@ try to minimize its overhead by keeping a local copy in stack_pointer_pointer. */ - diff = &local - stack_base_pointer; - if (stack_min <= diff && diff <= stack_max) { - /* common case: we are still in the same thread as last time - we checked, and still in the allowed part of the stack */ - return 0; - } - - if (stack_min == stack_max /* == 0 */) { + if (_LLstacktoobig_stack_min == _LLstacktoobig_stack_max /* == 0 */) { /* not initialized */ /* XXX We assume that initialization is performed early, when there is still only one thread running. This allows us to ignore race conditions here */ - char *errmsg = RPyThreadStaticTLS_Create(&stack_base_pointer_key); + char *errmsg = RPyThreadStaticTLS_Create( + &_LLstacktoobig_stack_base_pointer_key); if (errmsg) { /* XXX should we exit the process? */ fprintf(stderr, "Internal PyPy error: %s\n", errmsg); return 1; } if (_LL_stack_growing_direction(NULL) > 0) - stack_max = MAX_STACK_SIZE; + _LLstacktoobig_stack_max = MAX_STACK_SIZE; else - stack_min = -MAX_STACK_SIZE; + _LLstacktoobig_stack_min = -MAX_STACK_SIZE; } - baseptr = (char *) RPyThreadStaticTLS_Get(stack_base_pointer_key); + baseptr = (char *) RPyThreadStaticTLS_Get( + _LLstacktoobig_stack_base_pointer_key); if (baseptr != NULL) { diff = &local - baseptr; - if (stack_min <= diff && diff <= stack_max) { + if (_LLstacktoobig_stack_min <= diff && + diff <= _LLstacktoobig_stack_max) { /* within bounds */ - stack_base_pointer = baseptr; + _LLstacktoobig_stack_base_pointer = baseptr; return 0; } - if ((stack_min == 0 && diff < 0) || - (stack_max == 0 && diff > 0)) { + if ((_LLstacktoobig_stack_min == 0 && diff < 0) || + (_LLstacktoobig_stack_max == 0 && diff > 0)) { /* we underflowed the stack, which means that the initial estimation of the stack base must be revised (see below) */ @@ -96,8 +112,8 @@ /* update the stack base pointer to the current value */ baseptr = &local; - RPyThreadStaticTLS_Set(stack_base_pointer_key, baseptr); - stack_base_pointer = baseptr; + RPyThreadStaticTLS_Set(_LLstacktoobig_stack_base_pointer_key, baseptr); + _LLstacktoobig_stack_base_pointer = baseptr; return 0; } Modified: pypy/branch/applevel-ctypes/pypy/translator/c/support.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/support.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/support.py Sat Jan 5 11:51:44 2008 @@ -9,11 +9,6 @@ PyObjPtr = lltype.Ptr(lltype.PyObject) - -class ErrorValue: - def __init__(self, TYPE): - self.TYPE = TYPE - def barebonearray(ARRAY): """Check if ARRAY is a 'simple' array type, i.e. doesn't need a length nor GC headers.""" Modified: pypy/branch/applevel-ctypes/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/test/test_boehm.py Sat Jan 5 11:51:44 2008 @@ -150,7 +150,6 @@ def test_del_raises(self): from pypy.rpython.lltypesystem.lloperation import llop - import os class A(object): def __del__(self): s.dels += 1 Modified: pypy/branch/applevel-ctypes/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/applevel-ctypes/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/applevel-ctypes/pypy/translator/c/test/test_newgc.py Sat Jan 5 11:51:44 2008 @@ -298,7 +298,7 @@ a = A() a.b = g(1) return a - make.dont_inline = True + make._dont_inline_ = True def f(): a = make() llop.gc__collect(lltype.Void) @@ -316,7 +316,7 @@ pass def g(x): # cause a collect llop.gc__collect(lltype.Void) - g.dont_inline = True + g._dont_inline_ = True global_a = A() global_a.b = B() global_a.b.a = A() @@ -330,7 +330,7 @@ g(1) b0 = a.b b0.c = b.c = 42 - make.dont_inline = True + make._dont_inline_ = True def f(): make() llop.gc__collect(lltype.Void) @@ -356,7 +356,7 @@ for i in range(1000): prepare(B(), -1) # probably overwrites collected memory return a.value - g.dont_inline = True + g._dont_inline_ = True def f(): b = B() prepare(b, 123) @@ -420,7 +420,7 @@ a.x = None def make(): a.x = A(42) - make.dont_inline = True + make._dont_inline_ = True def f(): make() llop.gc__collect(lltype.Void) @@ -481,12 +481,12 @@ a = lltype.malloc(A) a.value = -n * 7 return lltype.cast_opaque_ptr(lltype.Ptr(O), a) - gethidden.dont_inline = True + gethidden._dont_inline_ = True def reveal(o): return lltype.cast_opaque_ptr(lltype.Ptr(A), o) def overwrite(a, i): a.value = i - overwrite.dont_inline = True + overwrite._dont_inline_ = True def f(): o = gethidden(10) llop.gc__collect(lltype.Void) From fijal at codespeak.net Sat Jan 5 12:24:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 12:24:18 +0100 (CET) Subject: [pypy-svn] r50350 - pypy/branch/applevel-ctypes2 Message-ID: <20080105112418.636C8168487@codespeak.net> Author: fijal Date: Sat Jan 5 12:24:16 2008 New Revision: 50350 Added: pypy/branch/applevel-ctypes2/ - copied from r50349, pypy/dist/ Log: Branch again from the dist to play with applevel ctypes. From fijal at codespeak.net Sat Jan 5 13:06:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 13:06:34 +0100 (CET) Subject: [pypy-svn] r50351 - pypy/branch/applevel-ctypes2/pypy/lib/ctypes Message-ID: <20080105120634.4F12916847F@codespeak.net> Author: fijal Date: Sat Jan 5 13:06:32 2008 New Revision: 50351 Removed: pypy/branch/applevel-ctypes2/pypy/lib/ctypes/ Log: Remove old ctypes. From fijal at codespeak.net Sat Jan 5 13:07:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 13:07:43 +0100 (CET) Subject: [pypy-svn] r50352 - in pypy/branch/applevel-ctypes2/pypy/lib: _ctypes ctypes Message-ID: <20080105120743.C259216847F@codespeak.net> Author: fijal Date: Sat Jan 5 13:07:43 2008 New Revision: 50352 Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/ - copied from r50351, pypy/branch/applevel-ctypes/pypy/lib/_ctypes/ pypy/branch/applevel-ctypes2/pypy/lib/ctypes/ - copied from r50351, pypy/branch/applevel-ctypes/pypy/lib/ctypes/ Log: Copy ctypes from the old branch From fijal at codespeak.net Sat Jan 5 13:10:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 13:10:36 +0100 (CET) Subject: [pypy-svn] r50353 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080105121036.426D816847F@codespeak.net> Author: fijal Date: Sat Jan 5 13:10:35 2008 New Revision: 50353 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/app_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: Merge _ffi from branch applevel-ctypes here Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py Sat Jan 5 13:10:35 2008 @@ -12,6 +12,7 @@ interpleveldefs = { 'CDLL' : 'interp_ffi.W_CDLL', 'FuncPtr' : 'interp_ffi.W_FuncPtr', + 'Structure' : 'structure.W_Structure', 'StructureInstance' : 'structure.W_StructureInstance', 'ArrayInstance' : 'array.W_ArrayInstance', '_get_type' : 'interp_ffi._w_get_type', @@ -19,7 +20,5 @@ } appleveldefs = { - 'Structure' : 'app_ffi.Structure', 'Array' : 'app_ffi.Array', - #'StructureInstance' : 'app_ffi.StructureInstance', } Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/app_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/app_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/app_ffi.py Sat Jan 5 13:10:35 2008 @@ -1,24 +1,5 @@ # NOT_RPYTHON -class Structure(object): - def check_fields(self, fields): - import _ffi - for name, letter in fields: - _ffi._get_type(letter) - - def __init__(self, fields): - self.check_fields(fields) - self.fields = fields - - def __call__(self, *args, **kwds): - from _ffi import StructureInstance - if args: - if len(args) > 1: - raise TypeError("Can give at most one non-keyword argument") - if kwds: - raise TypeError("Keyword arguments not allowed when passing address argument") - return StructureInstance(self, args[0], None) - return StructureInstance(self, None, kwds) class Array(object): def __init__(self, of): Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sat Jan 5 13:10:35 2008 @@ -124,14 +124,14 @@ __new__ = interp2app(descr_new_cdll), ptr = interp2app(W_CDLL.ptr), __doc__ = """ C Dynamically loaded library -use CDLL(libname) to create handle to C library (argument is processed the -same way as dlopen processes it). On such library call: +use CDLL(libname) to create a handle to a C library (the argument is processed +the same way as dlopen processes it). On such a library you can call: lib.ptr(func_name, argtype_list, restype) where argtype_list is a list of single characters and restype is a single -character. Character meanings are more or less the same as in struct module, -except that s has trailing \x00 added, while p is considered a raw buffer. -""" +character. The character meanings are more or less the same as in the struct +module, except that s has trailing \x00 added, while p is considered a raw +buffer.""" ) def pack_pointer(space, add_arg, argdesc, w_arg, push_func): Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py Sat Jan 5 13:10:35 2008 @@ -3,9 +3,9 @@ to app-level with apropriate interface """ -from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable,\ - Arguments -from pypy.interpreter.gateway import interp2app +from pypy.interpreter.baseobjspace import W_Root, Wrappable +from pypy.interpreter.gateway import interp2app, ObjSpace +from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror @@ -13,7 +13,7 @@ # the other one is in rlib/libffi, we should refactor it to reuse the same # logic, I'll not touch it by now, and refactor it later from pypy.module.struct.nativefmttable import native_fmttable as struct_native_fmttable -from pypy.module._ffi.interp_ffi import wrap_value, unwrap_value, _get_type +from pypy.module._ffi.interp_ffi import wrap_value, unwrap_value, _get_type, TYPEMAP native_fmttable = {} for key, value in struct_native_fmttable.items(): @@ -45,55 +45,98 @@ size += field_desc['size'] return size, pos + +class W_Structure(Wrappable): + def __init__(self, space, w_fields): + fields = unpack_fields(space, w_fields) + name_to_offset = {} + for i in range(len(fields)): + name, letter = fields[i] + if letter not in TYPEMAP: + raise OperationError(space.w_ValueError, space.wrap( + "Unkown type letter %s" % (letter,))) + if name in name_to_offset: + raise OperationError(space.w_ValueError, space.wrap( + "duplicate field name %s" % (name, ))) + name_to_offset[name] = i + size, pos = size_and_pos(fields) + self.size = size + self.ll_positions = pos + self.fields = fields + self.name_to_offset = name_to_offset + + def descr_call(self, space, __args__): + args_w, kwargs_w = __args__.unpack() + if args_w: + if len(args_w) > 1: + raise OperationError( + space.w_TypeError, + space.wrap("Can give at most one non-keyword argument")) + if kwargs_w: + raise OperationError( + space.w_TypeError, + space.wrap("Keyword arguments not allowed when passing address argument")) + return space.wrap(W_StructureInstance(space, self, args_w[0], None)) + return space.wrap(W_StructureInstance(space, self, None, kwargs_w)) + +def descr_new_structure(space, w_type, w_fields): + return space.wrap(W_Structure(space, w_fields)) + +W_Structure.typedef = TypeDef( + 'Structure', + __new__ = interp2app(descr_new_structure), + __call__ = interp2app(W_Structure.descr_call, + unwrap_spec=['self', ObjSpace, Arguments]), +) +W_Structure.typedef.acceptable_as_base_class = False + def push_field(self, num, value): - ptr = rffi.ptradd(self.ll_buffer, self.ll_positions[num]) + ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[num]) TP = lltype.typeOf(value) T = lltype.Ptr(rffi.CArray(TP)) rffi.cast(T, ptr)[0] = value push_field._annspecialcase_ = 'specialize:argtype(2)' def cast_pos(self, i, ll_t): - pos = rffi.ptradd(self.ll_buffer, self.ll_positions[i]) + pos = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i]) TP = lltype.Ptr(rffi.CArray(ll_t)) return rffi.cast(TP, pos)[0] cast_pos._annspecialcase_ = 'specialize:arg(2)' class W_StructureInstance(Wrappable): - def __init__(self, space, w_shape, w_address, w_fieldinits): + def __init__(self, space, shape, w_address, fieldinits_w): self.free_afterwards = False - w_fields = space.getattr(w_shape, space.wrap('fields')) - fields = unpack_fields(space, w_fields) - size, pos = size_and_pos(fields) - self.fields = fields - if space.is_true(w_address): + self.shape = shape + if w_address is not None: self.ll_buffer = rffi.cast(rffi.VOIDP, space.int_w(w_address)) else: self.free_afterwards = True - self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', + self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, shape.size, flavor='raw', zero=True) - self.ll_positions = pos - if space.is_true(w_fieldinits): - for w_field in space.unpackiterable(w_fieldinits): - w_value = space.getitem(w_fieldinits, w_field) - self.setattr(space, space.str_w(w_field), w_value) + if fieldinits_w: + self.fieldinits_w = fieldinits_w + for field, w_value in fieldinits_w.iteritems(): + self.setattr(space, field, w_value) + else: + self.fieldinits_w = None + + def getindex(self, space, attr): + try: + return self.shape.name_to_offset[attr] + except KeyError: + raise OperationError(space.w_AttributeError, space.wrap( + "C Structure has no attribute %s" % attr)) def getattr(self, space, attr): - if attr.startswith('tm'): - pass - for i in range(len(self.fields)): - name, c = self.fields[i] - if name == attr: - return wrap_value(space, cast_pos, self, i, c) - raise OperationError(space.w_AttributeError, space.wrap( - "C Structure has no attribute %s" % attr)) + i = self.getindex(space, attr) + _, c = self.shape.fields[i] + return wrap_value(space, cast_pos, self, i, c) getattr.unwrap_spec = ['self', ObjSpace, str] def setattr(self, space, attr, w_value): - for i in range(len(self.fields)): - name, c = self.fields[i] - if name == attr: - unwrap_value(space, push_field, self, i, c, w_value, None) - return + i = self.getindex(space, attr) + _, c = self.shape.fields[i] + unwrap_value(space, push_field, self, i, c, w_value, None) setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] def __del__(self): @@ -103,13 +146,11 @@ def getbuffer(space, self): return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) -def descr_new_structure_instance(space, w_type, w_shape, w_adr, w_fieldinits): - return W_StructureInstance(space, w_shape, w_adr, w_fieldinits) - W_StructureInstance.typedef = TypeDef( 'StructureInstance', - __new__ = interp2app(descr_new_structure_instance), __getattr__ = interp2app(W_StructureInstance.getattr), __setattr__ = interp2app(W_StructureInstance.setattr), buffer = GetSetProperty(W_StructureInstance.getbuffer), ) +W_StructureInstance.typedef.acceptable_as_base_class = False + Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sat Jan 5 13:10:35 2008 @@ -212,7 +212,6 @@ X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) x = X(next=X(next=None, x3='x'), x1=1, x2=2, x3='x') assert X(x.next).x3 == 'x' - assert inner(x) == 'x' create_double_struct = lib.ptr("create_double_struct", [], 'P') x = create_double_struct() assert X(X(x).next).x2 == 3 @@ -258,9 +257,7 @@ raises(ValueError, "lib.ptr('get_char', ['x'], None)") raises(ValueError, "lib.ptr('get_char', [], 'x')") raises(ValueError, "_ffi.Structure(['x1', 'xx'])") - S = _ffi.Structure([('x1', 'i')]) - S.fields[0] = ('x1', 'xx') - raises(ValueError, "S()") + raises(ValueError, _ffi.Structure, [('x1', 'xx')]) raises(ValueError, "_ffi.Array('xx')") A = _ffi.Array('i') A.of = 'xx' @@ -305,3 +302,14 @@ _ffi.CallbackPtr(compare, ['i', 'i'], 'i')) res = [ll_to_sort[i] for i in range(len(to_sort))] assert res == sorted(to_sort) + + def test_setattr_struct(self): + import _ffi + X = _ffi.Structure([('value1', 'i'), ('value2', 'i')]) + x = X(value1=1, value2=2) + assert x.value1 == 1 + assert x.value2 == 2 + x.value1 = 3 + assert x.value1 == 3 + raises(AttributeError, "x.foo") + raises(AttributeError, "x.foo = 1") From arigo at codespeak.net Sat Jan 5 16:20:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 5 Jan 2008 16:20:34 +0100 (CET) Subject: [pypy-svn] r50354 - in pypy/dist/pypy/rpython/memory: gc test Message-ID: <20080105152034.4A14716843F@codespeak.net> Author: arigo Date: Sat Jan 5 16:20:32 2008 New Revision: 50354 Modified: pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: For linux: parse /proc/cpuinfo when the program starts and deduce a reasonable nursery size from it. Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Sat Jan 5 16:20:32 2008 @@ -274,7 +274,9 @@ return SemiSpaceGC, GC_PARAMS elif config.translation.gc == "generation": GC_PARAMS = {'space_size': 8*1024*1024, # XXX adjust - 'nursery_size': 896*1024} + 'nursery_size': 896*1024, + 'min_nursery_size': 48*1024, + 'auto_nursery_size': True} from pypy.rpython.memory.gc.generation import GenerationGC return GenerationGC, GC_PARAMS else: Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Sat Jan 5 16:20:32 2008 @@ -32,6 +32,8 @@ def __init__(self, AddressLinkedList, nursery_size=128, + min_nursery_size=128, + auto_nursery_size=False, space_size=4096, max_space_size=sys.maxint//2+1, get_roots=None): @@ -39,8 +41,10 @@ space_size = space_size, max_space_size = max_space_size, get_roots = get_roots) - self.nursery_size = nursery_size - assert nursery_size <= space_size // 2 + assert min_nursery_size <= nursery_size <= space_size // 2 + self.initial_nursery_size = nursery_size + self.auto_nursery_size = auto_nursery_size + self.min_nursery_size = min_nursery_size def setup(self): SemiSpaceGC.setup(self) @@ -54,19 +58,56 @@ # reset to its correct value when GCFLAG_NO_YOUNG_PTRS is set # again at the start of a collection. self.young_objects_with_weakrefs = self.AddressLinkedList() + self.set_nursery_size(self.initial_nursery_size) + # the GC is fully setup now. The rest can make use of it. + if self.auto_nursery_size: + newsize = estimate_best_nursery_size() + if newsize > 0: + self.set_nursery_size(newsize) def reset_nursery(self): self.nursery = NULL self.nursery_top = NULL self.nursery_free = NULL + def set_nursery_size(self, newsize): + if newsize < self.min_nursery_size: + newsize = self.min_nursery_size + if newsize > self.space_size // 2: + newsize = self.space_size // 2 + + # Compute the new bounds for how large young objects can be + # (larger objects are allocated directly old). XXX adjust + self.nursery_size = newsize + self.largest_young_fixedsize = newsize // 2 - 1 + self.largest_young_var_basesize = newsize // 4 - 1 + scale = 0 + while (self.min_nursery_size << (scale+1)) <= newsize: + scale += 1 + self.nursery_scale = scale + if DEBUG_PRINT: + llop.debug_print(lltype.Void, "SSS nursery_size =", newsize) + llop.debug_print(lltype.Void, "SSS largest_young_fixedsize =", + self.largest_young_fixedsize) + llop.debug_print(lltype.Void, "SSS largest_young_var_basesize =", + self.largest_young_var_basesize) + llop.debug_print(lltype.Void, "SSS nursery_scale =", scale) + # we get the following invariant: + assert self.nursery_size >= (self.min_nursery_size << scale) + + # Force a full collect to remove the current nursery whose size + # no longer matches the bounds that we just computed. This must + # be done after changing the bounds, because it might re-create + # a new nursery (e.g. if it invokes finalizers). + self.semispace_collect() + def is_in_nursery(self, addr): return self.nursery <= addr < self.nursery_top def malloc_fixedsize_clear(self, typeid, size, can_collect, has_finalizer=False, contains_weakptr=False): if (has_finalizer or not can_collect or - raw_malloc_usage(size) >= self.nursery_size // 2): + raw_malloc_usage(size) > self.largest_young_fixedsize): ll_assert(not contains_weakptr, "wrong case for mallocing weakref") # "non-simple" case or object too big: don't use the nursery return SemiSpaceGC.malloc_fixedsize_clear(self, typeid, size, @@ -101,11 +142,27 @@ def malloc_varsize_clear(self, typeid, length, size, itemsize, offset_to_length, can_collect, has_finalizer=False): - # only use the nursery if there are not too many items + # Only use the nursery if there are not too many items. + if not raw_malloc_usage(itemsize): + too_many_items = False + else: + # The following line is usually constant-folded because both + # min_nursery_size and itemsize are constants (the latter + # due to inlining). + maxlength_for_minimal_nursery = (self.min_nursery_size // 4 // + raw_malloc_usage(itemsize)) + + # The actual maximum length for our nursery depends on how + # many times our nursery is bigger than the minimal size. + # The computation is done in this roundabout way so that + # only the only remaining computation is the following + # shift. + maxlength = maxlength_for_minimal_nursery << self.nursery_scale + too_many_items = length > maxlength + if (has_finalizer or not can_collect or - (raw_malloc_usage(itemsize) and - length > self.nursery_size // 4 // raw_malloc_usage(itemsize)) or - raw_malloc_usage(size) > self.nursery_size // 4): + too_many_items or + raw_malloc_usage(size) > self.largest_young_var_basesize): return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size, itemsize, offset_to_length, can_collect, has_finalizer) @@ -314,3 +371,85 @@ if oldhdr.tid & GCFLAG_NO_HEAP_PTRS: self.move_to_static_roots(addr_struct) remember_young_pointer._dont_inline_ = True + +# ____________________________________________________________ + +if sys.platform == 'linux2': + def estimate_best_nursery_size(): + """Try to estimate the best nursery size at run-time, depending + on the machine we are running on. + """ + import os + L2cache = sys.maxint + try: + fd = os.open('/proc/cpuinfo', os.O_RDONLY, 0644) + try: + data = [] + while True: + buf = os.read(fd, 4096) + if not buf: + break + data.append(buf) + finally: + os.close(fd) + except OSError: + pass + else: + data = ''.join(data) + linepos = 0 + while True: + start = findend(data, '\ncache size', linepos) + if start < 0: + break # done + linepos = findend(data, '\n', start) + if linepos < 0: + break # no end-of-line?? + # *** data[start:linepos] == " : 2048 KB\n" + start = skipspace(data, start) + if data[start] != ':': + continue + # *** data[start:linepos] == ": 2048 KB\n" + start = skipspace(data, start + 1) + # *** data[start:linepos] == "2048 KB\n" + end = start + while '0' <= data[end] <= '9': + end += 1 + # *** data[start:end] == "2048" + if start == end: + continue + number = int(data[start:end]) + # *** data[end:linepos] == " KB\n" + end = skipspace(data, end) + if data[end] not in ('K', 'k'): # assume kilobytes for now + continue + number = number * 1024 + # for now we look for the smallest of the L2 caches of the CPUs + if number < L2cache: + L2cache = number + + if L2cache < sys.maxint: + if DEBUG_PRINT: + llop.debug_print(lltype.Void, "CCC L2cache =", L2cache) + + # Heuristically, the best nursery size to choose is almost as + # big as the L2 cache. XXX adjust + return L2cache // 8 * 7 + else: + llop.debug_print(lltype.Void, + "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo") + return -1 + + def findend(data, pattern, pos): + pos = data.find(pattern, pos) + if pos < 0: + return -1 + return pos + len(pattern) + + def skipspace(data, pos): + while data[pos] in (' ', '\t'): + pos += 1 + return pos + +else: + def estimate_best_nursery_size(): + return -1 # XXX implement me for other platforms 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 Sat Jan 5 16:20:32 2008 @@ -912,8 +912,13 @@ class transformerclass(framework.FrameworkGCTransformer): from pypy.rpython.memory.gc.generation import GenerationGC class GCClass(GenerationGC): + __ready = False + def setup(self): + from pypy.rpython.memory.gc.generation import GenerationGC + GenerationGC.setup(self) + self.__ready = True def semispace_collect(self, size_changing=False): - ll_assert(False, + ll_assert(not self.__ready, "no full collect should occur in this test") GC_PARAMS = {'space_size': 2048, 'nursery_size': 512} From fijal at codespeak.net Sat Jan 5 16:38:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 16:38:01 +0100 (CET) Subject: [pypy-svn] r50355 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080105153801.CE313168432@codespeak.net> Author: fijal Date: Sat Jan 5 16:38:01 2008 New Revision: 50355 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/__init__.py (contents, props changed) Log: Add a directory for porting ctypes tests to py.test. Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/__init__.py ============================================================================== From fijal at codespeak.net Sat Jan 5 16:51:25 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 16:51:25 +0100 (CET) Subject: [pypy-svn] r50356 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080105155125.8387D168438@codespeak.net> Author: fijal Date: Sat Jan 5 16:51:25 2008 New Revision: 50356 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py (contents, props changed) Log: Add ported test_numbers Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py Sat Jan 5 16:51:25 2008 @@ -0,0 +1,176 @@ +from ctypes import * +import unittest +import sys, struct + +def valid_ranges(*types): + # given a sequence of numeric types, collect their _type_ + # attribute, which is a single format character compatible with + # the struct module, use the struct module to calculate the + # minimum and maximum value allowed for this format. + # Returns a list of (min, max) values. + result = [] + for t in types: + fmt = t._type_ + size = struct.calcsize(fmt) + a = struct.unpack(fmt, ("\x00"*32)[:size])[0] + b = struct.unpack(fmt, ("\xFF"*32)[:size])[0] + c = struct.unpack(fmt, ("\x7F"+"\x00"*32)[:size])[0] + d = struct.unpack(fmt, ("\x80"+"\xFF"*32)[:size])[0] + result.append((min(a, b, c, d), max(a, b, c, d))) + return result + +ArgType = type(byref(c_int(0))) + +unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong] +signed_types = [c_byte, c_short, c_int, c_long, c_longlong] + +float_types = [c_double, c_float] + +try: + c_ulonglong + c_longlong +except NameError: + pass +else: + unsigned_types.append(c_ulonglong) + signed_types.append(c_longlong) + +unsigned_ranges = valid_ranges(*unsigned_types) +signed_ranges = valid_ranges(*signed_types) + +################################################################ + +class TestNumber: + def test_default_init(self): + # default values are set to zero + for t in signed_types + unsigned_types + float_types: + assert t().value == 0 + + def test_unsigned_values(self): + # the value given to the constructor is available + # as the 'value' attribute + for t, (l, h) in zip(unsigned_types, unsigned_ranges): + assert t(l).value == l + assert t(h).value == h + + def test_signed_values(self): + # see above + for t, (l, h) in zip(signed_types, signed_ranges): + assert t(l).value == l + assert t(h).value == h + + def test_typeerror(self): + # Only numbers are allowed in the contructor, + # otherwise TypeError is raised + for t in signed_types + unsigned_types + float_types: + raises(TypeError, t, "") + raises(TypeError, t, None) + +## def test_valid_ranges(self): +## # invalid values of the correct type +## # raise ValueError (not OverflowError) +## for t, (l, h) in zip(unsigned_types, unsigned_ranges): +## self.assertRaises(ValueError, t, l-1) +## self.assertRaises(ValueError, t, h+1) + + def test_from_param(self): + # the from_param class method attribute always + # returns PyCArgObject instances + for t in signed_types + unsigned_types + float_types: + assert ArgType == type(t.from_param(0)) + + def test_byref(self): + # calling byref returns also a PyCArgObject instance + for t in signed_types + unsigned_types + float_types: + parm = byref(t()) + assert ArgType == type(parm) + + + def test_floats(self): + # c_float and c_double can be created from + # Python int, long and float + for t in float_types: + assert t(2.0).value == 2.0 + assert t(2).value == 2.0 + assert t(2L).value == 2.0 + + def test_integers(self): + # integers cannot be constructed from floats + for t in signed_types + unsigned_types: + raises(TypeError, t, 3.14) + + def test_sizes(self): + for t in signed_types + unsigned_types + float_types: + size = struct.calcsize(t._type_) + # sizeof of the type... + assert sizeof(t) == size + # and sizeof of an instance + assert sizeof(t()) == size + + def test_alignments(self): + for t in signed_types + unsigned_types + float_types: + code = t._type_ # the typecode + align = struct.calcsize("c%c" % code) - struct.calcsize(code) + + # alignment of the type... + assert (code, alignment(t)) == (code, align) + # and alignment of an instance + assert (code, alignment(t())) == (code, align) + + def test_int_from_address(self): + from array import array + for t in signed_types + unsigned_types: + # the array module doesn't suppport all format codes + # (no 'q' or 'Q') + try: + array(t._type_) + except ValueError: + continue + a = array(t._type_, [100]) + + # v now is an integer at an 'external' memory location + v = t.from_address(a.buffer_info()[0]) + assert v.value == a[0] + assert type(v) == t + + # changing the value at the memory location changes v's value also + a[0] = 42 + assert v.value == a[0] + + + def test_float_from_address(self): + from array import array + for t in float_types: + a = array(t._type_, [3.14]) + v = t.from_address(a.buffer_info()[0]) + assert v.value == a[0] + assert type(v) is t + a[0] = 2.3456e17 + assert v.value == a[0] + assert type(v) is t + + def test_char_from_address(self): + from ctypes import c_char + from array import array + + a = array('c', 'x') + v = c_char.from_address(a.buffer_info()[0]) + assert v.value == a[0] + assert type(v) is c_char + + a[0] = '?' + assert v.value == a[0] + + def test_init(self): + # c_int() can be initialized from Python's int, and c_int. + # Not from c_long or so, which seems strange, abd should + # probably be changed: + raises(TypeError, c_int, c_long(42)) + +## def test_perf(self): +## check_perf() + +from ctypes import _SimpleCData +class c_int_S(_SimpleCData): + _type_ = "i" + __slots__ = [] From fijal at codespeak.net Sat Jan 5 17:04:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 17:04:58 +0100 (CET) Subject: [pypy-svn] r50357 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080105160458.49FBE168444@codespeak.net> Author: fijal Date: Sat Jan 5 17:04:54 2008 New Revision: 50357 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Log: Don't automatically cast byte and ubyte to string. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sat Jan 5 17:04:54 2008 @@ -257,7 +257,7 @@ return space.wrap(func(add_arg, argdesc, ll_type)) elif c == 'f' or c == 'd': return space.wrap(float(func(add_arg, argdesc, ll_type))) - elif c == 'c' or c == 'b' or c == 'B': + elif c == 'c': return space.wrap(chr(rffi.cast(rffi.INT, func(add_arg, argdesc, ll_type)))) elif c == 'h' or c == 'H': From arigo at codespeak.net Sat Jan 5 17:45:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 5 Jan 2008 17:45:21 +0100 (CET) Subject: [pypy-svn] r50358 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080105164521.575C416843C@codespeak.net> Author: arigo Date: Sat Jan 5 17:45:20 2008 New Revision: 50358 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py Log: Code to read the L2 cache size on OS/X. Thanks pedronis for hints. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Sat Jan 5 17:45:20 2008 @@ -374,6 +374,14 @@ # ____________________________________________________________ +def best_nursery_size_for_L2cache(L2cache): + if DEBUG_PRINT: + llop.debug_print(lltype.Void, "CCC L2cache =", L2cache) + # Heuristically, the best nursery size to choose is almost as + # big as the L2 cache. XXX adjust + return L2cache // 8 * 7 + + if sys.platform == 'linux2': def estimate_best_nursery_size(): """Try to estimate the best nursery size at run-time, depending @@ -428,13 +436,9 @@ L2cache = number if L2cache < sys.maxint: - if DEBUG_PRINT: - llop.debug_print(lltype.Void, "CCC L2cache =", L2cache) - - # Heuristically, the best nursery size to choose is almost as - # big as the L2 cache. XXX adjust - return L2cache // 8 * 7 + return best_nursery_size_for_L2cache(L2cache) else: + # Print a warning even in non-debug builds llop.debug_print(lltype.Void, "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo") return -1 @@ -450,6 +454,48 @@ pos += 1 return pos +elif sys.platform == 'darwin': + from pypy.rpython.lltypesystem import lltype, rffi + + sysctlbyname = rffi.llexternal('sysctlbyname', + [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP, + rffi.VOIDP, rffi.SIZE_T], + rffi.INT) + + def estimate_best_nursery_size(): + """Try to estimate the best nursery size at run-time, depending + on the machine we are running on. + """ + L2cache = 0 + l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw') + try: + len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw') + try: + size = rffi.sizeof(rffi.LONGLONG) + l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0) + len_p[0] = rffi.cast(rffi.SIZE_T, size) + result = sysctlbyname("hw.l2cachesize", + rffi.cast(rffi.VOIDP, l2cache_p), + len_p, + lltype.nullptr(rffi.VOIDP.TO), + rffi.cast(rffi.SIZE_T, 0)) + if (rffi.cast(lltype.Signed, result) == 0 and + rffi.cast(lltype.Signed, len_p[0]) == size): + L2cache = rffi.cast(lltype.Signed, l2cache_p[0]) + if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]: + L2cache = 0 # overflow! + finally: + lltype.free(len_p, flavor='raw') + finally: + lltype.free(l2cache_p, flavor='raw') + if L2cache > 0: + return best_nursery_size_for_L2cache(L2cache) + else: + # Print a warning even in non-debug builds + llop.debug_print(lltype.Void, + "Warning: cannot find your CPU L2 cache size with sysctl()") + return -1 + else: def estimate_best_nursery_size(): return -1 # XXX implement me for other platforms From ac at codespeak.net Sat Jan 5 19:19:56 2008 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 5 Jan 2008 19:19:56 +0100 (CET) Subject: [pypy-svn] r50359 - in pypy/dist/pypy: rlib rpython/module Message-ID: <20080105181956.57955168436@codespeak.net> Author: ac Date: Sat Jan 5 19:19:55 2008 New Revision: 50359 Modified: pypy/dist/pypy/rlib/rstack.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/ll_os_environ.py Log: Whack, whack, whack until it translates on 64 bit Linux. Modified: pypy/dist/pypy/rlib/rstack.py ============================================================================== --- pypy/dist/pypy/rlib/rstack.py (original) +++ pypy/dist/pypy/rlib/rstack.py Sat Jan 5 19:19:55 2008 @@ -41,7 +41,7 @@ _callable=lambda: 0) def stack_check(): - if stack_too_big(): + if rffi.cast(lltype.Signed, stack_too_big()): # stack_unwind implementation is different depending on if stackless # is enabled. If it is it unwinds the stack, otherwise it simply # raises a RuntimeError. Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Sat Jan 5 19:19:55 2008 @@ -268,6 +268,7 @@ else: actime, modtime = tp error = os_utime_platform(path, actime, modtime) + error = rffi.cast(lltype.Signed, error) if error == -1: raise OSError(rposix.get_errno(), "os_utime failed") os_utime_llimpl._annspecialcase_ = 'specialize:argtype(1)' @@ -595,7 +596,7 @@ rffi.INT) def access_llimpl(path, mode): - error = os_access(path, mode) + error = rffi.cast(lltype.Signed, os_access(path, mode)) return error == 0 def os_access_oofakeimpl(path, mode): @@ -842,13 +843,14 @@ def os_pipe_llimpl(): filedes = lltype.malloc(INT_ARRAY_P.TO, 2, flavor='raw') - error = os_pipe(filedes) + error = rffi.cast(lltype.Signed, os_pipe(filedes)) read_fd = filedes[0] write_fd = filedes[1] lltype.free(filedes, flavor='raw') if error != 0: raise OSError(rposix.get_errno(), "os_pipe failed") - return (read_fd, write_fd) + return (rffi.cast(lltype.Signed, read_fd), + rffi.cast(lltype.Signed, write_fd)) return extdef([], (int, int), "ll_os.ll_os_pipe", @@ -867,7 +869,7 @@ l_path = rffi.str2charp(path) buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw') - res = os_readlink(l_path, buf, bufsize) + res = rffi.cast(lltype.Signed, os_readlink(l_path, buf, bufsize)) lltype.free(l_path, flavor='raw') if res < 0: error = rposix.get_errno() # failed @@ -910,10 +912,11 @@ def os_waitpid_llimpl(pid, options): status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') - status_p[0] = 0 + status_p[0] = rffi.cast(rffi.INT, 0) result = os_waitpid(rffi.cast(rffi.PID_T, pid), status_p, rffi.cast(rffi.INT, options)) + result = rffi.cast(lltype.Signed, result) status = status_p[0] lltype.free(status_p, flavor='raw') if result == -1: @@ -955,7 +958,7 @@ def system_llimpl(command): res = os_system(command) - return res + return rffi.cast(lltype.Signed, res) return extdef([str], int, llimpl=system_llimpl, export_name="ll_os.ll_os_system") @@ -965,7 +968,7 @@ os_unlink = self.llexternal(underscore_on_windows+'unlink', [rffi.CCHARP], rffi.INT) def unlink_llimpl(pathname): - res = os_unlink(pathname) + res = rffi.cast(lltype.Signed, os_unlink(pathname)) if res < 0: raise OSError(rposix.get_errno(), "os_unlink failed") @@ -977,7 +980,7 @@ os_chdir = self.llexternal(underscore_on_windows+'chdir', [rffi.CCHARP], rffi.INT) def chdir_llimpl(path): - res = os_chdir(path) + res = rffi.cast(lltype.Signed, os_chdir(path)) if res < 0: raise OSError(rposix.get_errno(), "os_chdir failed") @@ -999,6 +1002,7 @@ res = os_mkdir(pathname) else: res = os_mkdir(pathname, mode) + res = rffi.cast(lltype.Signed, res) if res < 0: raise OSError(rposix.get_errno(), "os_mkdir failed") @@ -1010,7 +1014,7 @@ os_rmdir = self.llexternal(underscore_on_windows+'rmdir', [rffi.CCHARP], rffi.INT) def rmdir_llimpl(pathname): - res = os_rmdir(pathname) + res = rffi.cast(lltype.Signed, os_rmdir(pathname)) if res < 0: raise OSError(rposix.get_errno(), "os_rmdir failed") @@ -1023,7 +1027,7 @@ rffi.INT) def chmod_llimpl(path, mode): - res = os_chmod(path, rffi.cast(rffi.MODE_T, mode)) + res = rffi.cast(lltype.Signed, os_chmod(path, rffi.cast(rffi.MODE_T, mode))) if res < 0: raise OSError(rposix.get_errno(), "os_chmod failed") @@ -1036,7 +1040,7 @@ rffi.INT) def rename_llimpl(oldpath, newpath): - res = os_rename(oldpath, newpath) + res = rffi.cast(lltype.Signed, os_rename(oldpath, newpath)) if res < 0: raise OSError(rposix.get_errno(), "os_rename failed") @@ -1060,8 +1064,8 @@ rffi.INT) def kill_llimpl(pid, sig): - res = os_kill(rffi.cast(rffi.PID_T, pid), - rffi.cast(rffi.INT, sig)) + res = rffi.cast(lltype.Signed, os_kill(rffi.cast(rffi.PID_T, pid), + rffi.cast(rffi.INT, sig))) if res < 0: raise OSError(rposix.get_errno(), "os_kill failed") @@ -1074,7 +1078,7 @@ rffi.INT) def link_llimpl(oldpath, newpath): - res = os_link(oldpath, newpath) + res = rffi.cast(lltype.Signed, os_link(oldpath, newpath)) if res < 0: raise OSError(rposix.get_errno(), "os_link failed") @@ -1087,7 +1091,7 @@ rffi.INT) def symlink_llimpl(oldpath, newpath): - res = os_symlink(oldpath, newpath) + res = rffi.cast(lltype.Signed, os_symlink(oldpath, newpath)) if res < 0: raise OSError(rposix.get_errno(), "os_symlink failed") @@ -1099,7 +1103,7 @@ os_fork = self.llexternal('fork', [], rffi.PID_T) def fork_llimpl(): - childpid = os_fork() + childpid = rffi.cast(lltype.Signed, os_fork()) if childpid == -1: raise OSError(rposix.get_errno(), "os_fork failed") return rffi.cast(lltype.Signed, childpid) Modified: pypy/dist/pypy/rpython/module/ll_os_environ.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os_environ.py (original) +++ pypy/dist/pypy/rpython/module/ll_os_environ.py Sat Jan 5 19:19:55 2008 @@ -82,7 +82,7 @@ def putenv_llimpl(name, value): l_string = rffi.str2charp('%s=%s' % (name, value)) - error = os_putenv(l_string) + error = rffi.cast(lltype.Signed, os_putenv(l_string)) if error: rffi.free_charp(l_string) raise OSError(rposix.get_errno(), "os_putenv failed") @@ -107,9 +107,12 @@ if sys.platform.startswith('darwin'): RETTYPE = lltype.Void + os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], RETTYPE) else: RETTYPE = rffi.INT - os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], RETTYPE) + _os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], RETTYPE) + def os_unsetenv(l_name): + return rffi.cast(lltype.Signed, _os_unsetenv(l_name)) def unsetenv_llimpl(name): l_name = rffi.str2charp(name) From ac at codespeak.net Sat Jan 5 19:23:27 2008 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 5 Jan 2008 19:23:27 +0100 (CET) Subject: [pypy-svn] r50360 - pypy/dist/pypy/rlib Message-ID: <20080105182327.C7305168435@codespeak.net> Author: ac Date: Sat Jan 5 19:23:27 2008 New Revision: 50360 Modified: pypy/dist/pypy/rlib/libffi.py Log: Make pypy/rlib/test/test_libffi.py pass on 64 bit Linux. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Sat Jan 5 19:23:27 2008 @@ -138,7 +138,7 @@ mode = RTLD_LOCAL | RTLD_NOW else: mode = RTLD_NOW - res = c_dlopen(name, mode) + res = c_dlopen(name, rffi.cast(rffi.INT, mode)) if not res: raise OSError(-1, dlerror()) return res From arigo at codespeak.net Sat Jan 5 21:18:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 5 Jan 2008 21:18:27 +0100 (CET) Subject: [pypy-svn] r50361 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080105201827.A0EE3168453@codespeak.net> Author: arigo Date: Sat Jan 5 21:18:25 2008 New Revision: 50361 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py Log: Finally figured out how I'm supposed to use mutate(). The trick is that the default() method of the visitors is not doing the right thing at all in this case, leading to completely bogus performance. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ast.py Sat Jan 5 21:18:25 2008 @@ -5915,9 +5915,12 @@ """ def default(self, node): + """This method is only suitable for when we use accept(visitor), + not mutate(visitor). In the latter case it *must* be overridden + by the visitor, typically to just return an unmodified "node". + """ for child in node.getChildNodes(): child.accept(self) - return node def _mutate_list(self, lst): i = 0 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/astgen.py Sat Jan 5 21:18:25 2008 @@ -596,9 +596,12 @@ """ def default(self, node): + """This method is only suitable for when we use accept(visitor), + not mutate(visitor). In the latter case it *must* be overridden + by the visitor, typically to just return an unmodified "node". + """ for child in node.getChildNodes(): child.accept(self) - return node def _mutate_list(self, lst): i = 0 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/opt.py Sat Jan 5 21:18:25 2008 @@ -84,6 +84,9 @@ def __init__(self, space): self.space = space + def default(self, node): + return node + def _visitUnaryOp(self, node, constant_fold): expr = node.expr if isinstance(expr, ast.Const): Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_ast.py Sat Jan 5 21:18:25 2008 @@ -3,6 +3,8 @@ from pypy.interpreter.pyparser.test.test_astbuilder import FakeSpace class BaseVisitor(ast.ASTVisitor): + def default(self, node): + return node def visitAdd(self, node): return ast.Const(3) From fijal at codespeak.net Sat Jan 5 21:21:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 5 Jan 2008 21:21:37 +0100 (CET) Subject: [pypy-svn] r50362 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080105202137.D39F716843C@codespeak.net> Author: fijal Date: Sat Jan 5 21:21:37 2008 New Revision: 50362 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Log: ARGH! solve properly char/unsigned char/signed char mess Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sat Jan 5 21:21:37 2008 @@ -38,8 +38,8 @@ LL_TYPEMAP = { 'c' : rffi.CHAR, - 'b' : rffi.UCHAR, - 'B' : rffi.CHAR, + 'b' : rffi.SIGNEDCHAR, + 'B' : rffi.UCHAR, 'h' : rffi.SHORT, 'H' : rffi.USHORT, 'i' : rffi.INT, From ac at codespeak.net Sat Jan 5 22:35:59 2008 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 5 Jan 2008 22:35:59 +0100 (CET) Subject: [pypy-svn] r50363 - pypy/dist/pypy/rlib Message-ID: <20080105213559.12332168444@codespeak.net> Author: ac Date: Sat Jan 5 22:35:58 2008 New Revision: 50363 Modified: pypy/dist/pypy/rlib/rsocket.py Log: Make _socket annotate on 64 bit (still 53 errors when rtyping). Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Sat Jan 5 22:35:58 2008 @@ -1125,7 +1125,7 @@ rffi.setintfield(hints, 'c_ai_flags' , flags) # XXX need to lock around getaddrinfo() calls? p_res = lltype.malloc(rffi.CArray(_c.addrinfo_ptr), 1, flavor='raw') - error = _c.getaddrinfo(host, port_or_service, hints, p_res) + error = intmask(_c.getaddrinfo(host, port_or_service, hints, p_res)) res = p_res[0] lltype.free(p_res, flavor='raw') lltype.free(hints, flavor='raw') @@ -1177,9 +1177,9 @@ serv = lltype.malloc(rffi.CCHARP.TO, NI_MAXSERV, flavor='raw') try: addr = address.lock() - error =_c.getnameinfo(addr, address.addrlen, - host, NI_MAXHOST, - serv, NI_MAXSERV, flags) + error = intmask(_c.getnameinfo(addr, address.addrlen, + host, NI_MAXHOST, + serv, NI_MAXSERV, flags)) address.unlock() if error: raise GAIError(error) From fijal at codespeak.net Sun Jan 6 10:31:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 10:31:33 +0100 (CET) Subject: [pypy-svn] r50365 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080106093133.3FC44168436@codespeak.net> Author: fijal Date: Sun Jan 6 10:31:31 2008 New Revision: 50365 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: Add size and alignment (extremely hard english word) to _ffi interface. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py Sun Jan 6 10:31:31 2008 @@ -16,6 +16,8 @@ 'StructureInstance' : 'structure.W_StructureInstance', 'ArrayInstance' : 'array.W_ArrayInstance', '_get_type' : 'interp_ffi._w_get_type', + 'sizeof' : 'interp_ffi.sizeof', + 'alignment' : 'interp_ffi.alignment', #'CallbackPtr' : 'callback.W_CallbackPtr', } Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sun Jan 6 10:31:31 2008 @@ -11,6 +11,7 @@ from pypy.module.struct.standardfmttable import min_max_acc_method from pypy.module.struct.nativefmttable import native_fmttable +from pypy.tool.sourcetools import func_with_new_name class FfiValueError(Exception): def __init__(self, msg): @@ -306,3 +307,20 @@ 'FuncPtr', __call__ = interp2app(W_FuncPtr.call) ) + +def _create_new_accessor(func_name, name): + def accessor(space, tp_letter): + if len(tp_letter) != 1: + raise OperationError(space.w_ValueError, space.wrap( + "Expecting string of length one")) + tp_letter = tp_letter[0] # fool annotator + try: + return space.wrap(getattr(TYPEMAP[tp_letter], name)) + except KeyError: + raise OperationError(space.w_ValueError, space.wrap( + "Unknown type specification %s" % tp_letter)) + accessor.unwrap_spec = [ObjSpace, str] + return func_with_new_name(accessor, func_name) + +sizeof = _create_new_accessor('sizeof', 'c_size') +alignment = _create_new_accessor('alignment', 'c_alignment') Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 6 10:31:31 2008 @@ -1,7 +1,9 @@ from pypy.conftest import gettestobjspace -from pypy.translator.tool.cbuild import compile_c_module, ExternalCompilationInfo +from pypy.translator.tool.cbuild import compile_c_module, \ + ExternalCompilationInfo +from pypy.module._ffi.interp_ffi import TYPEMAP import os, sys, py @@ -97,6 +99,8 @@ space = gettestobjspace(usemodules=('_ffi','struct')) cls.space = space cls.w_lib_name = space.wrap(cls.prepare_c_example()) + cls.w_sizes_and_alignments = space.wrap(dict( + [(k, (v.c_size, v.c_alignment)) for k,v in TYPEMAP.iteritems()])) def test_libload(self): import _ffi @@ -313,3 +317,10 @@ assert x.value1 == 3 raises(AttributeError, "x.foo") raises(AttributeError, "x.foo = 1") + + def test_sizes_and_alignments(self): + import _ffi + for k, (s, a) in self.sizes_and_alignments.iteritems(): + assert _ffi.sizeof(k) == s + assert _ffi.alignment(k) == a + From fijal at codespeak.net Sun Jan 6 10:48:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 10:48:11 +0100 (CET) Subject: [pypy-svn] r50366 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080106094811.CC2B6168447@codespeak.net> Author: fijal Date: Sun Jan 6 10:48:11 2008 New Revision: 50366 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Log: Fix translation Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sun Jan 6 10:48:11 2008 @@ -315,7 +315,7 @@ "Expecting string of length one")) tp_letter = tp_letter[0] # fool annotator try: - return space.wrap(getattr(TYPEMAP[tp_letter], name)) + return space.wrap(intmask(getattr(TYPEMAP[tp_letter], name))) except KeyError: raise OperationError(space.w_ValueError, space.wrap( "Unknown type specification %s" % tp_letter)) From fijal at codespeak.net Sun Jan 6 11:44:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 11:44:36 +0100 (CET) Subject: [pypy-svn] r50367 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080106104436.99FA9168457@codespeak.net> Author: fijal Date: Sun Jan 6 11:44:35 2008 New Revision: 50367 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: sizeof and alignment for primitives. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Sun Jan 6 11:44:35 2008 @@ -1,10 +1,10 @@ from _ctypes.dummy import Union, Structure, Array, _Pointer -from _ctypes.dummy import ArgumentError, sizeof, byref, addressof -from _ctypes.dummy import alignment, resize +from _ctypes.dummy import ArgumentError, byref, addressof +from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr from _ctypes.dummy import _cast_addr -from _ctypes.primitive import _SimpleCData +from _ctypes.primitive import _SimpleCData, sizeof, alignment from _ctypes.function import CFuncPtr from _ctypes.dll import dlopen Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py Sun Jan 6 11:44:35 2008 @@ -24,7 +24,6 @@ def dummyfunc(*args, **kwargs): return None -sizeof = dummyfunc byref = dummyfunc addressof = dummyfunc alignment = dummyfunc Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Sun Jan 6 11:44:35 2008 @@ -13,7 +13,7 @@ TP_TO_DEFAULT = { - 'c': '\x00', + 'c': 0, 'b': 0, 'B': 0, 'h': 0, @@ -73,3 +73,8 @@ def __repr__(self): return "%s(%s)" % (type(self).__name__, self.value) +def sizeof(tp): + return _ffi.sizeof(tp._type_) + +def alignment(tp): + return _ffi.alignment(tp._type_) From fijal at codespeak.net Sun Jan 6 12:00:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 12:00:43 +0100 (CET) Subject: [pypy-svn] r50368 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080106110043.B2D46168457@codespeak.net> Author: fijal Date: Sun Jan 6 12:00:43 2008 New Revision: 50368 Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py Log: * don't import unittest * skip tests which are not there yet. Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py Sun Jan 6 12:00:43 2008 @@ -1,5 +1,5 @@ +import py from ctypes import * -import unittest import sys, struct def valid_ranges(*types): @@ -81,6 +81,7 @@ def test_byref(self): # calling byref returns also a PyCArgObject instance + py.test.skip("Works by accident") for t in signed_types + unsigned_types + float_types: parm = byref(t()) assert ArgType == type(parm) @@ -118,6 +119,7 @@ assert (code, alignment(t())) == (code, align) def test_int_from_address(self): + py.test.skip("Unsupported") from array import array for t in signed_types + unsigned_types: # the array module doesn't suppport all format codes @@ -139,6 +141,7 @@ def test_float_from_address(self): + py.test.skip("Unsupported") from array import array for t in float_types: a = array(t._type_, [3.14]) @@ -150,6 +153,7 @@ assert type(v) is t def test_char_from_address(self): + py.test.skip("Unsupported") from ctypes import c_char from array import array From cfbolz at codespeak.net Sun Jan 6 12:51:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 12:51:17 +0100 (CET) Subject: [pypy-svn] r50369 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080106115117.54B51168457@codespeak.net> Author: cfbolz Date: Sun Jan 6 12:51:16 2008 New Revision: 50369 Removed: pypy/branch/applevel-ctypes2/pypy/module/_ffi/app_ffi.py Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: refactor arrays in the same way as I did with structures: now Array lives at interplevel and W_ArrayInstance has a reference to an W_Array which keeps all the common information. So far there is not much common information. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py Sun Jan 6 12:51:16 2008 @@ -14,6 +14,7 @@ 'FuncPtr' : 'interp_ffi.W_FuncPtr', 'Structure' : 'structure.W_Structure', 'StructureInstance' : 'structure.W_StructureInstance', + 'Array' : 'array.W_Array', 'ArrayInstance' : 'array.W_ArrayInstance', '_get_type' : 'interp_ffi._w_get_type', 'sizeof' : 'interp_ffi.sizeof', @@ -22,5 +23,4 @@ } appleveldefs = { - 'Array' : 'app_ffi.Array', } Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Sun Jan 6 12:51:16 2008 @@ -6,7 +6,7 @@ from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable,\ Arguments from pypy.interpreter.gateway import interp2app -from pypy.interpreter.typedef import TypeDef, GetSetProperty +from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror from pypy.module._ffi.structure import native_fmttable @@ -23,27 +23,49 @@ return ll_array[pos] get_elem._annspecialcase_ = 'specialize:arg(2)' -class W_ArrayInstance(Wrappable): - def __init__(self, space, of, w_length_or_iterable): - self.ll_array = lltype.nullptr(rffi.VOIDP.TO) +class W_Array(Wrappable): + def __init__(self, space, of): + self.space = space + self.of = of + self.itemsize = native_fmttable[of]['size'] + + def descr_call(self, space, w_length_or_iterable): if space.is_true(space.isinstance(w_length_or_iterable, space.w_int)): length = space.int_w(w_length_or_iterable) - items_w = None + return space.wrap(W_ArrayInstance(space, self, length)) else: items_w = space.unpackiterable(w_length_or_iterable) length = len(items_w) + result = W_ArrayInstance(space, self, length) + for num in range(len(items_w)): + w_item = items_w[num] + unwrap_value(space, push_elem, result.ll_array, num, self.of, + w_item, None) + return space.wrap(result) + +def descr_new_array(space, w_type, of): + _get_type(space, of) + return space.wrap(W_Array(space, of)) + +W_Array.typedef = TypeDef( + 'Array', + __new__ = interp2app(descr_new_array, unwrap_spec=[ObjSpace, W_Root, str]), + __call__ = interp2app(W_Array.descr_call, + unwrap_spec=['self', ObjSpace, W_Root]), + of = interp_attrproperty('of', W_Array), +) +W_Array.typedef.acceptable_as_base_class = False + + +class W_ArrayInstance(Wrappable): + def __init__(self, space, shape, length): + self.ll_array = lltype.nullptr(rffi.VOIDP.TO) self.alloced = False - self.of = of - _get_type(space, of) + self.shape = shape self.length = length - size = native_fmttable[of]['size'] * length + size = shape.itemsize * length self.ll_array = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', zero=True) - if items_w: - for num in range(len(items_w)): - w_item = items_w[num] - unwrap_value(space, push_elem, self.ll_array, num, self.of, - w_item, None) # XXX don't allow negative indexes, nor slices @@ -51,7 +73,7 @@ if num >= self.length or num < 0: raise OperationError(space.w_ValueError, space.wrap( "Setting element %d of array sized %d" % (num, self.length))) - unwrap_value(space, push_elem, self.ll_array, num, self.of, w_value, + unwrap_value(space, push_elem, self.ll_array, num, self.shape.of, w_value, None) setitem.unwrap_spec = ['self', ObjSpace, int, W_Root] @@ -59,7 +81,7 @@ if num >= self.length or num < 0: raise OperationError(space.w_ValueError, space.wrap( "Getting element %d of array sized %d" % (num, self.length))) - return wrap_value(space, get_elem, self.ll_array, num, self.of) + return wrap_value(space, get_elem, self.ll_array, num, self.shape.of) getitem.unwrap_spec = ['self', ObjSpace, int] def getbuffer(space, self): @@ -69,9 +91,10 @@ if self.ll_array: lltype.free(self.ll_array, flavor='raw') -def descr_new_array_instance(space, w_type, of, w_size_or_iterable): - return space.wrap(W_ArrayInstance(space, of, w_size_or_iterable)) -descr_new_array_instance.unwrap_spec = [ObjSpace, W_Root, str, W_Root] +def descr_new_array_instance(space, w_type, w_shape, w_size_or_iterable): + w_shape = space.interp_w(W_Array, w_shape) + return space.wrap(W_ArrayInstance(space, w_shape, w_size_or_iterable)) +descr_new_array_instance.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root] W_ArrayInstance.typedef = TypeDef( 'ArrayInstance', @@ -80,3 +103,5 @@ __getitem__ = interp2app(W_ArrayInstance.getitem), buffer = GetSetProperty(W_ArrayInstance.getbuffer), ) + + Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 6 12:51:16 2008 @@ -263,9 +263,10 @@ raises(ValueError, "_ffi.Structure(['x1', 'xx'])") raises(ValueError, _ffi.Structure, [('x1', 'xx')]) raises(ValueError, "_ffi.Array('xx')") - A = _ffi.Array('i') - A.of = 'xx' - raises(ValueError, 'A(1)') + # XXX I don't think this should be allowed at all: + #A = _ffi.Array('i') + #A.of = 'xx' + #raises(ValueError, 'A(1)') def test_implicit_structure(self): skip("Does not work yet") From arigo at codespeak.net Sun Jan 6 13:22:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Jan 2008 13:22:30 +0100 (CET) Subject: [pypy-svn] r50370 - in pypy/dist/pypy: module/posix objspace/std translator/goal Message-ID: <20080106122230.5D59A16847B@codespeak.net> Author: arigo Date: Sun Jan 6 13:22:28 2008 New Revision: 50370 Modified: pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/objspace/std/smallintobject.py pypy/dist/pypy/translator/goal/ann_override.py Log: Annotation fixes: don't use space.wrap(tuple). Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Sun Jan 6 13:22:28 2008 @@ -207,7 +207,11 @@ except OSError, e: raise wrap_oserror(space, e) else: - return space.wrap(times) + return space.newtuple([space.wrap(times[0]), + space.wrap(times[1]), + space.wrap(times[2]), + space.wrap(times[3]), + space.wrap(times[4])]) times.unwrap_spec = [ObjSpace] def system(space, cmd): Modified: pypy/dist/pypy/objspace/std/smallintobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/smallintobject.py (original) +++ pypy/dist/pypy/objspace/std/smallintobject.py Sun Jan 6 13:22:28 2008 @@ -181,7 +181,7 @@ space.wrap("integer modulo")) # no overflow possible m = x % y - return space.wrap((z,m)) + return space.newtuple([space.wrap(z), space.wrap(m)]) def div__SmallInt_SmallInt(space, w_int1, w_int2): return _floordiv(space, w_int1, w_int2) Modified: pypy/dist/pypy/translator/goal/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/goal/ann_override.py (original) +++ pypy/dist/pypy/translator/goal/ann_override.py Sun Jan 6 13:22:28 2008 @@ -52,6 +52,9 @@ typ = Wrappable else: assert not issubclass(typ, Wrappable) + assert typ != tuple, "space.wrap(tuple) forbidden; use newtuple()" + assert typ != list, "space.wrap(list) forbidden; use newlist()" + assert typ != dict, "space.wrap(dict) forbidden; use newdict()" if args_s[0].is_constant() and args_s[1].is_constant(): if typ in (str, bool, int, float): space = args_s[0].const From arigo at codespeak.net Sun Jan 6 14:00:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 6 Jan 2008 14:00:18 +0100 (CET) Subject: [pypy-svn] r50371 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080106130018.16D1B16845B@codespeak.net> Author: arigo Date: Sun Jan 6 14:00:17 2008 New Revision: 50371 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: * avoid these strange "raise RuntimeError" here and there. * a test showing a messy problem and a comment at the place which is buggy. Not fixed. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Sun Jan 6 14:00:17 2008 @@ -10,6 +10,10 @@ from pypy.tool import stdlib_opcode as pythonopcode from pypy.interpreter.error import OperationError +class InternalCompilerError(Exception): + """Something went wrong in the ast compiler.""" + + class BlockSet: """A Set implementation specific to Blocks it uses Block.bid as keys to underlying dict""" @@ -285,6 +289,11 @@ if index[c.bid] < i: forward_p = 0 for inst in b.insts: + # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + # other bytecodes need the same logic, but + # trying to do that throws this function into + # an infinite loop. Sad sad sad. + # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX if inst.op == 'JUMP_FORWARD': assert isinstance(inst, InstrBlock) if inst.block == c: @@ -494,7 +503,7 @@ self.makeByteCode() if self.stage == DONE: return self.newCodeObject() - raise RuntimeError, "inconsistent PyFlowGraph state" + raise InternalCompilerError("inconsistent PyFlowGraph state") def dump(self, io=None): if io: @@ -621,6 +630,8 @@ abspos = begin[block] if opname in self.hasjrel: offset = abspos - pc - 3 + if offset < 0: + raise InternalCompilerError("unexpected backward jump") inst.intval = offset else: inst.intval = abspos @@ -872,6 +883,7 @@ def twobyte(val): """Convert an int argument into high and low bytes""" assert isinstance(val,int) + assert 0 <= val < 65536 hi = val // 256 lo = val % 256 return hi, lo Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py Sun Jan 6 14:00:17 2008 @@ -198,7 +198,7 @@ tree.accept(s) def get_module(self): - raise RuntimeError, "should be implemented by subclasses" + raise NotImplementedError("should be implemented by subclasses") # Next five methods handle name access def storeName(self, name, lineno): @@ -239,8 +239,9 @@ else: self.emitop(prefix + '_NAME', name) else: - raise RuntimeError, "unsupported scope for var %s in %s: %d" % \ - (name, self.scope.name, scope) + raise pyassem.InternalCompilerError( + "unsupported scope for var %s in %s: %d" % + (name, self.scope.name, scope)) def _implicitNameOp(self, prefix, name): """Emit name ops for names generated implicitly by for loops @@ -1567,7 +1568,7 @@ self.main = main_visitor def default(self, node): - raise RuntimeError("shouldn't arrive here!") + raise pyassem.InternalCompilerError("shouldn't arrive here!") def visitName(self, node ): self.main.loadName(node.varname, node.lineno) @@ -1589,7 +1590,7 @@ self.main = main_visitor def default(self, node): - raise RuntimeError("shouldn't arrive here!") + raise pyassem.InternalCompilerError("shouldn't arrive here!") def visitName(self, node): self.main.storeName(node.varname, node.lineno) Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Sun Jan 6 14:00:17 2008 @@ -362,3 +362,93 @@ yield self.st, "x = sum(n+2 for n in (6, 1, 2))", 'x', 15 yield self.st, "k=2; x = sum(n+2 for n in [6, 1, k])", 'x', 15 yield self.st, "k=2; x = sum(n+2 for n in (6, 1, k))", 'x', 15 + + def test_pprint(self): + # a larger example that showed a bug with jumps + # over more than 256 bytes + decl = py.code.Source(""" + def _safe_repr(object, context, maxlevels, level): + typ = _type(object) + if typ is str: + if 'locale' not in _sys.modules: + return repr(object), True, False + if "'" in object and '"' not in object: + closure = '"' + quotes = {'"': '\\"'} + else: + closure = "'" + quotes = {"'": "\\'"} + qget = quotes.get + sio = _StringIO() + write = sio.write + for char in object: + if char.isalpha(): + write(char) + else: + write(qget(char, repr(char)[1:-1])) + return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False + + r = getattr(typ, "__repr__", None) + if issubclass(typ, dict) and r is dict.__repr__: + if not object: + return "{}", True, False + objid = _id(object) + if maxlevels and level > maxlevels: + return "{...}", False, objid in context + if objid in context: + return _recursion(object), False, True + context[objid] = 1 + readable = True + recursive = False + components = [] + append = components.append + level += 1 + saferepr = _safe_repr + for k, v in object.iteritems(): + krepr, kreadable, krecur = saferepr(k, context, maxlevels, level) + vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level) + append("%s: %s" % (krepr, vrepr)) + readable = readable and kreadable and vreadable + if krecur or vrecur: + recursive = True + del context[objid] + return "{%s}" % _commajoin(components), readable, recursive + + if (issubclass(typ, list) and r is list.__repr__) or \ + (issubclass(typ, tuple) and r is tuple.__repr__): + if issubclass(typ, list): + if not object: + return "[]", True, False + format = "[%s]" + elif _len(object) == 1: + format = "(%s,)" + else: + if not object: + return "()", True, False + format = "(%s)" + objid = _id(object) + if maxlevels and level > maxlevels: + return format % "...", False, objid in context + if objid in context: + return _recursion(object), False, True + context[objid] = 1 + readable = True + recursive = False + components = [] + append = components.append + level += 1 + for o in object: + orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level) + append(orepr) + if not oreadable: + readable = False + if orecur: + recursive = True + del context[objid] + return format % _commajoin(components), readable, recursive + + rep = repr(object) + return rep, (rep and not rep.startswith('<')), False + """) + decl = str(decl) + '\n' + yield self.st, decl + 'x=_safe_repr([5], {}, 3, 0)', 'x', '[5]' From cfbolz at codespeak.net Sun Jan 6 14:39:47 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 14:39:47 +0100 (CET) Subject: [pypy-svn] r50372 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080106133947.B96D51684CE@codespeak.net> Author: cfbolz Date: Sun Jan 6 14:39:46 2008 New Revision: 50372 Added: pypy/branch/applevel-ctypes2/pypy/module/_ffi/error.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: don't free structures automatically ever. Also don't keep alive the field inits Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/__init__.py Sun Jan 6 14:39:46 2008 @@ -23,4 +23,5 @@ } appleveldefs = { + 'SegfaultException' : 'error.SegfaultException', } Added: pypy/branch/applevel-ctypes2/pypy/module/_ffi/error.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/error.py Sun Jan 6 14:39:46 2008 @@ -0,0 +1,2 @@ +class SegfaultException(Exception): + pass Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py Sun Jan 6 14:39:46 2008 @@ -103,6 +103,11 @@ return rffi.cast(TP, pos)[0] cast_pos._annspecialcase_ = 'specialize:arg(2)' +def segfault_exception(space, reason): + w_mod = space.getbuiltinmodule("_ffi") + w_exception = space.getattr(w_mod, space.wrap("SegfaultException")) + return OperationError(w_exception, space.wrap(reason)) + class W_StructureInstance(Wrappable): def __init__(self, space, shape, w_address, fieldinits_w): self.free_afterwards = False @@ -110,15 +115,12 @@ if w_address is not None: self.ll_buffer = rffi.cast(rffi.VOIDP, space.int_w(w_address)) else: - self.free_afterwards = True self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, shape.size, flavor='raw', zero=True) if fieldinits_w: - self.fieldinits_w = fieldinits_w for field, w_value in fieldinits_w.iteritems(): self.setattr(space, field, w_value) - else: - self.fieldinits_w = None + def getindex(self, space, attr): try: @@ -128,29 +130,38 @@ "C Structure has no attribute %s" % attr)) def getattr(self, space, attr): + if not self.ll_buffer: + raise segfault_exception(space, "accessing NULL pointer") i = self.getindex(space, attr) _, c = self.shape.fields[i] return wrap_value(space, cast_pos, self, i, c) getattr.unwrap_spec = ['self', ObjSpace, str] def setattr(self, space, attr, w_value): + if not self.ll_buffer: + raise segfault_exception(space, "accessing NULL pointer") i = self.getindex(space, attr) _, c = self.shape.fields[i] unwrap_value(space, push_field, self, i, c, w_value, None) setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] - def __del__(self): - if self.free_afterwards: - lltype.free(self.ll_buffer, flavor='raw') + def free(self, space): + if not self.ll_buffer: + raise segfault_exception(space, "freeing NULL pointer") + lltype.free(self.ll_buffer, flavor='raw') + self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO) + free.unwrap_spec = ['self', ObjSpace] def getbuffer(space, self): return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) + W_StructureInstance.typedef = TypeDef( 'StructureInstance', __getattr__ = interp2app(W_StructureInstance.getattr), __setattr__ = interp2app(W_StructureInstance.setattr), buffer = GetSetProperty(W_StructureInstance.getbuffer), + free = interp2app(W_StructureInstance.free), ) W_StructureInstance.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 6 14:39:46 2008 @@ -187,6 +187,7 @@ assert structure.tv_usec != struct2.tv_usec assert (structure.tv_sec == struct2.tv_sec) or (structure.tv_sec == struct2.tv_sec - 1) raises(AttributeError, "structure.xxx") + structure.free() def test_structreturn(self): import _ffi @@ -208,17 +209,24 @@ assert t.tm_year == 70 assert t.tm_sec == 1 assert t.tm_min == 2 + x.free() def test_nested_structures(self): import _ffi lib = _ffi.CDLL(self.lib_name) inner = lib.ptr("inner_struct_elem", ['P'], 'c') X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) - x = X(next=X(next=None, x3='x'), x1=1, x2=2, x3='x') + next = X(next=None, x3='x') + x = X(next=next, x1=1, x2=2, x3='x') assert X(x.next).x3 == 'x' + x.free() + next.free() + # XXX isn't that leaking memory? create_double_struct = lib.ptr("create_double_struct", [], 'P') x = create_double_struct() - assert X(X(x).next).x2 == 3 + x = X(x) + assert X(x.next).x2 == 3 + def test_array(self): import _ffi @@ -250,6 +258,8 @@ ptr1 = get_array_elem_s(a, 0) assert ptr1 is None assert X(get_array_elem_s(a, 1)).x2 == 3 + assert get_array_elem_s(a, 1) == x.buffer + x.free() def test_bad_parameters(self): import _ffi @@ -263,10 +273,6 @@ raises(ValueError, "_ffi.Structure(['x1', 'xx'])") raises(ValueError, _ffi.Structure, [('x1', 'xx')]) raises(ValueError, "_ffi.Array('xx')") - # XXX I don't think this should be allowed at all: - #A = _ffi.Array('i') - #A.of = 'xx' - #raises(ValueError, 'A(1)') def test_implicit_structure(self): skip("Does not work yet") @@ -318,6 +324,7 @@ assert x.value1 == 3 raises(AttributeError, "x.foo") raises(AttributeError, "x.foo = 1") + x.free() def test_sizes_and_alignments(self): import _ffi From cfbolz at codespeak.net Sun Jan 6 14:43:18 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 14:43:18 +0100 (CET) Subject: [pypy-svn] r50373 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080106134318.867C01684DA@codespeak.net> Author: cfbolz Date: Sun Jan 6 14:43:18 2008 New Revision: 50373 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: same for arrays: don't free automatically Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Sun Jan 6 14:43:18 2008 @@ -87,9 +87,13 @@ def getbuffer(space, self): return space.wrap(rffi.cast(rffi.INT, self.ll_array)) - def __del__(self): - if self.ll_array: - lltype.free(self.ll_array, flavor='raw') + def free(self, space): + if not self.ll_array: + raise segfault_exception(space, "freeing NULL pointer") + lltype.free(self.ll_array, flavor='raw') + self.ll_array = lltype.nullptr(rffi.VOIDP.TO) + free.unwrap_spec = ['self', ObjSpace] + def descr_new_array_instance(space, w_type, w_shape, w_size_or_iterable): w_shape = space.interp_w(W_Array, w_shape) @@ -102,6 +106,7 @@ __setitem__ = interp2app(W_ArrayInstance.setitem), __getitem__ = interp2app(W_ArrayInstance.getitem), buffer = GetSetProperty(W_ArrayInstance.getbuffer), + free = interp2app(W_ArrayInstance.free), ) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 6 14:43:18 2008 @@ -242,9 +242,11 @@ assert get_array_elem(a, 7) == 1 assert get_array_elem(a, 6) == 2 assert a[3] == 0 + a.free() a = A([1, 2, 3, 4]) assert get_array_elem(a, 0) == 1 assert a[3] == 4 + a.free() def test_array_of_structure(self): import _ffi @@ -260,6 +262,7 @@ assert X(get_array_elem_s(a, 1)).x2 == 3 assert get_array_elem_s(a, 1) == x.buffer x.free() + a.free() def test_bad_parameters(self): import _ffi From cfbolz at codespeak.net Sun Jan 6 14:48:42 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 14:48:42 +0100 (CET) Subject: [pypy-svn] r50374 - pypy/branch/applevel-ctypes2/pypy/module/_ffi/test Message-ID: <20080106134842.052DF1683FD@codespeak.net> Author: cfbolz Date: Sun Jan 6 14:48:42 2008 New Revision: 50374 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: free all memory Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 6 14:48:42 2008 @@ -46,6 +46,12 @@ x2->x2 = 3; return x1; } + + void free_double_struct(struct x* x1) + { + free(x1->next); + free(x1); + } const char *static_str = "xxxxxx"; @@ -221,11 +227,12 @@ assert X(x.next).x3 == 'x' x.free() next.free() - # XXX isn't that leaking memory? create_double_struct = lib.ptr("create_double_struct", [], 'P') x = create_double_struct() x = X(x) assert X(x.next).x2 == 3 + free_double_struct = lib.ptr("free_double_struct", ['P'], None) + free_double_struct(x) def test_array(self): From vinogradov at codespeak.net Sun Jan 6 15:11:59 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Sun, 6 Jan 2008 15:11:59 +0100 (CET) Subject: [pypy-svn] r50375 - in pypy/branch/ghop-ropes-classes/pypy/rlib: . test Message-ID: <20080106141159.7C4411684DD@codespeak.net> Author: vinogradov Date: Sun Jan 6 15:11:57 2008 New Revision: 50375 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: Rewrite Rope __add__ algorithm Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Sun Jan 6 15:11:57 2008 @@ -23,10 +23,20 @@ return self.__class__(rope.multiply(self._node, n)) def __add__(self, other): + if isinstance(self, RopeUnicode) or isinstance(other, RopeUnicode): - return RopeUnicode(self._node + other._node) + if isinstance(self, RopeUnicode): + result = self._node.flatten_unicode() + else: + result = self.decode('utf-8')._node.flatten_unicode() + + if isinstance(other, RopeUnicode): + result += other._node.flatten_unicode() + else: + result += other.decode('utf-8')._node.flatten_unicode() + return RopeUnicode(result) else: - return self.__class__(self._node + other._node) + return RopeString(self._node.flatten_string() + other._node.flatten_string()) def __getitem__(self, index): if isinstance(index, int): @@ -66,7 +76,7 @@ def encode(self, encoding, errors='strict'): s = self._node.flatten_string() result = s.encode(encoding, errors) - return RopeUnicode(result) + return RopeString(result) def decode(self, codepage, errors='strict'): s = self._node.flatten_string() Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Sun Jan 6 15:11:57 2008 @@ -127,6 +127,7 @@ s1 = self.conststr("\xff") s2 = self.constunicode("a") py.test.raises(UnicodeDecodeError, "s1 + s2") + py.test.raises(UnicodeDecodeError, "s2 + s1") class TestPythonCoercion(AbstractTestCoercion): conststr = str From vinogradov at codespeak.net Sun Jan 6 15:23:53 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Sun, 6 Jan 2008 15:23:53 +0100 (CET) Subject: [pypy-svn] r50376 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080106142353.1F8A61684CE@codespeak.net> Author: vinogradov Date: Sun Jan 6 15:23:52 2008 New Revision: 50376 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Rewrite RopeString decode method. Use optimized rope.str_decode_* functions Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Sun Jan 6 15:23:52 2008 @@ -79,8 +79,18 @@ return RopeString(result) def decode(self, codepage, errors='strict'): - s = self._node.flatten_string() - result = s.decode(codepage, errors) + result = None + + if codepage == 'utf-8': + result = rope.str_decode_utf8(self._node) + if codepage == 'latin1': + result = rope.str_decode_latin1(self._node) + if codepage == 'ascii': + result = rope.str_decode_ascii(self._node) + + if result == None: + s = self._node.flatten_string() + result = s.decode(codepage, errors) return RopeUnicode(result) def getchar(self,index): From vinogradov at codespeak.net Sun Jan 6 15:28:58 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Sun, 6 Jan 2008 15:28:58 +0100 (CET) Subject: [pypy-svn] r50378 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080106142858.4936E1684CE@codespeak.net> Author: vinogradov Date: Sun Jan 6 15:28:57 2008 New Revision: 50378 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Rewrite RopeUnicode encode method. Use optimized rope.unicode_encode_* functions Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Sun Jan 6 15:28:57 2008 @@ -83,7 +83,7 @@ if codepage == 'utf-8': result = rope.str_decode_utf8(self._node) - if codepage == 'latin1': + if codepage == 'latin-1': result = rope.str_decode_latin1(self._node) if codepage == 'ascii': result = rope.str_decode_ascii(self._node) @@ -125,8 +125,18 @@ return RopeUnicodeIterator(self._node) def encode(self, encoding, errors = 'strict'): - s = self._node.flatten_unicode() - result = s.encode(encoding, errors) + result = None + + if encoding == 'utf8': + result = rope.unicode_encode_utf8(self._node) + if encoding == 'latin-1': + result = rope.unicode_encode_latin1(self._node) + if encoding == 'ascii': + result = rope.unicode_encode_ascii(self._node) + + if result == None: + s = self._node.flatten_unicode() + result = s.encode(encoding, errors) return RopeString(result) def decode(self, codepage, errors = 'strict'): From cfbolz at codespeak.net Sun Jan 6 15:40:58 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 15:40:58 +0100 (CET) Subject: [pypy-svn] r50379 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080106144058.D9B4B168457@codespeak.net> Author: cfbolz Date: Sun Jan 6 15:40:58 2008 New Revision: 50379 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: a mean test that shows what is wrong with the current __add__ implementation ? this should pass quickly Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Sun Jan 6 15:40:58 2008 @@ -58,13 +58,19 @@ assert hash(s1) == hash(s2) -class TestString(AbstractTest): +class AbstractRopeTest(object): + def test_add_long(self): + s1 = self.const("a") + s2 = self.const("b") * (2 ** 30) + s3 = s1 + s2 + +class TestString(AbstractTest, AbstractRopeTest): const = RopeString class TestPythonString(AbstractTest): const = str -class TestUnicode(AbstractTest): +class TestUnicode(AbstractTest, AbstractRopeTest): const = RopeUnicode class TestPythonUnicode(AbstractTest): From vinogradov at codespeak.net Sun Jan 6 15:42:18 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Sun, 6 Jan 2008 15:42:18 +0100 (CET) Subject: [pypy-svn] r50380 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080106144218.B387D168457@codespeak.net> Author: vinogradov Date: Sun Jan 6 15:42:18 2008 New Revision: 50380 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Romeve usage of flatten_string/unicode from Rope __add__ algorithm Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Sun Jan 6 15:42:18 2008 @@ -26,17 +26,17 @@ if isinstance(self, RopeUnicode) or isinstance(other, RopeUnicode): if isinstance(self, RopeUnicode): - result = self._node.flatten_unicode() + result = self._node else: - result = self.decode('utf-8')._node.flatten_unicode() + result = self.decode('utf-8')._node if isinstance(other, RopeUnicode): - result += other._node.flatten_unicode() + result += other._node else: - result += other.decode('utf-8')._node.flatten_unicode() + result += other.decode('utf-8')._node return RopeUnicode(result) else: - return RopeString(self._node.flatten_string() + other._node.flatten_string()) + return RopeString(self._node + other._node) def __getitem__(self, index): if isinstance(index, int): From cfbolz at codespeak.net Sun Jan 6 15:42:46 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 15:42:46 +0100 (CET) Subject: [pypy-svn] r50381 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080106144246.42C5D168457@codespeak.net> Author: cfbolz Date: Sun Jan 6 15:42:45 2008 New Revision: 50381 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: test a bit more Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Sun Jan 6 15:42:45 2008 @@ -63,6 +63,11 @@ s1 = self.const("a") s2 = self.const("b") * (2 ** 30) s3 = s1 + s2 + assert len(s3) == 2 ** 30 + 1 + assert s3[0] == "a" + assert s3[1] == "b" + assert s3[5] == "b" + assert s3[-1] == "b" class TestString(AbstractTest, AbstractRopeTest): const = RopeString @@ -142,3 +147,13 @@ class TestRopesCoercion(AbstractTestCoercion): conststr = RopeString constunicode = RopeUnicode + + def test_add_coercion_long(self): + s1 = self.conststr("a") + s2 = self.constunicode("b") * (2 ** 30) + s3 = s1 + s2 + assert len(s3) == 2 ** 30 + 1 + assert s3[0] == "a" + assert s3[1] == "b" + assert s3[5] == "b" + assert s3[-1] == "b" From ericvrp at codespeak.net Sun Jan 6 15:42:59 2008 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 6 Jan 2008 15:42:59 +0100 (CET) Subject: [pypy-svn] r50382 - pypy/dist/pypy/translator/microbench Message-ID: <20080106144259.72A10168457@codespeak.net> Author: ericvrp Date: Sun Jan 6 15:42:59 2008 New Revision: 50382 Modified: pypy/dist/pypy/translator/microbench/microbench.py Log: fix typo Modified: pypy/dist/pypy/translator/microbench/microbench.py ============================================================================== --- pypy/dist/pypy/translator/microbench/microbench.py (original) +++ pypy/dist/pypy/translator/microbench/microbench.py Sun Jan 6 15:42:59 2008 @@ -1,8 +1,8 @@ #!/usr/bin/env python """This script computes the relative performance between python -implementations on a set of microbenchmarks. The script usally is started -with "./microbench.py python ./pypy" where pypy is a symlink to you pypy exectable.""" +implementations on a set of microbenchmarks. The script usually is started +with "./microbench.py python ./pypy" where pypy is a symlink to your pypy executable.""" import os, time, sys @@ -96,3 +96,4 @@ if not executables: run(test_cases, fmt) + From fijal at codespeak.net Sun Jan 6 15:45:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 15:45:47 +0100 (CET) Subject: [pypy-svn] r50383 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080106144547.464B31684DD@codespeak.net> Author: fijal Date: Sun Jan 6 15:45:46 2008 New Revision: 50383 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/ (props changed) pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py Log: * fix one test number * add pointer tests Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py Sun Jan 6 15:45:46 2008 @@ -81,7 +81,6 @@ def test_byref(self): # calling byref returns also a PyCArgObject instance - py.test.skip("Works by accident") for t in signed_types + unsigned_types + float_types: parm = byref(t()) assert ArgType == type(parm) Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Sun Jan 6 15:45:46 2008 @@ -0,0 +1,178 @@ +import py +from ctypes import * + +ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, + c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float] +python_types = [int, int, int, int, int, long, + int, long, long, long, float, float] + +def setup_module(mod): + f = py.magic.autopath().dirpath().join('_ctypes_test.so') + if not f.check(): + raise Exception("Grab your _ctypes_test.so from your python lib directory and copy it here") + mod._ctypes_test = str(f) + +class TestPointers: + + def test_pointer_crash(self): + + class A(POINTER(c_ulong)): + pass + + POINTER(c_ulong)(c_ulong(22)) + # Pointer can't set contents: has no _type_ + py.test.raises(TypeError, A, c_ulong(33)) + + def test_pass_pointers(self): + dll = CDLL(_ctypes_test) + func = dll._testfunc_p_p + func.restype = c_long + + i = c_int(12345678) +## func.argtypes = (POINTER(c_int),) + address = func(byref(i)) + assert c_int.from_address(address).value == 12345678 + + func.restype = POINTER(c_int) + res = func(pointer(i)) + assert res.contents.value == 12345678 + assert res[0] == 12345678 + + def test_change_pointers(self): + dll = CDLL(_ctypes_test) + func = dll._testfunc_p_p + + i = c_int(87654) + func.restype = POINTER(c_int) + func.argtypes = (POINTER(c_int),) + + res = func(pointer(i)) + assert res[0] == 87654 + assert res.contents.value == 87654 + + # C code: *res = 54345 + res[0] = 54345 + assert i.value == 54345 + + # C code: + # int x = 12321; + # res = &x + res.contents = c_int(12321) + assert i.value == 54345 + + def test_callbacks_with_pointers(self): + # a function type receiving a pointer + PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int)) + + self.result = [] + + def func(arg): + for i in range(10): +## print arg[i], + self.result.append(arg[i]) +## print + return 0 + callback = PROTOTYPE(func) + + dll = CDLL(_ctypes_test) + # This function expects a function pointer, + # and calls this with an integer pointer as parameter. + # The int pointer points to a table containing the numbers 1..10 + doit = dll._testfunc_callback_with_pointer + +## i = c_int(42) +## callback(byref(i)) +## self.failUnless(i.value == 84) + + doit(callback) +## print self.result + doit(callback) +## print self.result + + def test_basics(self): + from operator import delitem + for ct, pt in zip(ctype_types, python_types): + i = ct(42) + p = pointer(i) +## print type(p.contents), ct + assert type(p.contents) is ct + # p.contents is the same as p[0] +## print p.contents +## self.failUnless(p.contents == 42) +## self.failUnless(p[0] == 42) + + py.test.raises(TypeError, delitem, p, 0) + + def test_from_address(self): + from array import array + a = array('i', [100, 200, 300, 400, 500]) + addr = a.buffer_info()[0] + + p = POINTER(POINTER(c_int)) +## print dir(p) +## print p.from_address +## print p.from_address(addr)[0][0] + + def test_other(self): + class Table(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int)] + + pt = pointer(Table(1, 2, 3)) + + assert pt.contents.a == 1 + assert pt.contents.b == 2 + assert pt.contents.c == 3 + + pt.contents.c = 33 + + from ctypes import _pointer_type_cache + del _pointer_type_cache[Table] + + def test_basic(self): + p = pointer(c_int(42)) + # Although a pointer can be indexed, it ha no length + py.test.raises(TypeError, len, p) + assert p[0] == 42 + assert p.contents.value == 42 + + def test_charpp(self): + """Test that a character pointer-to-pointer is correctly passed""" + dll = CDLL(_ctypes_test) + func = dll._testfunc_c_p_p + func.restype = c_char_p + argv = (c_char_p * 2)() + argc = c_int( 2 ) + argv[0] = 'hello' + argv[1] = 'world' + result = func( byref(argc), argv ) + assert result == 'world', result + + def test_bug_1467852(self): + # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 + x = c_int(5) + dummy = [] + for i in range(32000): + dummy.append(c_int(i)) + y = c_int(6) + p = pointer(x) + pp = pointer(p) + q = pointer(y) + pp[0] = q # <== + assert p[0] == 6 + def test_c_void_p(self): + # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470 + if sizeof(c_void_p) == 4: + assert c_void_p(0xFFFFFFFFL).value == c_void_p(-1).value + assert c_void_p(0xFFFFFFFFFFFFFFFFL).value == c_void_p(-1).value + elif sizeof(c_void_p) == 8: + assert c_void_p(0xFFFFFFFFL).value == 0xFFFFFFFFL + assert c_void_p(0xFFFFFFFFFFFFFFFFL).value == c_void_p(-1).value + assert c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFFL).value == c_void_p(-1).value + + py.test.raises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted + py.test.raises(TypeError, c_void_p, object()) # nor other objects + +if __name__ == '__main__': + unittest.main() From fijal at codespeak.net Sun Jan 6 15:46:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 15:46:18 +0100 (CET) Subject: [pypy-svn] r50384 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080106144618.E64DC1684DD@codespeak.net> Author: fijal Date: Sun Jan 6 15:46:18 2008 New Revision: 50384 Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: Wack until one test_pointer passes. (There is some deep problem right now though) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Sun Jan 6 15:46:18 2008 @@ -1,10 +1,11 @@ -from _ctypes.dummy import Union, Structure, Array, _Pointer -from _ctypes.dummy import ArgumentError, byref, addressof +from _ctypes.dummy import Union, Structure, Array +from _ctypes.dummy import ArgumentError, addressof from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr from _ctypes.dummy import _cast_addr -from _ctypes.primitive import _SimpleCData, sizeof, alignment +from _ctypes.primitive import _SimpleCData, sizeof, alignment, byref +from _ctypes.pointer import _Pointer from _ctypes.function import CFuncPtr from _ctypes.dll import dlopen Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py Sun Jan 6 15:46:18 2008 @@ -10,21 +10,12 @@ class Array(type): pass -class PointerType(type): - pass - -class _Pointer(object): - __metaclass__ = PointerType - - class ArgumentError(Exception): pass - def dummyfunc(*args, **kwargs): return None -byref = dummyfunc addressof = dummyfunc alignment = dummyfunc resize = dummyfunc Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Sun Jan 6 15:46:18 2008 @@ -0,0 +1,30 @@ + +import _ffi + +class PointerType(type): + def __new__(self, name, cls, typedict): + d = dict( + size = _ffi.sizeof('P'), + align = _ffi.alignment('P'), + length = 1 + ) + # XXX check if typedict['_type_'] is any sane + # XXX remember about paramfunc + obj = type.__new__(self, name, cls, typedict) + for k, v in d.iteritems(): + setattr(obj, k, v) + return obj + +class _Pointer(object): + __metaclass__ = PointerType + + def __init__(self, value=None): + if value is None: + self.is_null = True + else: + self.value = value + # we should later check why exactly this is the case + try: + type(self).__dict__['_type_'] + except KeyError: + raise TypeError("%s has no _type_" % self.__class__) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Sun Jan 6 15:46:18 2008 @@ -11,7 +11,6 @@ 'z': 's', } - TP_TO_DEFAULT = { 'c': 0, 'b': 0, @@ -78,3 +77,9 @@ def alignment(tp): return _ffi.alignment(tp._type_) + +def byref(cdata): + from ctypes import pointer + if not isinstance(cdata, _SimpleCData): + raise TypeError("expected CData instance") + return pointer(cdata) From cfbolz at codespeak.net Sun Jan 6 15:46:46 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 15:46:46 +0100 (CET) Subject: [pypy-svn] r50385 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080106144646.7A4491684DD@codespeak.net> Author: cfbolz Date: Sun Jan 6 15:46:46 2008 New Revision: 50385 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: another small failing test Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Sun Jan 6 15:46:46 2008 @@ -10,6 +10,11 @@ assert s[1] == self.const("b") assert s[2] == self.const("c") + def test_negative_index(self): + s = self.const("abc") * 10000 + for i in range(len(s)): + assert s[-i - 1] == s[len(s) - 1 - i] + def test_add(self): s1 = self.const("abc") s2 = self.const("def") From vinogradov at codespeak.net Sun Jan 6 15:52:36 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Sun, 6 Jan 2008 15:52:36 +0100 (CET) Subject: [pypy-svn] r50386 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080106145236.DCD801684E7@codespeak.net> Author: vinogradov Date: Sun Jan 6 15:52:36 2008 New Revision: 50386 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Fix __getitem__ for negative index Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Sun Jan 6 15:52:36 2008 @@ -40,7 +40,10 @@ def __getitem__(self, index): if isinstance(index, int): - return self.getchar(index) + if index >= 0: + return self.getchar(index) + else: + return self.getchar(len(self) + index) if isinstance(index, slice): start, stop, step = index.indices(self._node.length()) return self.__class__(rope.getslice(self._node, start, stop, step)) From cfbolz at codespeak.net Sun Jan 6 15:54:32 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 15:54:32 +0100 (CET) Subject: [pypy-svn] r50387 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080106145432.2CF1C1684E7@codespeak.net> Author: cfbolz Date: Sun Jan 6 15:54:31 2008 New Revision: 50387 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: remove tabs Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Sun Jan 6 15:54:31 2008 @@ -34,7 +34,7 @@ result += other._node else: result += other.decode('utf-8')._node - return RopeUnicode(result) + return RopeUnicode(result) else: return RopeString(self._node + other._node) @@ -64,7 +64,7 @@ def __init__(self, s): if isinstance(s, str): self._node = rope.LiteralStringNode(s) - elif isinstance(s, rope.StringNode): + elif isinstance(s, rope.StringNode): self._node = s def __eq__(self, other): @@ -91,7 +91,7 @@ if codepage == 'ascii': result = rope.str_decode_ascii(self._node) - if result == None: + if result == None: s = self._node.flatten_string() result = s.decode(codepage, errors) return RopeUnicode(result) @@ -136,7 +136,6 @@ result = rope.unicode_encode_latin1(self._node) if encoding == 'ascii': result = rope.unicode_encode_ascii(self._node) - if result == None: s = self._node.flatten_unicode() result = s.encode(encoding, errors) From cfbolz at codespeak.net Sun Jan 6 15:59:46 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 15:59:46 +0100 (CET) Subject: [pypy-svn] r50388 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080106145946.BEC691684CE@codespeak.net> Author: cfbolz Date: Sun Jan 6 15:59:46 2008 New Revision: 50388 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: remove outdated comment Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Sun Jan 6 15:59:46 2008 @@ -48,8 +48,6 @@ assert not s1 != s2 def test_iteration(self): - # XXX rope iteration is working but should use a custom iterator - # e.g. define an __iter__ method s = self.const("abcdefghijkl") i = 0 for c in s: From fijal at codespeak.net Sun Jan 6 16:15:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 16:15:27 +0100 (CET) Subject: [pypy-svn] r50389 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080106151527.269B61684DA@codespeak.net> Author: fijal Date: Sun Jan 6 16:15:23 2008 New Revision: 50389 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/_ctypes_test.c Log: A bit of peeling on top of _ctypes_test.c - strike down some details about -lpython Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/_ctypes_test.c ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/_ctypes_test.c Sun Jan 6 16:15:23 2008 @@ -0,0 +1,514 @@ +/***************************************************************** + This file should be kept compatible with Python 2.3, see PEP 291. + *****************************************************************/ + + +#include + +/* + Backwards compatibility: + Python2.2 used LONG_LONG instead of PY_LONG_LONG +*/ +#if defined(HAVE_LONG_LONG) && !defined(PY_LONG_LONG) +#define PY_LONG_LONG LONG_LONG +#endif + +#ifdef MS_WIN32 +#include +#endif + +#if defined(MS_WIN32) || defined(__CYGWIN__) +#define EXPORT(x) __declspec(dllexport) x +#else +#define EXPORT(x) x +#endif + +/* some functions handy for testing */ + +EXPORT(char *)my_strtok(char *token, const char *delim) +{ + return strtok(token, delim); +} + +EXPORT(char *)my_strchr(const char *s, int c) +{ + return strchr(s, c); +} + + +EXPORT(double) my_sqrt(double a) +{ + return sqrt(a); +} + +EXPORT(void) my_qsort(void *base, size_t num, size_t width, int(*compare)(const void*, const void*)) +{ + qsort(base, num, width, compare); +} + +EXPORT(int *) _testfunc_ai8(int a[8]) +{ + return a; +} + +EXPORT(void) _testfunc_v(int a, int b, int *presult) +{ + *presult = a + b; +} + +EXPORT(int) _testfunc_i_bhilfd(signed char b, short h, int i, long l, float f, double d) +{ +/* printf("_testfunc_i_bhilfd got %d %d %d %ld %f %f\n", + b, h, i, l, f, d); +*/ + return (int)(b + h + i + l + f + d); +} + +EXPORT(float) _testfunc_f_bhilfd(signed char b, short h, int i, long l, float f, double d) +{ +/* printf("_testfunc_f_bhilfd got %d %d %d %ld %f %f\n", + b, h, i, l, f, d); +*/ + return (float)(b + h + i + l + f + d); +} + +EXPORT(double) _testfunc_d_bhilfd(signed char b, short h, int i, long l, float f, double d) +{ +/* printf("_testfunc_d_bhilfd got %d %d %d %ld %f %f\n", + b, h, i, l, f, d); +*/ + return (double)(b + h + i + l + f + d); +} + +EXPORT(char *) _testfunc_p_p(void *s) +{ + return (char *)s; +} + +EXPORT(void *) _testfunc_c_p_p(int *argcp, char **argv) +{ + return argv[(*argcp)-1]; +} + +EXPORT(void *) get_strchr(void) +{ + return (void *)strchr; +} + +EXPORT(char *) my_strdup(char *src) +{ + char *dst = (char *)malloc(strlen(src)+1); + if (!dst) + return NULL; + strcpy(dst, src); + return dst; +} + +EXPORT(void)my_free(void *ptr) +{ + free(ptr); +} + +#ifdef HAVE_WCHAR_H +EXPORT(wchar_t *) my_wcsdup(wchar_t *src) +{ + size_t len = wcslen(src); + wchar_t *ptr = (wchar_t *)malloc((len + 1) * sizeof(wchar_t)); + if (ptr == NULL) + return NULL; + memcpy(ptr, src, (len+1) * sizeof(wchar_t)); + return ptr; +} + +EXPORT(size_t) my_wcslen(wchar_t *src) +{ + return wcslen(src); +} +#endif + +#ifndef MS_WIN32 +# ifndef __stdcall +# define __stdcall /* */ +# endif +#endif + +typedef struct { + int (*c)(int, int); + int (__stdcall *s)(int, int); +} FUNCS; + +EXPORT(int) _testfunc_callfuncp(FUNCS *fp) +{ + fp->c(1, 2); + fp->s(3, 4); + return 0; +} + +EXPORT(int) _testfunc_deref_pointer(int *pi) +{ + return *pi; +} + +#ifdef MS_WIN32 +EXPORT(int) _testfunc_piunk(IUnknown FAR *piunk) +{ + piunk->lpVtbl->AddRef(piunk); + return piunk->lpVtbl->Release(piunk); +} +#endif + +EXPORT(int) _testfunc_callback_with_pointer(int (*func)(int *)) +{ + int table[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + return (*func)(table); +} + +#ifdef HAVE_LONG_LONG +EXPORT(PY_LONG_LONG) _testfunc_q_bhilfdq(signed char b, short h, int i, long l, float f, + double d, PY_LONG_LONG q) +{ + return (PY_LONG_LONG)(b + h + i + l + f + d + q); +} + +EXPORT(PY_LONG_LONG) _testfunc_q_bhilfd(signed char b, short h, int i, long l, float f, double d) +{ + return (PY_LONG_LONG)(b + h + i + l + f + d); +} + +EXPORT(int) _testfunc_callback_i_if(int value, int (*func)(int)) +{ + int sum = 0; + while (value != 0) { + sum += func(value); + value /= 2; + } + return sum; +} + +EXPORT(PY_LONG_LONG) _testfunc_callback_q_qf(PY_LONG_LONG value, + PY_LONG_LONG (*func)(PY_LONG_LONG)) +{ + PY_LONG_LONG sum = 0; + + while (value != 0) { + sum += func(value); + value /= 2; + } + return sum; +} + +#endif + +typedef struct { + char *name; + char *value; +} SPAM; + +typedef struct { + char *name; + int num_spams; + SPAM *spams; +} EGG; + +SPAM my_spams[2] = { + { "name1", "value1" }, + { "name2", "value2" }, +}; + +EGG my_eggs[1] = { + { "first egg", 1, my_spams } +}; + +EXPORT(int) getSPAMANDEGGS(EGG **eggs) +{ + *eggs = my_eggs; + return 1; +} + +typedef struct tagpoint { + int x; + int y; +} point; + +EXPORT(int) _testfunc_byval(point in, point *pout) +{ + if (pout) { + pout->x = in.x; + pout->y = in.y; + } + return in.x + in.y; +} + +EXPORT (int) an_integer = 42; + +EXPORT(int) get_an_integer(void) +{ + return an_integer; +} + +EXPORT(double) +integrate(double a, double b, double (*f)(double), long nstep) +{ + double x, sum=0.0, dx=(b-a)/(double)nstep; + for(x=a+0.5*dx; (b-x)*(x-a)>0.0; x+=dx) + sum += f(x); + return sum/(double)nstep; +} + +typedef struct { + void (*initialize)(void *(*)(int), void(*)(void *)); +} xxx_library; + +static void _xxx_init(void *(*Xalloc)(int), void (*Xfree)(void *)) +{ + void *ptr; + + printf("_xxx_init got %p %p\n", Xalloc, Xfree); + printf("calling\n"); + ptr = Xalloc(32); + Xfree(ptr); + printf("calls done, ptr was %p\n", ptr); +} + +xxx_library _xxx_lib = { + _xxx_init +}; + +EXPORT(xxx_library) *library_get(void) +{ + return &_xxx_lib; +} + +#ifdef MS_WIN32 +/* See Don Box (german), pp 79ff. */ +EXPORT(void) GetString(BSTR *pbstr) +{ + *pbstr = SysAllocString(L"Goodbye!"); +} +#endif + +EXPORT(void) _py_func_si(char *s, int i) +{ +} + +EXPORT(void) _py_func(void) +{ +} + +EXPORT(PY_LONG_LONG) last_tf_arg_s; +EXPORT(unsigned PY_LONG_LONG) last_tf_arg_u; + +struct BITS { + int A: 1, B:2, C:3, D:4, E: 5, F: 6, G: 7, H: 8, I: 9; + short M: 1, N: 2, O: 3, P: 4, Q: 5, R: 6, S: 7; +}; + +DL_EXPORT(void) set_bitfields(struct BITS *bits, char name, int value) +{ + switch (name) { + case 'A': bits->A = value; break; + case 'B': bits->B = value; break; + case 'C': bits->C = value; break; + case 'D': bits->D = value; break; + case 'E': bits->E = value; break; + case 'F': bits->F = value; break; + case 'G': bits->G = value; break; + case 'H': bits->H = value; break; + case 'I': bits->I = value; break; + + case 'M': bits->M = value; break; + case 'N': bits->N = value; break; + case 'O': bits->O = value; break; + case 'P': bits->P = value; break; + case 'Q': bits->Q = value; break; + case 'R': bits->R = value; break; + case 'S': bits->S = value; break; + } +} + +DL_EXPORT(int) unpack_bitfields(struct BITS *bits, char name) +{ + switch (name) { + case 'A': return bits->A; + case 'B': return bits->B; + case 'C': return bits->C; + case 'D': return bits->D; + case 'E': return bits->E; + case 'F': return bits->F; + case 'G': return bits->G; + case 'H': return bits->H; + case 'I': return bits->I; + + case 'M': return bits->M; + case 'N': return bits->N; + case 'O': return bits->O; + case 'P': return bits->P; + case 'Q': return bits->Q; + case 'R': return bits->R; + case 'S': return bits->S; + } + return 0; +} + +#define S last_tf_arg_s = (PY_LONG_LONG)c +#define U last_tf_arg_u = (unsigned PY_LONG_LONG)c + +EXPORT(signed char) tf_b(signed char c) { S; return c/3; } +EXPORT(unsigned char) tf_B(unsigned char c) { U; return c/3; } +EXPORT(short) tf_h(short c) { S; return c/3; } +EXPORT(unsigned short) tf_H(unsigned short c) { U; return c/3; } +EXPORT(int) tf_i(int c) { S; return c/3; } +EXPORT(unsigned int) tf_I(unsigned int c) { U; return c/3; } +EXPORT(long) tf_l(long c) { S; return c/3; } +EXPORT(unsigned long) tf_L(unsigned long c) { U; return c/3; } +EXPORT(PY_LONG_LONG) tf_q(PY_LONG_LONG c) { S; return c/3; } +EXPORT(unsigned PY_LONG_LONG) tf_Q(unsigned PY_LONG_LONG c) { U; return c/3; } +EXPORT(float) tf_f(float c) { S; return c/3; } +EXPORT(double) tf_d(double c) { S; return c/3; } + +#ifdef MS_WIN32 +EXPORT(signed char) __stdcall s_tf_b(signed char c) { S; return c/3; } +EXPORT(unsigned char) __stdcall s_tf_B(unsigned char c) { U; return c/3; } +EXPORT(short) __stdcall s_tf_h(short c) { S; return c/3; } +EXPORT(unsigned short) __stdcall s_tf_H(unsigned short c) { U; return c/3; } +EXPORT(int) __stdcall s_tf_i(int c) { S; return c/3; } +EXPORT(unsigned int) __stdcall s_tf_I(unsigned int c) { U; return c/3; } +EXPORT(long) __stdcall s_tf_l(long c) { S; return c/3; } +EXPORT(unsigned long) __stdcall s_tf_L(unsigned long c) { U; return c/3; } +EXPORT(PY_LONG_LONG) __stdcall s_tf_q(PY_LONG_LONG c) { S; return c/3; } +EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_Q(unsigned PY_LONG_LONG c) { U; return c/3; } +EXPORT(float) __stdcall s_tf_f(float c) { S; return c/3; } +EXPORT(double) __stdcall s_tf_d(double c) { S; return c/3; } +#endif +/*******/ + +EXPORT(signed char) tf_bb(signed char x, signed char c) { S; return c/3; } +EXPORT(unsigned char) tf_bB(signed char x, unsigned char c) { U; return c/3; } +EXPORT(short) tf_bh(signed char x, short c) { S; return c/3; } +EXPORT(unsigned short) tf_bH(signed char x, unsigned short c) { U; return c/3; } +EXPORT(int) tf_bi(signed char x, int c) { S; return c/3; } +EXPORT(unsigned int) tf_bI(signed char x, unsigned int c) { U; return c/3; } +EXPORT(long) tf_bl(signed char x, long c) { S; return c/3; } +EXPORT(unsigned long) tf_bL(signed char x, unsigned long c) { U; return c/3; } +EXPORT(PY_LONG_LONG) tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; } +EXPORT(unsigned PY_LONG_LONG) tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; } +EXPORT(float) tf_bf(signed char x, float c) { S; return c/3; } +EXPORT(double) tf_bd(signed char x, double c) { S; return c/3; } +EXPORT(void) tv_i(int c) { S; return; } + +#ifdef MS_WIN32 +EXPORT(signed char) __stdcall s_tf_bb(signed char x, signed char c) { S; return c/3; } +EXPORT(unsigned char) __stdcall s_tf_bB(signed char x, unsigned char c) { U; return c/3; } +EXPORT(short) __stdcall s_tf_bh(signed char x, short c) { S; return c/3; } +EXPORT(unsigned short) __stdcall s_tf_bH(signed char x, unsigned short c) { U; return c/3; } +EXPORT(int) __stdcall s_tf_bi(signed char x, int c) { S; return c/3; } +EXPORT(unsigned int) __stdcall s_tf_bI(signed char x, unsigned int c) { U; return c/3; } +EXPORT(long) __stdcall s_tf_bl(signed char x, long c) { S; return c/3; } +EXPORT(unsigned long) __stdcall s_tf_bL(signed char x, unsigned long c) { U; return c/3; } +EXPORT(PY_LONG_LONG) __stdcall s_tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; } +EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; } +EXPORT(float) __stdcall s_tf_bf(signed char x, float c) { S; return c/3; } +EXPORT(double) __stdcall s_tf_bd(signed char x, double c) { S; return c/3; } +EXPORT(void) __stdcall s_tv_i(int c) { S; return; } +#endif + +/********/ + +#ifndef MS_WIN32 + +typedef struct { + long x; + long y; +} POINT; + +typedef struct { + long left; + long top; + long right; + long bottom; +} RECT; + +#endif + +EXPORT(int) PointInRect(RECT *prc, POINT pt) +{ + if (pt.x < prc->left) + return 0; + if (pt.x > prc->right) + return 0; + if (pt.y < prc->top) + return 0; + if (pt.y > prc->bottom) + return 0; + return 1; +} + +typedef struct { + short x; + short y; +} S2H; + +EXPORT(S2H) ret_2h_func(S2H inp) +{ + inp.x *= 2; + inp.y *= 3; + return inp; +} + +typedef struct { + int a, b, c, d, e, f, g, h; +} S8I; + +EXPORT(S8I) ret_8i_func(S8I inp) +{ + inp.a *= 2; + inp.b *= 3; + inp.c *= 4; + inp.d *= 5; + inp.e *= 6; + inp.f *= 7; + inp.g *= 8; + inp.h *= 9; + return inp; +} + +EXPORT(int) GetRectangle(int flag, RECT *prect) +{ + if (flag == 0) + return 0; + prect->left = (int)flag; + prect->top = (int)flag + 1; + prect->right = (int)flag + 2; + prect->bottom = (int)flag + 3; + return 1; +} + +EXPORT(void) TwoOutArgs(int a, int *pi, int b, int *pj) +{ + *pi += a; + *pj += b; +} + +#ifdef MS_WIN32 +EXPORT(S2H) __stdcall s_ret_2h_func(S2H inp) { return ret_2h_func(inp); } +EXPORT(S8I) __stdcall s_ret_8i_func(S8I inp) { return ret_8i_func(inp); } +#endif + +#ifdef MS_WIN32 +/* Should port this */ +#include +#include + +EXPORT (HRESULT) KeepObject(IUnknown *punk) +{ + static IUnknown *pobj; + if (punk) + punk->lpVtbl->AddRef(punk); + if (pobj) + pobj->lpVtbl->Release(pobj); + pobj = punk; + return S_OK; +} + +#endif From fijal at codespeak.net Sun Jan 6 16:47:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 16:47:02 +0100 (CET) Subject: [pypy-svn] r50390 - pypy/dist/pypy/translator/tool Message-ID: <20080106154702.3BF89168469@codespeak.net> Author: fijal Date: Sun Jan 6 16:47:01 2008 New Revision: 50390 Modified: pypy/dist/pypy/translator/tool/graphpage.py Log: Another helper for actually getting a graph instead of showing it. Modified: pypy/dist/pypy/translator/tool/graphpage.py ============================================================================== --- pypy/dist/pypy/translator/tool/graphpage.py (original) +++ pypy/dist/pypy/translator/tool/graphpage.py Sun Jan 6 16:47:01 2008 @@ -449,6 +449,28 @@ else: raise TypeError("try_show(%r object)" % (type(obj).__name__,)) +def try_get_functiongraph(obj): + if isinstance(obj, FunctionGraph): + obj.show() + elif isinstance(obj, Link): + try_show(obj.prevblock) + elif isinstance(obj, Block): + import gc + pending = [obj] # pending blocks + seen = {obj: True, None: True} + for x in pending: + for y in gc.get_referrers(x): + if isinstance(y, FunctionGraph): + return y + elif isinstance(y, Link): + block = y.prevblock + if block not in seen: + pending.append(block) + seen[block] = True + return pending + else: + raise TypeError("try_get_functiongraph(%r object)" % (type(obj).__name__,)) + class IncompleteGraph: name = '(incomplete graph)' tag = None From fijal at codespeak.net Sun Jan 6 16:48:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 16:48:07 +0100 (CET) Subject: [pypy-svn] r50391 - pypy/dist/pypy/module/bz2 Message-ID: <20080106154807.95B8C168469@codespeak.net> Author: fijal Date: Sun Jan 6 16:48:07 2008 New Revision: 50391 Modified: pypy/dist/pypy/module/bz2/interp_bz2.py Log: Fix for 64 bit. Modified: pypy/dist/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/dist/pypy/module/bz2/interp_bz2.py (original) +++ pypy/dist/pypy/module/bz2/interp_bz2.py Sun Jan 6 16:48:07 2008 @@ -8,6 +8,7 @@ from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app, Arguments from pypy.rlib.streamio import Stream from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.rarithmetic import intmask import sys class CConfig: @@ -417,7 +418,7 @@ raise OperationError(self.space.w_ValueError, self.space.wrap("compresslevel must be between 1 and 9")) - bzerror = BZ2_bzCompressInit(self.bzs, compresslevel, 0, 0) + bzerror = intmask(BZ2_bzCompressInit(self.bzs, compresslevel, 0, 0)) if bzerror != BZ_OK: _catch_bz2_error(self.space, bzerror) From fijal at codespeak.net Sun Jan 6 17:15:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 17:15:28 +0100 (CET) Subject: [pypy-svn] r50394 - pypy/dist/pypy/rlib Message-ID: <20080106161528.552DD168476@codespeak.net> Author: fijal Date: Sun Jan 6 17:15:28 2008 New Revision: 50394 Modified: pypy/dist/pypy/rlib/rsocket.py Log: Another 64bit-related fix Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Sun Jan 6 17:15:28 2008 @@ -538,7 +538,7 @@ if hasattr(_c, 'fcntl'): def _setblocking(self, block): - delay_flag = _c.fcntl(self.fd, _c.F_GETFL, 0) + delay_flag = intmask(_c.fcntl(self.fd, _c.F_GETFL, 0)) if block: delay_flag &= ~_c.O_NONBLOCK else: From fijal at codespeak.net Sun Jan 6 17:25:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 6 Jan 2008 17:25:51 +0100 (CET) Subject: [pypy-svn] r50407 - pypy/dist/pypy/rlib Message-ID: <20080106162551.D542E168480@codespeak.net> Author: fijal Date: Sun Jan 6 17:25:51 2008 New Revision: 50407 Modified: pypy/dist/pypy/rlib/rsocket.py Log: Try to fix socketnum, not sure if this is it. Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Sun Jan 6 17:25:51 2008 @@ -523,7 +523,7 @@ fd = _c.INVALID_SOCKET def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0): """Create a new socket.""" - fd = _c.socket(family, type, proto) + fd = intmask(_c.socket(family, type, proto)) if _c.invalid_socket(fd): raise self.error_handler() # PLAT RISCOS From cfbolz at codespeak.net Sun Jan 6 19:12:31 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 19:12:31 +0100 (CET) Subject: [pypy-svn] r50408 - pypy/dist/pypy/rlib/parsing Message-ID: <20080106181231.7F0921684E7@codespeak.net> Author: cfbolz Date: Sun Jan 6 19:12:29 2008 New Revision: 50408 Modified: pypy/dist/pypy/rlib/parsing/lexer.py Log: "typo" of sorts Modified: pypy/dist/pypy/rlib/parsing/lexer.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/lexer.py (original) +++ pypy/dist/pypy/rlib/parsing/lexer.py Sun Jan 6 19:12:29 2008 @@ -184,7 +184,7 @@ self.ignore = ignore def ignore_token(self, state): - return self.automaton.names[self.last_matched_state] in self.ignore + return self.automaton.names[state] in self.ignore def make_token(self, index, state, text, eof=False): source_pos = SourcePos(index, self.lineno, self.columnno) From cfbolz at codespeak.net Sun Jan 6 21:54:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 6 Jan 2008 21:54:45 +0100 (CET) Subject: [pypy-svn] r50409 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080106205445.C9BB4168460@codespeak.net> Author: cfbolz Date: Sun Jan 6 21:54:44 2008 New Revision: 50409 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: another failing test Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Sun Jan 6 21:54:44 2008 @@ -59,6 +59,10 @@ s1 = self.const("abc") s2 = self.const("abc") assert hash(s1) == hash(s2) + + def test_str(self): + s1 = self.const("abc") + assert str(s1) == "abc" class AbstractRopeTest(object): From vinogradov at codespeak.net Mon Jan 7 06:27:39 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Mon, 7 Jan 2008 06:27:39 +0100 (CET) Subject: [pypy-svn] r50413 - pypy/branch/ghop-ropes-classes/pypy/rlib Message-ID: <20080107052739.9AE2216844D@codespeak.net> Author: vinogradov Date: Mon Jan 7 06:27:37 2008 New Revision: 50413 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Log: Implement __str__ method for RopeString and RopeUnicode Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/ropewrapper.py Mon Jan 7 06:27:37 2008 @@ -76,6 +76,9 @@ def __iter__(self): return RopeStringIterator(self._node) + def __str__(self): + return self._node.flatten_string() + def encode(self, encoding, errors='strict'): s = self._node.flatten_string() result = s.encode(encoding, errors) @@ -127,6 +130,9 @@ def __iter__(self): return RopeUnicodeIterator(self._node) + def __str__(self): + return self._node.flatten_unicode() + def encode(self, encoding, errors = 'strict'): result = None From arigo at codespeak.net Mon Jan 7 14:21:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 14:21:22 +0100 (CET) Subject: [pypy-svn] r50422 - pypy/dist/pypy/objspace/std Message-ID: <20080107132122.B85DE168430@codespeak.net> Author: arigo Date: Mon Jan 7 14:21:21 2008 New Revision: 50422 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: Fix an XXX before I forget about it. Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Mon Jan 7 14:21:21 2008 @@ -622,12 +622,17 @@ self.setitem(w_obj, w_key, w_value) def getindex_w(self, w_obj, w_exception, objdescr=None): - # performance shortcut for W_IntObject - # XXX we should also have one for W_SmallIntObject, I guess - if type(w_obj) is W_IntObject: - return w_obj.intval + # Performance shortcut for the common case of w_obj being an int. + # If withsmallint is disabled, we check for W_IntObject. + # If withsmallint is enabled, we only check for W_SmallIntObject - it's + # probably not useful to have a shortcut for W_IntObject at all then. + if self.config.objspace.std.withsmallint: + if type(w_obj) is W_SmallIntObject: + return w_obj.intval else: - return ObjSpace.getindex_w(self, w_obj, w_exception, objdescr) + if type(w_obj) is W_IntObject: + return w_obj.intval + return ObjSpace.getindex_w(self, w_obj, w_exception, objdescr) def call_method(self, w_obj, methname, *arg_w): if self.config.objspace.opcodes.CALL_METHOD: From arigo at codespeak.net Mon Jan 7 16:25:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 16:25:36 +0100 (CET) Subject: [pypy-svn] r50425 - pypy/branch/simpler-pyassem Message-ID: <20080107152536.7D4A616842E@codespeak.net> Author: arigo Date: Mon Jan 7 16:25:35 2008 New Revision: 50425 Added: pypy/branch/simpler-pyassem/ - copied from r50424, pypy/branch/astcompilertests/ Log: A branch off the astcompilertests branch in which to write a simpler pyassem.py. From arigo at codespeak.net Mon Jan 7 16:26:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 16:26:36 +0100 (CET) Subject: [pypy-svn] r50426 - pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler Message-ID: <20080107152636.1410716842E@codespeak.net> Author: arigo Date: Mon Jan 7 16:26:30 2008 New Revision: 50426 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py Log: Start pyassem from scratch, copy-pasting some bits of the old one. Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 16:26:30 2008 @@ -1,449 +1,19 @@ -"""A flow graph representation for Python bytecode""" - -import sys - -from pypy.interpreter.astcompiler import misc, ast from pypy.interpreter.astcompiler.consts \ import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS from pypy.interpreter.pycode import PyCode -from pypy.interpreter.baseobjspace import W_Root from pypy.tool import stdlib_opcode as pythonopcode from pypy.interpreter.error import OperationError + class InternalCompilerError(Exception): """Something went wrong in the ast compiler.""" -class BlockSet: - """A Set implementation specific to Blocks - it uses Block.bid as keys to underlying dict""" - def __init__(self): - self.elts = {} - def __len__(self): - return len(self.elts) - def __contains__(self, elt): - return elt.bid in self.elts - def add(self, elt): - self.elts[elt.bid] = elt - def elements(self): - return self.elts.values() - def has_elt(self, elt): - return elt.bid in self.elts - def remove(self, elt): - del self.elts[elt.bid] - def copy(self): - c = BlockSet() - c.elts.update(self.elts) - return c - - -class Instr: - has_arg = False - - def __init__(self, op): - self.op = op - -class InstrWithArg(Instr): - has_arg = True - -class InstrName(InstrWithArg): - def __init__(self, inst, name): - Instr.__init__(self, inst) - self.name = name - - def getArg(self): - "NOT_RPYTHON" - return self.name - -class InstrInt(InstrWithArg): - def __init__(self, inst, intval): - Instr.__init__(self, inst) - self.intval = intval - - def getArg(self): - "NOT_RPYTHON" - return self.intval - -class InstrBlock(InstrWithArg): - def __init__(self, inst, block): - Instr.__init__(self, inst) - self.block = block - - def getArg(self): - "NOT_RPYTHON" - return self.block - -class InstrObj(InstrWithArg): - def __init__(self, inst, obj): - Instr.__init__(self, inst) - self.obj = obj - - def getArg(self): - "NOT_RPYTHON" - return self.obj - -class InstrCode(InstrWithArg): - def __init__(self, inst, gen): - Instr.__init__(self, inst) - self.gen = gen - - def getArg(self): - "NOT_RPYTHON" - return self.gen - -class FlowGraph: - def __init__(self, space): - self.space = space - self.current = self.entry = Block(space) - self.exit = Block(space,"exit") - self.blocks = BlockSet() - self.blocks.add(self.entry) - self.blocks.add(self.exit) - - def startBlock(self, block): - if self._debug: - if self.current: - print "end", repr(self.current) - print " next", self.current.next - print " ", self.current.get_children() - print repr(block) - assert block is not None - self.current = block - - def nextBlock(self, block=None): - # XXX think we need to specify when there is implicit transfer - # from one block to the next. might be better to represent this - # with explicit JUMP_ABSOLUTE instructions that are optimized - # out when they are unnecessary. - # - # I think this strategy works: each block has a child - # designated as "next" which is returned as the last of the - # children. because the nodes in a graph are emitted in - # reverse post order, the "next" block will always be emitted - # immediately after its parent. - # Worry: maintaining this invariant could be tricky - if block is None: - block = self.newBlock() - - # Note: If the current block ends with an unconditional - # control transfer, then it is incorrect to add an implicit - # transfer to the block graph. The current code requires - # these edges to get the blocks emitted in the right order, - # however. :-( If a client needs to remove these edges, call - # pruneEdges(). - - self.current.addNext(block) - self.startBlock(block) - - def newBlock(self): - b = Block(self.space) - self.blocks.add(b) - return b - - def startExitBlock(self): - self.startBlock(self.exit) - - _debug = 0 - - def _enable_debug(self): - self._debug = 1 - - def _disable_debug(self): - self._debug = 0 - - def emit(self, inst): - if self._debug: - print "\t", inst - if inst in ['RETURN_VALUE', 'YIELD_VALUE']: - self.current.addOutEdge(self.exit) - self.current.emit( Instr(inst) ) - - #def emitop(self, inst, arg ): - # if self._debug: - # print "\t", inst, arg - # self.current.emit( (inst,arg) ) - - def emitop_obj(self, inst, obj ): - if self._debug: - print "\t", inst, repr(obj) - self.current.emit( InstrObj(inst,obj) ) - - def emitop_code(self, inst, obj ): - if self._debug: - print "\t", inst, repr(obj) - self.current.emit( InstrCode(inst, obj) ) - - def emitop_int(self, inst, intval ): - if self._debug: - print "\t", inst, intval - assert isinstance(intval,int) - self.current.emit( InstrInt(inst,intval) ) - - def emitop_block(self, inst, block): - if self._debug: - print "\t", inst, block - assert isinstance(block, Block) - self.current.addOutEdge( block ) - self.current.emit( InstrBlock(inst,block) ) - - def emitop_name(self, inst, name ): - if self._debug: - print "\t", inst, name - assert isinstance(name,str) - self.current.emit( InstrName(inst,name) ) - - def getBlocksInOrder(self): - """Return the blocks in reverse postorder - - i.e. each node appears before all of its successors - """ - # TODO: What we need here is a topological sort that - - - # XXX make sure every node that doesn't have an explicit next - # is set so that next points to exit - for b in self.blocks.elements(): - if b is self.exit: - continue - if not b.next: - b.addNext(self.exit) - order = dfs_postorder(self.entry, {}) - order.reverse() - self.fixupOrder(order, self.exit) - # hack alert - if not self.exit in order: - order.append(self.exit) - - return order - - def fixupOrder(self, blocks, default_next): - """Fixup bad order introduced by DFS.""" - - # XXX This is a total mess. There must be a better way to get - # the code blocks in the right order. - - self.fixupOrderHonorNext(blocks, default_next) - self.fixupOrderForward(blocks, default_next) - - def fixupOrderHonorNext(self, blocks, default_next): - """Fix one problem with DFS. - - The DFS uses child block, but doesn't know about the special - "next" block. As a result, the DFS can order blocks so that a - block isn't next to the right block for implicit control - transfers. - """ - new_blocks = blocks - blocks = blocks[:] - del new_blocks[:] - i = 0 - while i < len(blocks) - 1: - b = blocks[i] - n = blocks[i + 1] - i += 1 - new_blocks.append(b) - if not b.next or b.next[0] == default_next or b.next[0] == n: - continue - # The blocks are in the wrong order. Find the chain of - # blocks to insert where they belong. - cur = b - chain = [] - elt = cur - while elt.next and elt.next[0] != default_next: - chain.append(elt.next[0]) - elt = elt.next[0] - # Now remove the blocks in the chain from the current - # block list, so that they can be re-inserted. - for b in chain: - for j in range(i + 1, len(blocks)): - if blocks[j] == b: - del blocks[j] - break - else: - assert False, "Can't find block" - - new_blocks.extend(chain) - if i == len(blocks) - 1: - new_blocks.append(blocks[i]) - - def fixupOrderForward(self, blocks, default_next): - """Make sure all JUMP_FORWARDs jump forward""" - index = {} - chains = [] - cur = [] - for b in blocks: - index[b.bid] = len(chains) - cur.append(b) - if b.next and b.next[0] == default_next: - chains.append(cur) - cur = [] - chains.append(cur) - - while 1: - constraints = [] - - for i in range(len(chains)): - l = chains[i] - for b in l: - for c in b.get_children(): - if index[c.bid] < i: - forward_p = 0 - for inst in b.insts: - # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - # other bytecodes need the same logic, but - # trying to do that throws this function into - # an infinite loop. Sad sad sad. - # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - if inst.op == 'JUMP_FORWARD': - assert isinstance(inst, InstrBlock) - if inst.block == c: - forward_p = 1 - if not forward_p: - continue - constraints.append((index[c.bid], i)) - - if not constraints: - break - - # XXX just do one for now - # do swaps to get things in the right order - goes_before, a_chain = constraints[0] - assert a_chain > goes_before >= 0 - c = chains[a_chain] - del chains[a_chain] - chains.insert(goes_before, c) - - del blocks[:] - for c in chains: - for b in c: - blocks.append(b) - - def getBlocks(self): - return self.blocks.elements() - - def getRoot(self): - """Return nodes appropriate for use with dominator""" - return self.entry - - def getContainedGraphs(self): - l = [] - for b in self.getBlocks(): - l.extend(b.getContainedGraphs()) - return l - -def dfs_postorder(b, seen): - """Depth-first search of tree rooted at b, return in postorder""" - order = [] - seen[b.bid] = b - for c in b.get_children(): - if c.bid in seen: - continue - order = order + dfs_postorder(c, seen) - order.append(b) - return order - -BlockCounter = misc.Counter(0) - -class Block: - - def __init__(self, space, label=''): - self.insts = [] - self.inEdges = BlockSet() - self.outEdges = BlockSet() - self.label = label - self.bid = BlockCounter.next() - self.next = [] - self.space = space - - def __repr__(self): - if self.label: - return "" % (self.label, self.bid) - else: - return "" % (self.bid) - - def __str__(self): - insts = [ str(i) for i in self.insts ] - return "" % (self.label, self.bid, - '\n'.join(insts)) - - def emit(self, inst): - op = inst.op - if op[:4] == 'JUMP': - assert isinstance(inst, InstrBlock) - self.outEdges.add(inst.block) -## if op=="LOAD_CONST": -## assert isinstance( inst[1], W_Root ) or hasattr( inst[1], 'getCode') - self.insts.append( inst ) - - def getInstructions(self): - return self.insts - - def addInEdge(self, block): - self.inEdges.add(block) - - def addOutEdge(self, block): - self.outEdges.add(block) - - def addNext(self, block): - self.next.append(block) - assert len(self.next) == 1, [ str(i) for i in self.next ] - - _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE', - 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP') - - def pruneNext(self): - """Remove bogus edge for unconditional transfers - - Each block has a next edge that accounts for implicit control - transfers, e.g. from a JUMP_IF_FALSE to the block that will be - executed if the test is true. - - These edges must remain for the current assembler code to - work. If they are removed, the dfs_postorder gets things in - weird orders. However, they shouldn't be there for other - purposes, e.g. conversion to SSA form. This method will - remove the next edge when it follows an unconditional control - transfer. - """ - try: - inst = self.insts[-1] - except (IndexError, ValueError): - return - if inst.op in self._uncond_transfer: - self.next = [] - - def get_children(self): - if self.next and self.next[0].bid in self.outEdges.elts: - self.outEdges.remove(self.next[0]) - return self.outEdges.elements() + self.next - - def getContainedGraphs(self): - """Return all graphs contained within this block. - - For example, a MAKE_FUNCTION block will contain a reference to - the graph for the function body. - """ - contained = [] - for inst in self.insts: - if isinstance(inst, InstrCode): - gen = inst.gen - if gen: - contained.append(gen) - return contained - -# flags for code objects - -# the FlowGraph is transformed in place; it exists in one of these states -RAW = "RAW" -FLAT = "FLAT" -CONV = "CONV" -DONE = "DONE" - -class PyFlowGraph(FlowGraph): +class PyFlowGraph(object): def __init__(self, space, name, filename, argnames=None, optimized=0, klass=0, newlocals=0): - FlowGraph.__init__(self, space) + self.space = space if argnames is None: argnames = [] self.name = name @@ -471,8 +41,8 @@ # kinds of variables. self.closure = [] self.varnames = list(argnames) - self.stage = RAW - self.orderedblocks = [] + # The bytecode we are building, as a list of characters + self.co_code = [] def setDocstring(self, doc): self.docstring = doc @@ -492,273 +62,78 @@ def setCellVars(self, names): self.cellvars = names - def getCode(self): - """Get a Python code object""" - if self.stage == RAW: - self.computeStackDepth() - self.convertArgs() - if self.stage == CONV: - self.flattenGraph() - if self.stage == FLAT: - self.makeByteCode() - if self.stage == DONE: - return self.newCodeObject() - raise InternalCompilerError("inconsistent PyFlowGraph state") - - def dump(self, io=None): - if io: - save = sys.stdout - sys.stdout = io - pc = 0 - for t in self.insts: - opname = t.op - if opname == "SET_LINENO": - print - if not t.has_arg: - print "\t", "%3d" % pc, opname - pc = pc + 1 - else: - print "\t", "%3d" % pc, opname, t.getArg() - pc = pc + 3 - if io: - sys.stdout = save - - def _max_depth(self, depth, seen, b, d): - if b in seen: - return d - seen[b] = 1 - d = d + depth[b] - children = b.get_children() - if children: - maxd = -1 - for c in children: - childd =self._max_depth(depth, seen, c, d) - if childd > maxd: - maxd = childd - return maxd - else: - if not b.label == "exit": - return self._max_depth(depth, seen, self.exit, d) - else: - return d - - def computeStackDepth(self): - """Compute the max stack depth. - - Approach is to compute the stack effect of each basic block. - Then find the path through the code with the largest total - effect. - """ - depth = {} - exit = None - for b in self.getBlocks(): - depth[b] = findDepth(b.getInstructions()) - - seen = {} - - self.stacksize = self._max_depth( depth, seen, self.entry, 0) - - def flattenGraph(self): - """Arrange the blocks in order and resolve jumps""" - assert self.stage == CONV - self.insts = insts = [] - firstline = 0 - pc = 0 - begin = {} - end = {} - forward_refs = [] - for b in self.orderedblocks: - # Prune any setlineno before the 'implicit return' block. - if b is self.exit: - while len(insts) and insts[-1].op == "SET_LINENO": - insts.pop() - begin[b] = pc - for inst in b.getInstructions(): - if not inst.has_arg: - insts.append(inst) - pc = pc + 1 - elif inst.op != "SET_LINENO": - if inst.op in self.hasjrel: - assert isinstance(inst, InstrBlock) - # relative jump - no extended arg - block = inst.block - inst = InstrInt(inst.op, 0) - forward_refs.append( (block, inst, pc) ) - insts.append(inst) - pc = pc + 3 - elif inst.op in self.hasjabs: - # absolute jump - can be extended if backward - assert isinstance(inst, InstrBlock) - arg = inst.block - if arg in begin: - # can only extend argument if backward - offset = begin[arg] - hi = offset // 65536 - lo = offset % 65536 - if hi>0: - # extended argument - insts.append( InstrInt("EXTENDED_ARG", hi) ) - pc = pc + 3 - inst = InstrInt(inst.op, lo) - else: - inst = InstrInt(inst.op, 0) - forward_refs.append( (arg, inst, pc ) ) - insts.append(inst) - pc = pc + 3 - else: - assert isinstance(inst, InstrInt) - arg = inst.intval - # numerical arg - hi = arg // 65536 - lo = arg % 65536 - if hi>0: - # extended argument - insts.append( InstrInt("EXTENDED_ARG", hi) ) - inst.intval = lo - pc = pc + 3 - insts.append(inst) - pc = pc + 3 - else: - insts.append(inst) - if firstline == 0: - firstline = inst.intval - end[b] = pc - pc = 0 - - for block, inst, pc in forward_refs: - opname = inst.op - abspos = begin[block] - if opname in self.hasjrel: - offset = abspos - pc - 3 - if offset < 0: - raise InternalCompilerError("unexpected backward jump") - inst.intval = offset - else: - inst.intval = abspos - self.firstline = firstline - self.stage = FLAT - - hasjrel = {} - for i in pythonopcode.hasjrel: - hasjrel[pythonopcode.opname[i]] = True - hasjabs = {} - for i in pythonopcode.hasjabs: - hasjabs[pythonopcode.opname[i]] = True + # ____________________________________________________________ + # Simple instructions - def setconst(self, w_consts, w_item, value): - space = self.space - w_item_type = space.type(w_item) - w_key = space.newtuple([w_item, w_item_type]) - space.setitem(w_consts, w_key, space.wrap(value)) - - def convertArgs(self): - """Convert arguments from symbolic to concrete form""" - assert self.stage == RAW - space = self.space - self.orderedblocks = self.getBlocksInOrder() - self.setconst(self.w_consts, self.docstring, 0) - #self.const_list.insert(0, self.docstring) - self.sort_cellvars() - - for b in self.orderedblocks: - insts = b.getInstructions() - for i in range(len(insts)): - inst = insts[i] - if inst.has_arg: - opname = inst.op - conv = self._converters.get(opname, None) - if conv: - insts[i] = conv(self, inst) - self.stage = CONV + def emit(self, opname): + self.co_code.append(chr(pythonopcode.opmap[opname])) - def sort_cellvars(self): - """Sort cellvars in the order of varnames and prune from freevars. - """ - cells = {} - for name in self.cellvars: - cells[name] = 1 - self.cellvars = [name for name in self.varnames - if name in cells] - for name in self.cellvars: - del cells[name] - self.cellvars = self.cellvars + cells.keys() - self.closure = self.cellvars + self.freevars + def emitop_extended_arg(self, intval): + assert intval <= 0x7FFFFFFF + self.emit('EXTENDED_ARG') + self.co_code.append(chr((intval >> 16) & 0xFF)) + self.co_code.append(chr((intval >> 24) & 0xFF)) + return intval & 0xFFFF + emitop_extended_arg._dont_inline_ = True + + def emitop_int(self, opname, intval): + assert intval >= 0 + if opname == "SET_LINENO": + return # XXX + if intval > 0xFFFF: + intval = self.emitop_extended_arg(intval) + self.emit(opname) + self.co_code.append(chr(intval & 0xFF)) + self.co_code.append(chr(intval >> 8)) - def _lookupName(self, name, list): - """Return index of name in list, appending if necessary - """ - assert isinstance(name, str) - for i in range(len(list)): - if list[i] == name: - return i - end = len(list) - list.append(name) - return end + # ____________________________________________________________ + # Instructions with an object argument (LOAD_CONST) - def _cmpConsts(self, w_left, w_right): - space = self.space - t = space.type(w_left) - if space.is_w(t, space.type(w_right)): - if space.is_w(t, space.w_tuple): - left_len = space.int_w(space.len(w_left)) - right_len = space.int_w(space.len(w_right)) - if left_len == right_len: - for i in range(left_len): - w_lefti = space.getitem(w_left, space.wrap(i)) - w_righti = space.getitem(w_right, space.wrap(i)) - if not self._cmpConsts(w_lefti, w_righti): - return False - return True - elif space.eq_w(w_left, w_right): - return True - return False + def emitop_obj(self, opname, w_obj): + index = self._lookupConst(w_obj, self.w_consts) + self.emitop_int(opname, index) def _lookupConst(self, w_obj, w_dict): - """ - This routine uses a list instead of a dictionary, because a - dictionary can't store two different keys if the keys have the - same value but different types, e.g. 2 and 2L. The compiler - must treat these two separately, so it does an explicit type - comparison before comparing the values. - """ space = self.space w_obj_type = space.type(w_obj) + w_key = space.newtuple([w_obj, w_obj_type]) try: - w_key = space.newtuple([w_obj, w_obj_type]) - return space.int_w(space.getitem(w_dict, w_key)) + w_result = space.getitem(w_dict, w_key) except OperationError, operr: if not operr.match(space, space.w_KeyError): raise - lgt = space.int_w(space.len(w_dict)) - self.setconst(w_dict, w_obj, lgt) - return lgt - - _converters = {} + w_result = space.len(w_dict) + space.setitem(w_dict, w_key, w_result) + return space.int_w(w_result) + + # ____________________________________________________________ + # Instructions with a name argument + + def emitop_name(self, opname, name): + conv = self._converters[opname] + index = conv(self, name) + self.emitop_int(opname, index) - def _convert_LOAD_CONST(self, inst): - if isinstance(inst, InstrCode): - w_obj = inst.gen.getCode() - else: - assert isinstance(inst, InstrObj) - w_obj = inst.obj - #assert w_obj is not None - index = self._lookupConst(w_obj, self.w_consts) - return InstrInt(inst.op, index) + def _lookupName(self, name, list): + """Return index of name in list, appending if necessary + """ + # XXX use dicts instead of lists + assert isinstance(name, str) + for i in range(len(list)): + if list[i] == name: + return i + end = len(list) + list.append(name) + return end - def _convert_LOAD_FAST(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name + def _convert_LOAD_FAST(self, arg): self._lookupName(arg, self.names) - index= self._lookupName(arg, self.varnames) - return InstrInt(inst.op, index) + return self._lookupName(arg, self.varnames) _convert_STORE_FAST = _convert_LOAD_FAST _convert_DELETE_FAST = _convert_LOAD_FAST - def _convert_NAME(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name - index = self._lookupName(arg, self.names) - return InstrInt(inst.op, index) + def _convert_NAME(self, arg): + return self._lookupName(arg, self.names) _convert_LOAD_NAME = _convert_NAME _convert_STORE_NAME = _convert_NAME _convert_DELETE_NAME = _convert_NAME @@ -772,73 +147,30 @@ _convert_DELETE_GLOBAL = _convert_NAME _convert_LOOKUP_METHOD = _convert_NAME - def _convert_DEREF(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name + def _convert_DEREF(self, arg): self._lookupName(arg, self.names) - index = self._lookupName(arg, self.closure) - return InstrInt(inst.op, index) + return self._lookupName(arg, self.closure) _convert_LOAD_DEREF = _convert_DEREF _convert_STORE_DEREF = _convert_DEREF - def _convert_LOAD_CLOSURE(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name - index = self._lookupName(arg, self.closure) - return InstrInt(inst.op, index) - - _cmp = list(pythonopcode.cmp_op) - def _convert_COMPARE_OP(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name - index = self._cmp.index(arg) - return InstrInt(inst.op, index) - + def _convert_LOAD_CLOSURE(self, arg): + return self._lookupName(arg, self.closure) - # similarly for other opcodes... + _cmp = list(pythonopcode.cmp_op) + def _convert_COMPARE_OP(self, arg): + return self._cmp.index(arg) + _converters = {} for name, obj in locals().items(): if name[:9] == "_convert_": opname = name[9:] _converters[opname] = obj del name, obj, opname - def makeByteCode(self): - assert self.stage == FLAT - self.lnotab = lnotab = LineAddrTable(self.firstline) - for t in self.insts: - opname = t.op - if self._debug: - if not t.has_arg: - print "x",opname - else: - print "x",opname, t.getArg() - if not t.has_arg: - lnotab.addCode1(self.opnum[opname]) - else: - assert isinstance(t, InstrInt) - oparg = t.intval - if opname == "SET_LINENO": - lnotab.nextLine(oparg) - continue - hi, lo = twobyte(oparg) - try: - lnotab.addCode3(self.opnum[opname], lo, hi) - except ValueError: - if self._debug: - print opname, oparg - print self.opnum[opname], lo, hi - raise - self.stage = DONE - - opnum = {} - for num in range(len(pythonopcode.opname)): - opnum[pythonopcode.opname[num]] = num - # This seems to duplicate dis.opmap from opcode.opmap - del num + # ____________________________________________________________ - def newCodeObject(self): - assert self.stage == DONE + def getCode(self): + self.stacksize = 20 # XXX! if (self.flags & CO_NEWLOCALS) == 0: nlocals = 0 else: @@ -846,243 +178,27 @@ argcount = self.argcount if self.flags & CO_VARKEYWORDS: argcount = argcount - 1 - # was return new.code, now we just return the parameters and let - # the caller create the code object return PyCode( self.space, argcount, nlocals, self.stacksize, self.flags, - self.lnotab.getCode(), + ''.join(self.co_code), self.getConsts(), self.names, self.varnames, self.filename, self.name, - self.firstline, - self.lnotab.getTable(), + 1, # XXX! self.firstline, + "", # XXX! self.lnotab.getTable(), self.freevars, self.cellvars ) def getConsts(self): """Return a tuple for the const slot of the code object - - Must convert references to code (MAKE_FUNCTION) to code - objects recursively. """ space = self.space - l_w = [None] * space.int_w(space.len(self.w_consts)) keys_w = space.unpackiterable(self.w_consts) + l_w = [None] * len(keys_w) for w_key in keys_w: index = space.int_w(space.getitem(self.w_consts, w_key)) w_v = space.unpacktuple(w_key)[0] l_w[index] = w_v return l_w - -def isJump(opname): - if opname[:4] == 'JUMP': - return 1 - -def twobyte(val): - """Convert an int argument into high and low bytes""" - assert isinstance(val,int) - assert 0 <= val < 65536 - hi = val // 256 - lo = val % 256 - return hi, lo - -class LineAddrTable: - """lnotab - - This class builds the lnotab, which is documented in compile.c. - Here's a brief recap: - - For each SET_LINENO instruction after the first one, two bytes are - added to lnotab. (In some cases, multiple two-byte entries are - added.) The first byte is the distance in bytes between the - instruction for the last SET_LINENO and the current SET_LINENO. - The second byte is offset in line numbers. If either offset is - greater than 255, multiple two-byte entries are added -- see - compile.c for the delicate details. - """ - - def __init__(self, firstline): - self.code = [] - self.codeOffset = 0 - self.firstline = firstline - self.lastline = firstline - self.lastoff = 0 - self.lnotab = [] - - def addCode1(self, op ): - self.code.append(chr(op)) - self.codeOffset = self.codeOffset + 1 - - def addCode3(self, op, hi, lo): - self.code.append(chr(op)) - self.code.append(chr(hi)) - self.code.append(chr(lo)) - self.codeOffset = self.codeOffset + 3 - - def nextLine(self, lineno): - # compute deltas - addr = self.codeOffset - self.lastoff - line = lineno - self.lastline - # Python assumes that lineno always increases with - # increasing bytecode address (lnotab is unsigned char). - # Depending on when SET_LINENO instructions are emitted - # this is not always true. Consider the code: - # a = (1, - # b) - # In the bytecode stream, the assignment to "a" occurs - # after the loading of "b". This works with the C Python - # compiler because it only generates a SET_LINENO instruction - # for the assignment. - if line >= 0: - push = self.lnotab.append - while addr > 255: - push(255); push(0) - addr -= 255 - while line > 255: - push(addr); push(255) - line -= 255 - addr = 0 - if addr > 0 or line > 0: - push(addr); push(line) - self.lastline = lineno - self.lastoff = self.codeOffset - - def getCode(self): - return ''.join(self.code) - - def getTable(self): - return ''.join( [ chr(i) for i in self.lnotab ] ) - - -def depth_UNPACK_SEQUENCE(count): - return count-1 -def depth_BUILD_TUPLE(count): - return -count+1 -def depth_BUILD_LIST(count): - return -count+1 -def depth_CALL_FUNCTION(argc): - hi = argc//256 - lo = argc%256 - return -(lo + hi * 2) -def depth_CALL_FUNCTION_VAR(argc): - return depth_CALL_FUNCTION(argc)-1 -def depth_CALL_FUNCTION_KW(argc): - return depth_CALL_FUNCTION(argc)-1 -def depth_CALL_FUNCTION_VAR_KW(argc): - return depth_CALL_FUNCTION(argc)-2 -def depth_CALL_METHOD(argc): - return -argc-1 -def depth_MAKE_FUNCTION(argc): - return -argc -def depth_MAKE_CLOSURE(argc): - # XXX need to account for free variables too! - return -argc -def depth_BUILD_SLICE(argc): - if argc == 2: - return -1 - elif argc == 3: - return -2 - assert False, 'Unexpected argument %s to depth_BUILD_SLICE' % argc - -def depth_DUP_TOPX(argc): - return argc - -DEPTH_OP_TRACKER = { - "UNPACK_SEQUENCE" : depth_UNPACK_SEQUENCE, - "BUILD_TUPLE" : depth_BUILD_TUPLE, - "BUILD_LIST" : depth_BUILD_LIST, - "CALL_FUNCTION" : depth_CALL_FUNCTION, - "CALL_FUNCTION_VAR" : depth_CALL_FUNCTION_VAR, - "CALL_FUNCTION_KW" : depth_CALL_FUNCTION_KW, - "CALL_FUNCTION_VAR_KW" : depth_CALL_FUNCTION_VAR_KW, - "MAKE_FUNCTION" : depth_MAKE_FUNCTION, - "MAKE_CLOSURE" : depth_MAKE_CLOSURE, - "BUILD_SLICE" : depth_BUILD_SLICE, - "DUP_TOPX" : depth_DUP_TOPX, - } - -class StackDepthTracker: - # 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! - - def findDepth(self, insts, debug=0): - depth = 0 - maxDepth = 0 - for i in insts: - opname = i.op - if debug: - print i, - delta = self.effect.get(opname, sys.maxint) - if delta != sys.maxint: - depth = depth + delta - else: - # now check patterns - for pat, pat_delta in self.patterns: - if opname[:len(pat)] == pat: - delta = pat_delta - depth = depth + delta - break - # if we still haven't found a match - if delta == sys.maxint: - meth = DEPTH_OP_TRACKER.get( opname, None ) - if meth is not None: - assert isinstance(i, InstrInt) - depth = depth + meth(i.intval) - if depth > maxDepth: - maxDepth = depth - if debug: - print depth, maxDepth - return maxDepth - - effect = { - 'POP_TOP': -1, - 'DUP_TOP': 1, - 'SLICE+1': -1, - 'SLICE+2': -1, - 'SLICE+3': -2, - 'STORE_SLICE+0': -1, - 'STORE_SLICE+1': -2, - 'STORE_SLICE+2': -2, - 'STORE_SLICE+3': -3, - 'DELETE_SLICE+0': -1, - 'DELETE_SLICE+1': -2, - 'DELETE_SLICE+2': -2, - 'DELETE_SLICE+3': -3, - 'STORE_SUBSCR': -3, - 'DELETE_SUBSCR': -2, - # PRINT_EXPR? - 'PRINT_ITEM': -1, - 'RETURN_VALUE': -1, - 'YIELD_VALUE': -1, - 'EXEC_STMT': -3, - 'BUILD_CLASS': -2, - 'STORE_NAME': -1, - 'STORE_ATTR': -2, - 'DELETE_ATTR': -1, - 'STORE_GLOBAL': -1, - 'BUILD_MAP': 1, - 'COMPARE_OP': -1, - 'STORE_FAST': -1, - 'IMPORT_STAR': -1, - 'IMPORT_NAME': 0, - 'IMPORT_FROM': 1, - 'LOAD_ATTR': 0, # unlike other loads - # close enough... - 'SETUP_EXCEPT': 3, - 'SETUP_FINALLY': 3, - 'FOR_ITER': 1, - 'WITH_CLEANUP': 3, - 'LOOKUP_METHOD': 1, - 'LIST_APPEND': -2, - } - # use pattern match - patterns = [ - ('BINARY_', -1), - ('LOAD_', 1), - ] - - -findDepth = StackDepthTracker().findDepth Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py Mon Jan 7 16:26:30 2008 @@ -161,7 +161,9 @@ return self.graph.emitop_obj( inst, obj ) def emitop_code(self, inst, gen): - return self.graph.emitop_code( inst, gen ) + code = gen.getCode() + w_code = self.space.wrap(code) + return self.graph.emitop_obj( inst, w_code ) def emitop_int(self, inst, op): assert isinstance(op, int) @@ -170,14 +172,10 @@ def emitop_block(self, inst, block): return self.graph.emitop_block( inst, block ) - def nextBlock(self, block=None ): + def nextBlock(self, block ): """graph delegation""" return self.graph.nextBlock( block ) - def startBlock(self, block ): - """graph delegation""" - return self.graph.startBlock( block ) - def newBlock(self): """graph delegation""" return self.graph.newBlock() @@ -392,11 +390,10 @@ self.set_lineno(test) nextTest = self.newBlock() test.opt_accept_jump_if(self, False, nextTest) - self.nextBlock() self.emit('POP_TOP') suite.accept( self ) self.emitop_block('JUMP_FORWARD', end) - self.startBlock(nextTest) + self.nextBlock(nextTest) self.emit('POP_TOP') if node.else_: node.else_.accept( self ) @@ -422,15 +419,14 @@ self.set_lineno(node, force=True) if is_constant_true(self.space, node.test): # "while 1:" - self.nextBlock() + pass else: node.test.opt_accept_jump_if(self, False, else_) - self.nextBlock() self.emit('POP_TOP') node.body.accept( self ) self.emitop_block('JUMP_ABSOLUTE', loop) - self.startBlock(else_) # or just the POPs if not else clause + self.nextBlock(else_) # or just the POPs if not else clause self.emit('POP_TOP') self.emit('POP_BLOCK') self.setups.pop() @@ -475,7 +471,6 @@ if kind == LOOP: self.set_lineno(node) self.emitop_block('JUMP_ABSOLUTE', block) - self.nextBlock() elif kind == EXCEPT or kind == TRY_FINALLY: self.set_lineno(node) # find the block that starts the loop @@ -492,7 +487,6 @@ if kind != LOOP: raise SyntaxError( "'continue' not properly in loop", node.lineno) self.emitop_block('CONTINUE_LOOP', loop_block) - self.nextBlock() elif kind == END_FINALLY: msg = "'continue' not supported inside 'finally' clause" raise SyntaxError( msg, node.lineno ) @@ -502,7 +496,6 @@ for child in node.nodes[:-1]: child.accept( self ) self.emitop_block(jump, end) - self.nextBlock() self.emit('POP_TOP') node.nodes[-1].accept( self ) self.nextBlock(end) @@ -585,7 +578,6 @@ self.emit('ROT_THREE') self.emitop('COMPARE_OP', op) self.emitop_block('JUMP_IF_FALSE', cleanup) - self.nextBlock() self.emit('POP_TOP') # now do the last comparison if node.ops: @@ -595,7 +587,7 @@ if len(node.ops) > 1: end = self.newBlock() self.emitop_block('JUMP_FORWARD', end) - self.startBlock(cleanup) + self.nextBlock(cleanup) self.emit('ROT_TWO') self.emit('POP_TOP') self.nextBlock(end) @@ -634,11 +626,11 @@ if cont: skip_one = self.newBlock() self.emitop_block('JUMP_FORWARD', skip_one) - self.startBlock(cont) + self.nextBlock(cont) self.emit('POP_TOP') self.nextBlock(skip_one) self.emitop_block('JUMP_ABSOLUTE', start) - self.startBlock(anchor) + self.nextBlock(anchor) self._implicitNameOp('DELETE', tmpname) self.__list_count = self.__list_count - 1 @@ -652,7 +644,6 @@ self.nextBlock(start) self.set_lineno(node, force=True) self.emitop_block('FOR_ITER', anchor) - self.nextBlock() node.assign.accept( self ) return start, anchor @@ -711,11 +702,11 @@ if cont: skip_one = self.newBlock() self.emitop_block('JUMP_FORWARD', skip_one) - self.startBlock(cont) + self.nextBlock(cont) self.emit('POP_TOP') self.nextBlock(skip_one) self.emitop_block('JUMP_ABSOLUTE', start) - self.startBlock(anchor) + self.nextBlock(anchor) self.emitop_obj('LOAD_CONST', self.space.w_None) def _visitGenExprFor(self, node): @@ -731,7 +722,6 @@ self.nextBlock(start) self.set_lineno(node, force=True) self.emitop_block('FOR_ITER', anchor) - self.nextBlock() node.assign.accept( self ) return start, anchor @@ -752,9 +742,7 @@ # XXX AssertionError appears to be special case -- it is always # loaded as a global even if there is a local name. I guess this # is a sort of renaming op. - self.nextBlock() node.test.opt_accept_jump_if(self, True, end) - self.nextBlock() self.emit('POP_TOP') self.emitop('LOAD_GLOBAL', 'AssertionError') if node.fail: @@ -795,7 +783,7 @@ self.emit('POP_BLOCK') self.setups.pop() self.emitop_block('JUMP_FORWARD', lElse) - self.startBlock(handlers) + self.nextBlock(handlers) last = len(node.handlers) - 1 next = None @@ -807,7 +795,6 @@ self.emitop('COMPARE_OP', 'exception match') next = self.newBlock() self.emitop_block('JUMP_IF_FALSE', next) - self.nextBlock() self.emit('POP_TOP') else: next = None @@ -1444,7 +1431,6 @@ return self.module def finish(self): - self.graph.startExitBlock() if not self.isLambda: self.emitop_obj('LOAD_CONST', self.space.w_None) self.emit('RETURN_VALUE') @@ -1517,7 +1503,6 @@ return self.module def finish(self): - self.graph.startExitBlock() self.emit('LOAD_LOCALS') self.emit('RETURN_VALUE') From arigo at codespeak.net Mon Jan 7 16:45:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 16:45:44 +0100 (CET) Subject: [pypy-svn] r50427 - pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler Message-ID: <20080107154544.794D3168431@codespeak.net> Author: arigo Date: Mon Jan 7 16:45:43 2008 New Revision: 50427 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Log: Labels and jumps. Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 16:45:43 2008 @@ -43,6 +43,8 @@ self.varnames = list(argnames) # The bytecode we are building, as a list of characters self.co_code = [] + # Pending label targets to fix: [(label, index-in-co_code-to-fix, abs)] + self.pending_label_fixes = [] def setDocstring(self, doc): self.docstring = doc @@ -168,9 +170,66 @@ del name, obj, opname # ____________________________________________________________ + # Labels and jumps + + def newBlock(self): + """This really returns a new label, initially not pointing anywhere.""" + return Label() + + def nextBlock(self, label): + if label.position >= 0: + raise InternalCompilerError("Label target already seen") + label.position = len(self.co_code) + + def emitop_block(self, opname, label): + absolute = opname in self.hasjabs + target = label.position + if target < 0: # unknown yet + i = len(self.co_code) + self.pending_label_fixes.append((label, i, absolute)) + target = 0xFFFF + else: + if not absolute: + # if the target was already seen, it must be backward, + # which is forbidden for these instructions + raise InternalCompilerError("%s cannot do a back jump" % + (opname,)) + self.emitop_int(opname, target) + + hasjabs = {} + for i in pythonopcode.hasjabs: + hasjabs[pythonopcode.opname[i]] = True + del i + + # ____________________________________________________________ def getCode(self): + self.computeStackDepth() + self.fixLabelTargets() + return self.newCodeObject() + + def computeStackDepth(self): self.stacksize = 20 # XXX! + + def fixLabelTargets(self): + for label, i, absolute in self.pending_label_fixes: + target = label.position + if target < 0: + raise InternalCompilerError("Label target not found") + if not absolute: + target = target - (i+3) # relative jump + if target < 0: + raise InternalCompilerError("Unexpected backward jump") + if target > 0xFFFF: + # CPython has the same limitation, for the same practical + # reason + msg = "function too large (bytecode would jump too far away)" + space = self.space + raise OperationError(space.w_SystemError, space.wrap(msg)) + self.co_code[i+1] = chr(target & 0xFF) + self.co_code[i+2] = chr(target >> 8) + + def newCodeObject(self): if (self.flags & CO_NEWLOCALS) == 0: nlocals = 0 else: @@ -202,3 +261,8 @@ w_v = space.unpacktuple(w_key)[0] l_w[index] = w_v return l_w + +# ____________________________________________________________ + +class Label(object): + position = -1 From arigo at codespeak.net Mon Jan 7 16:49:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 16:49:55 +0100 (CET) Subject: [pypy-svn] r50428 - pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler Message-ID: <20080107154955.5EDDB16843C@codespeak.net> Author: arigo Date: Mon Jan 7 16:49:54 2008 New Revision: 50428 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py Log: cannot pass None any more to nextBlock(). Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py Mon Jan 7 16:49:54 2008 @@ -786,7 +786,6 @@ self.nextBlock(handlers) last = len(node.handlers) - 1 - next = None for expr, target, body in node.handlers: if expr: self.set_lineno(expr) @@ -806,8 +805,8 @@ self.emit('POP_TOP') body.accept( self ) self.emitop_block('JUMP_FORWARD', end) - self.nextBlock(next) if expr: # XXX + self.nextBlock(next) self.emit('POP_TOP') self.emit('END_FINALLY') if node.else_: From arigo at codespeak.net Mon Jan 7 18:23:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 18:23:35 +0100 (CET) Subject: [pypy-svn] r50429 - in pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler: . test Message-ID: <20080107172335.F34B716842A@codespeak.net> Author: arigo Date: Mon Jan 7 18:23:34 2008 New Revision: 50429 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py Log: Stack depth computation. Probably still buggy, but hopefully more robust that the older version. Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 18:23:34 2008 @@ -1,3 +1,4 @@ +import sys from pypy.interpreter.astcompiler.consts \ import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS from pypy.interpreter.pycode import PyCode @@ -196,6 +197,9 @@ (opname,)) self.emitop_int(opname, target) + hasjrel = {} + for i in pythonopcode.hasjrel: + hasjrel[pythonopcode.opname[i]] = True hasjabs = {} for i in pythonopcode.hasjabs: hasjabs[pythonopcode.opname[i]] = True @@ -204,12 +208,90 @@ # ____________________________________________________________ def getCode(self): - self.computeStackDepth() self.fixLabelTargets() + self.computeStackDepth() return self.newCodeObject() + def _setdepth(self, i, stackdepth): + if stackdepth < 0: + raise InternalCompilerError("negative stack depth") + depths = self._stackdepths + previous_value = depths[i] + if previous_value < 0: + if i <= self._stackdepth_seen_until: + raise InternalCompilerError("back jump to code that is " + "otherwise not reachable") + depths[i] = stackdepth + else: + if previous_value != stackdepth: + raise InternalCompilerError("inconsistent stack depth") + def computeStackDepth(self): - self.stacksize = 20 # XXX! + UNREACHABLE = -1 + co_code = self.co_code + self._stackdepths = [UNREACHABLE] * len(co_code) + self._stackdepths[0] = 0 + just_loaded_const = None + consts_w = self.getConsts() + largestsize = 0 + i = 0 + + while i < len(co_code): + curstackdepth = self._stackdepths[i] + if curstackdepth > largestsize: + largestsize = curstackdepth + self._stackdepth_seen_until = i + + # decode the next instruction + opcode = ord(co_code[i]) + if opcode >= pythonopcode.HAVE_ARGUMENT: + oparg = ord(co_code[i+1]) | (ord(co_code[i+2]) << 8) + i += 3 + if opcode == pythonopcode.opmap['EXTENDED_ARG']: + opcode = ord(co_code[i]) + assert opcode >= pythonopcode.HAVE_ARGUMENT + oparg = ((oparg << 16) | + ord(co_code[i+1]) | (ord(co_code[i+2]) << 8)) + i += 3 + else: + oparg = sys.maxint + i += 1 + + if curstackdepth == UNREACHABLE: + just_loaded_const = None + continue # ignore unreachable instructions + + if opcode in DEPTH_OP_EFFECT_ALONG_JUMP: + if opcode in pythonopcode.hasjabs: + target_i = oparg + else: + target_i = i + oparg + effect = DEPTH_OP_EFFECT_ALONG_JUMP[opcode] + self._setdepth(target_i, curstackdepth + effect) + + try: + tracker = DEPTH_OP_TRACKER[opcode] + except KeyError: + pass + else: + if opcode == pythonopcode.opmap['MAKE_CLOSURE']: + # only supports "LOAD_CONST co / MAKE_CLOSURE n" + if just_loaded_const is None: + raise InternalCompilerError("MAKE_CLOSURE not " + "following LOAD_CONST") + codeobj = self.space.interp_w(PyCode, just_loaded_const) + nfreevars = len(codeobj.co_freevars) + effect = - nfreevars - oparg + else: + effect = tracker(oparg) + self._setdepth(i, curstackdepth + effect) + + if opcode == pythonopcode.opmap['LOAD_CONST']: + just_loaded_const = consts_w[oparg] + else: + just_loaded_const = None + + self.stacksize = largestsize def fixLabelTargets(self): for label, i, absolute in self.pending_label_fixes: @@ -266,3 +348,165 @@ class Label(object): position = -1 + +# ____________________________________________________________ +# Stack depth tracking + +def depth_UNPACK_SEQUENCE(count): + return count-1 +def depth_BUILD_TUPLE(count): + return -count+1 +def depth_BUILD_LIST(count): + return -count+1 +def depth_CALL_FUNCTION(argc): + hi = argc//256 + lo = argc%256 + return -(lo + hi * 2) +def depth_CALL_FUNCTION_VAR(argc): + return depth_CALL_FUNCTION(argc)-1 +def depth_CALL_FUNCTION_KW(argc): + return depth_CALL_FUNCTION(argc)-1 +def depth_CALL_FUNCTION_VAR_KW(argc): + return depth_CALL_FUNCTION(argc)-2 +def depth_CALL_METHOD(argc): + return -argc-1 +def depth_CALL_LIKELY_BUILTIN(argc): + nargs = argc & 0xFF + return -nargs+1 +def depth_MAKE_FUNCTION(argc): + return -argc +def depth_MAKE_CLOSURE(argc): + raise InternalCompilerError("must special-case this in order to account" + " for the free variables") +def depth_BUILD_SLICE(argc): + if argc == 2: + return -1 + elif argc == 3: + return -2 + assert False, 'Unexpected argument %s to depth_BUILD_SLICE' % argc + +def depth_DUP_TOPX(argc): + return argc + +def setup_stack_depth_tracker(): + effect = { + 'STOP_CODE': 0, + 'NOP': 0, + 'EXTENDED_ARG': 0, + 'POP_TOP': -1, + 'DUP_TOP': 1, + 'SLICE+0': 0, + 'SLICE+1': -1, + 'SLICE+2': -1, + 'SLICE+3': -2, + 'STORE_SLICE+0': -1, + 'STORE_SLICE+1': -2, + 'STORE_SLICE+2': -2, + 'STORE_SLICE+3': -3, + 'DELETE_SLICE+0': -1, + 'DELETE_SLICE+1': -2, + 'DELETE_SLICE+2': -2, + 'DELETE_SLICE+3': -3, + 'STORE_SUBSCR': -3, + 'DELETE_SUBSCR': -2, + 'PRINT_EXPR': -1, + 'PRINT_ITEM': -1, + 'PRINT_ITEM_TO': -2, + 'PRINT_NEWLINE': 0, + 'PRINT_NEWLINE_TO': -1, + 'YIELD_VALUE': -1, + 'EXEC_STMT': -3, + 'BUILD_CLASS': -2, + 'STORE_NAME': -1, + 'DELETE_NAME': 0, + 'STORE_ATTR': -2, + 'DELETE_ATTR': -1, + 'STORE_GLOBAL': -1, + 'DELETE_GLOBAL': 0, + 'STORE_DEREF': -1, + 'BUILD_MAP': 1, + 'COMPARE_OP': -1, + 'STORE_FAST': -1, + 'DELETE_FAST': 0, + 'IMPORT_STAR': -1, + 'IMPORT_NAME': 0, + 'IMPORT_FROM': 1, + 'LOAD_ATTR': 0, # unlike other loads + 'GET_ITER': 0, + 'FOR_ITER': 1, + 'BREAK_LOOP': 0, + 'CONTINUE_LOOP': 0, + 'POP_BLOCK': 0, + 'END_FINALLY': -3, + 'WITH_CLEANUP': -1, + 'LOOKUP_METHOD': 1, + 'LIST_APPEND': -2, + } + # use pattern match + patterns = [ + ('ROT_', 0), + ('UNARY_', 0), + ('BINARY_', -1), + ('INPLACE_', -1), + ('LOAD_', 1), + ('SETUP_', 0), + ('JUMP_IF_', 0), + ] + + def gettracker(opname): + # first look for an explicit tracker + try: + return globals()['depth_' + opname] + except KeyError: + pass + # then look for an explicit constant effect + try: + delta = effect[opname] + except KeyError: + # then do pattern matching + for pat, delta in patterns: + if opname.startswith(pat): + break + else: + raise InternalCompilerError("no stack effect registered for " + + opname) + def tracker(argc): + return delta + return tracker + + effect_along_jump = { + 'JUMP_FORWARD': 0, + 'JUMP_ABSOLUTE': 0, + 'JUMP_IF_TRUE': 0, + 'JUMP_IF_FALSE': 0, + 'FOR_ITER': -1, + 'SETUP_LOOP': 0, + 'SETUP_EXCEPT': 3, + 'SETUP_FINALLY': 3, + } + def geteffect_jump(opname): + try: + return effect_along_jump[opname] + except KeyError: + raise InternalCompilerError("no stack effect registered for " + "the branch of " + opname) + + for opname, opcode in pythonopcode.opmap.items(): + if opname in ops_interrupt_unconditionally: + continue + if opname not in ops_jump_unconditionally: + # the effect on the stack depth when execution goes from + # this instruction to the next one + DEPTH_OP_TRACKER[opcode] = gettracker(opname) + if opname in ops_jumps: + DEPTH_OP_EFFECT_ALONG_JUMP[opcode] = geteffect_jump(opname) + + +ops_interrupt_unconditionally = ('RETURN_VALUE', 'RAISE_VARARGS', + 'CONTINUE_LOOP', 'BREAK_LOOP') +ops_jump_unconditionally = ('JUMP_ABSOLUTE', 'JUMP_FORWARD') +ops_jumps = list(PyFlowGraph.hasjrel) + list(PyFlowGraph.hasjabs) + +DEPTH_OP_TRACKER = {} +DEPTH_OP_EFFECT_ALONG_JUMP = {} +setup_stack_depth_tracker() Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py Mon Jan 7 18:23:34 2008 @@ -363,6 +363,16 @@ yield self.st, "k=2; x = sum(n+2 for n in [6, 1, k])", 'x', 15 yield self.st, "k=2; x = sum(n+2 for n in (6, 1, k))", 'x', 15 + def test_closure(self): + decl = py.code.Source(""" + def make_adder(n): + def add(m): + return n + m + return add + """) + decl = str(decl) + "\n" + yield self.st, decl + "x = make_adder(40)(2)", 'x', 42 + def test_pprint(self): # a larger example that showed a bug with jumps # over more than 256 bytes From arigo at codespeak.net Mon Jan 7 18:41:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 18:41:14 +0100 (CET) Subject: [pypy-svn] r50430 - in pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler: . test Message-ID: <20080107174114.09E9116843C@codespeak.net> Author: arigo Date: Mon Jan 7 18:41:14 2008 New Revision: 50430 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py Log: Bug fix. Missing: __doc__ handling, and co_lnotab. Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 18:41:14 2008 @@ -28,9 +28,8 @@ if newlocals: self.flags |= CO_NEWLOCALS - # XXX we need to build app-level dict here, bleh + # we need to build an app-level dict here self.w_consts = space.newdict() - #self.const_list = [] self.names = [] # Free variables found by the symbol table scan, including # variables used only in nested scopes, are included here. @@ -207,6 +206,16 @@ # ____________________________________________________________ + def dump(self): + try: + self.fixLabelTargets() + except: + pass + if not hasattr(self, 'stacksize'): + self.stacksize = 99 # temporarily + co = self.newCodeObject() + co.dump() + def getCode(self): self.fixLabelTargets() self.computeStackDepth() @@ -233,6 +242,7 @@ self._stackdepths[0] = 0 just_loaded_const = None consts_w = self.getConsts() + finally_targets = {} largestsize = 0 i = 0 @@ -268,6 +278,8 @@ target_i = i + oparg effect = DEPTH_OP_EFFECT_ALONG_JUMP[opcode] self._setdepth(target_i, curstackdepth + effect) + if opcode == pythonopcode.opmap['SETUP_FINALLY']: + finally_targets[target_i] = None try: tracker = DEPTH_OP_TRACKER[opcode] @@ -284,7 +296,10 @@ effect = - nfreevars - oparg else: effect = tracker(oparg) - self._setdepth(i, curstackdepth + effect) + curstackdepth += effect + if i in finally_targets: + curstackdepth += 2 # see pyopcode.FinallyBlock.cleanup() + self._setdepth(i, curstackdepth) if opcode == pythonopcode.opmap['LOAD_CONST']: just_loaded_const = consts_w[oparg] Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py Mon Jan 7 18:41:14 2008 @@ -373,12 +373,25 @@ decl = str(decl) + "\n" yield self.st, decl + "x = make_adder(40)(2)", 'x', 42 + def test_try_except_finally(self): + yield self.simple_test, """ + try: + x = 5 + try: + if x > 2: + raise ValueError + finally: + x += 1 + except ValueError: + x *= 7 + """, 'x', 42 + def test_pprint(self): # a larger example that showed a bug with jumps # over more than 256 bytes decl = py.code.Source(""" def _safe_repr(object, context, maxlevels, level): - typ = _type(object) + typ = type(object) if typ is str: if 'locale' not in _sys.modules: return repr(object), True, False @@ -402,7 +415,7 @@ if issubclass(typ, dict) and r is dict.__repr__: if not object: return "{}", True, False - objid = _id(object) + objid = id(object) if maxlevels and level > maxlevels: return "{...}", False, objid in context if objid in context: @@ -422,7 +435,7 @@ if krecur or vrecur: recursive = True del context[objid] - return "{%s}" % _commajoin(components), readable, recursive + return "{%s}" % ', '.join(components), readable, recursive if (issubclass(typ, list) and r is list.__repr__) or \ (issubclass(typ, tuple) and r is tuple.__repr__): @@ -436,7 +449,7 @@ if not object: return "()", True, False format = "(%s)" - objid = _id(object) + objid = id(object) if maxlevels and level > maxlevels: return format % "...", False, objid in context if objid in context: @@ -455,10 +468,13 @@ if orecur: recursive = True del context[objid] - return format % _commajoin(components), readable, recursive + return format % ', '.join(components), readable, recursive rep = repr(object) return rep, (rep and not rep.startswith('<')), False """) decl = str(decl) + '\n' - yield self.st, decl + 'x=_safe_repr([5], {}, 3, 0)', 'x', '[5]' + g = {} + exec decl in g + expected = g['_safe_repr']([5], {}, 3, 0) + yield self.st, decl + 'x=_safe_repr([5], {}, 3, 0)', 'x', expected From arigo at codespeak.net Mon Jan 7 18:56:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 18:56:45 +0100 (CET) Subject: [pypy-svn] r50431 - in pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler: . test Message-ID: <20080107175645.025E716843E@codespeak.net> Author: arigo Date: Mon Jan 7 18:56:45 2008 New Revision: 50431 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py Log: Docstrings. Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 18:56:45 2008 @@ -19,7 +19,7 @@ argnames = [] self.name = name self.filename = filename - self.docstring = space.w_None + self.w_docstring = space.w_None self.argcount = len(argnames) self.klass = klass self.flags = 0 @@ -46,8 +46,8 @@ # Pending label targets to fix: [(label, index-in-co_code-to-fix, abs)] self.pending_label_fixes = [] - def setDocstring(self, doc): - self.docstring = doc + def setDocstring(self, w_docstring): + self.w_docstring = w_docstring def setFlag(self, flag): self.flags = self.flags | flag @@ -97,6 +97,12 @@ def _lookupConst(self, w_obj, w_dict): space = self.space + # insert the docstring first, if necessary + if not space.is_true(w_dict): + w_obj_type = space.type(self.w_docstring) + w_key = space.newtuple([self.w_docstring, w_obj_type]) + space.setitem(w_dict, w_key, space.wrap(0)) + # normal logic follows w_obj_type = space.type(w_obj) w_key = space.newtuple([w_obj, w_obj_type]) try: @@ -350,6 +356,10 @@ def getConsts(self): """Return a tuple for the const slot of the code object """ + # sanity-check + index = self._lookupConst(self.w_docstring, self.w_consts) + if index != 0: + raise InternalCompilerError("setDocstring() called too late") space = self.space keys_w = space.unpackiterable(self.w_consts) l_w = [None] * len(keys_w) Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pycodegen.py Mon Jan 7 18:56:45 2008 @@ -313,8 +313,6 @@ def visitFunction(self, node): self._visitFuncOrLambda(node, isLambda=0) space = self.space - if not space.is_w(node.w_doc, space.w_None): - self.setDocstring(node.w_doc) self.storeName(node.name, node.lineno) def visitLambda(self, node): @@ -1416,7 +1414,7 @@ CodeGenerator.__init__(self, space, graph) self.optimized = 1 - if not isLambda and not space.is_w(func.w_doc, space.w_None): + if not isLambda: self.setDocstring(func.w_doc) if func.varargs: @@ -1495,8 +1493,7 @@ CodeGenerator.__init__(self, space, graph) self.graph.setFlag(CO_NEWLOCALS) - if not space.is_w(klass.w_doc, space.w_None): - self.setDocstring(klass.w_doc) + self.setDocstring(klass.w_doc) def get_module(self): return self.module Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/test/test_compiler.py Mon Jan 7 18:56:45 2008 @@ -325,6 +325,11 @@ """doc"""; print 1 a=1 ''', "doc"), + (''' + class Foo(object): pass + foo = Foo() + exec "'moduledoc'" in foo.__dict__ + ''', "moduledoc"), ]: yield self.simple_test, source, "foo.__doc__", expected From arigo at codespeak.net Mon Jan 7 19:06:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 19:06:15 +0100 (CET) Subject: [pypy-svn] r50432 - pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler Message-ID: <20080107180615.D5D6116846C@codespeak.net> Author: arigo Date: Mon Jan 7 19:06:14 2008 New Revision: 50432 Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Log: lnotab, copied from the previous pyassem. Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 19:06:14 2008 @@ -45,6 +45,7 @@ self.co_code = [] # Pending label targets to fix: [(label, index-in-co_code-to-fix, abs)] self.pending_label_fixes = [] + self.lnotab = None def setDocstring(self, w_docstring): self.w_docstring = w_docstring @@ -78,10 +79,18 @@ return intval & 0xFFFF emitop_extended_arg._dont_inline_ = True + def emitop_setlineno(self, lineno): + if self.lnotab is None: + self.lnotab = LineAddrTable(lineno) + else: + self.lnotab.nextLine(len(self.co_code), lineno) + emitop_setlineno._dont_inline_ = True + def emitop_int(self, opname, intval): assert intval >= 0 if opname == "SET_LINENO": - return # XXX + self.emitop_setlineno(intval) + return if intval > 0xFFFF: intval = self.emitop_extended_arg(intval) self.emit(opname) @@ -340,6 +349,12 @@ argcount = self.argcount if self.flags & CO_VARKEYWORDS: argcount = argcount - 1 + if self.lnotab is None: # obscure case + firstline = 0 + lnotab = "" + else: + firstline = self.lnotab.firstline + lnotab = self.lnotab.getTable() return PyCode( self.space, argcount, nlocals, self.stacksize, self.flags, ''.join(self.co_code), @@ -347,8 +362,8 @@ self.names, self.varnames, self.filename, self.name, - 1, # XXX! self.firstline, - "", # XXX! self.lnotab.getTable(), + firstline, + lnotab, self.freevars, self.cellvars ) @@ -375,6 +390,61 @@ position = -1 # ____________________________________________________________ +# Encoding the line numbers in lnotab + +class LineAddrTable: + """lnotab + + This class builds the lnotab, which is documented in compile.c. + Here's a brief recap: + + For each SET_LINENO instruction after the first one, two bytes are + added to lnotab. (In some cases, multiple two-byte entries are + added.) The first byte is the distance in bytes between the + instruction for the last SET_LINENO and the current SET_LINENO. + The second byte is offset in line numbers. If either offset is + greater than 255, multiple two-byte entries are added -- see + compile.c for the delicate details. + """ + + def __init__(self, firstline): + self.firstline = firstline + self.lastline = firstline + self.lastoff = 0 + self.lnotab = [] # list of characters + + def nextLine(self, codeOffset, lineno): + # compute deltas + addr = codeOffset - self.lastoff + line = lineno - self.lastline + # Python assumes that lineno always increases with + # increasing bytecode address (lnotab is unsigned char). + # Depending on when SET_LINENO instructions are emitted + # this is not always true. Consider the code: + # a = (1, + # b) + # In the bytecode stream, the assignment to "a" occurs + # after the loading of "b". This works with the C Python + # compiler because it only generates a SET_LINENO instruction + # for the assignment. + if line >= 0: + push = self.lnotab.append + while addr > 255: + push(chr(255)); push(chr(0)) + addr -= 255 + while line > 255: + push(chr(addr)); push(chr(255)) + line -= 255 + addr = 0 + if addr > 0 or line > 0: + push(chr(addr)); push(chr(line)) + self.lastline = lineno + self.lastoff = codeOffset + + def getTable(self): + return ''.join(self.lnotab) + +# ____________________________________________________________ # Stack depth tracking def depth_UNPACK_SEQUENCE(count): From arigo at codespeak.net Mon Jan 7 19:35:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 19:35:37 +0100 (CET) Subject: [pypy-svn] r50433 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080107183537.9BFA816846C@codespeak.net> Author: arigo Date: Mon Jan 7 19:35:37 2008 New Revision: 50433 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: Rewrite pyassem mostly from scratch to be simple, straightforward and fast instead of complicated, buggily too clever, and slow. (Branch merge.) Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 19:35:37 2008 @@ -1,454 +1,25 @@ -"""A flow graph representation for Python bytecode""" - import sys - -from pypy.interpreter.astcompiler import misc, ast from pypy.interpreter.astcompiler.consts \ import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS from pypy.interpreter.pycode import PyCode -from pypy.interpreter.baseobjspace import W_Root from pypy.tool import stdlib_opcode as pythonopcode from pypy.interpreter.error import OperationError + class InternalCompilerError(Exception): """Something went wrong in the ast compiler.""" -class BlockSet: - """A Set implementation specific to Blocks - it uses Block.bid as keys to underlying dict""" - def __init__(self): - self.elts = {} - def __len__(self): - return len(self.elts) - def __contains__(self, elt): - return elt.bid in self.elts - def add(self, elt): - self.elts[elt.bid] = elt - def elements(self): - return self.elts.values() - def has_elt(self, elt): - return elt.bid in self.elts - def remove(self, elt): - del self.elts[elt.bid] - def copy(self): - c = BlockSet() - c.elts.update(self.elts) - return c - - -class Instr: - has_arg = False - - def __init__(self, op): - self.op = op - -class InstrWithArg(Instr): - has_arg = True - -class InstrName(InstrWithArg): - def __init__(self, inst, name): - Instr.__init__(self, inst) - self.name = name - - def getArg(self): - "NOT_RPYTHON" - return self.name - -class InstrInt(InstrWithArg): - def __init__(self, inst, intval): - Instr.__init__(self, inst) - self.intval = intval - - def getArg(self): - "NOT_RPYTHON" - return self.intval - -class InstrBlock(InstrWithArg): - def __init__(self, inst, block): - Instr.__init__(self, inst) - self.block = block - - def getArg(self): - "NOT_RPYTHON" - return self.block - -class InstrObj(InstrWithArg): - def __init__(self, inst, obj): - Instr.__init__(self, inst) - self.obj = obj - - def getArg(self): - "NOT_RPYTHON" - return self.obj - -class InstrCode(InstrWithArg): - def __init__(self, inst, gen): - Instr.__init__(self, inst) - self.gen = gen - - def getArg(self): - "NOT_RPYTHON" - return self.gen - -class FlowGraph: - def __init__(self, space): - self.space = space - self.current = self.entry = Block(space) - self.exit = Block(space,"exit") - self.blocks = BlockSet() - self.blocks.add(self.entry) - self.blocks.add(self.exit) - - def startBlock(self, block): - if self._debug: - if self.current: - print "end", repr(self.current) - print " next", self.current.next - print " ", self.current.get_children() - print repr(block) - assert block is not None - self.current = block - - def nextBlock(self, block=None): - # XXX think we need to specify when there is implicit transfer - # from one block to the next. might be better to represent this - # with explicit JUMP_ABSOLUTE instructions that are optimized - # out when they are unnecessary. - # - # I think this strategy works: each block has a child - # designated as "next" which is returned as the last of the - # children. because the nodes in a graph are emitted in - # reverse post order, the "next" block will always be emitted - # immediately after its parent. - # Worry: maintaining this invariant could be tricky - if block is None: - block = self.newBlock() - - # Note: If the current block ends with an unconditional - # control transfer, then it is incorrect to add an implicit - # transfer to the block graph. The current code requires - # these edges to get the blocks emitted in the right order, - # however. :-( If a client needs to remove these edges, call - # pruneEdges(). - - self.current.addNext(block) - self.startBlock(block) - - def newBlock(self): - b = Block(self.space) - self.blocks.add(b) - return b - - def startExitBlock(self): - self.startBlock(self.exit) - - _debug = 0 - - def _enable_debug(self): - self._debug = 1 - - def _disable_debug(self): - self._debug = 0 - - def emit(self, inst): - if self._debug: - print "\t", inst - if inst in ['RETURN_VALUE', 'YIELD_VALUE']: - self.current.addOutEdge(self.exit) - self.current.emit( Instr(inst) ) - - #def emitop(self, inst, arg ): - # if self._debug: - # print "\t", inst, arg - # self.current.emit( (inst,arg) ) - - def emitop_obj(self, inst, obj ): - if self._debug: - print "\t", inst, repr(obj) - self.current.emit( InstrObj(inst,obj) ) - - def emitop_code(self, inst, obj ): - if self._debug: - print "\t", inst, repr(obj) - self.current.emit( InstrCode(inst, obj) ) - - def emitop_int(self, inst, intval ): - if self._debug: - print "\t", inst, intval - assert isinstance(intval,int) - self.current.emit( InstrInt(inst,intval) ) - - def emitop_block(self, inst, block): - if self._debug: - print "\t", inst, block - assert isinstance(block, Block) - self.current.addOutEdge( block ) - self.current.emit( InstrBlock(inst,block) ) - - def emitop_name(self, inst, name ): - if self._debug: - print "\t", inst, name - assert isinstance(name,str) - self.current.emit( InstrName(inst,name) ) - - def getBlocksInOrder(self): - """Return the blocks in reverse postorder - - i.e. each node appears before all of its successors - """ - # TODO: What we need here is a topological sort that - - - # XXX make sure every node that doesn't have an explicit next - # is set so that next points to exit - for b in self.blocks.elements(): - if b is self.exit: - continue - if not b.next: - b.addNext(self.exit) - order = dfs_postorder(self.entry, {}) - order.reverse() - self.fixupOrder(order, self.exit) - # hack alert - if not self.exit in order: - order.append(self.exit) - - return order - - def fixupOrder(self, blocks, default_next): - """Fixup bad order introduced by DFS.""" - - # XXX This is a total mess. There must be a better way to get - # the code blocks in the right order. - - self.fixupOrderHonorNext(blocks, default_next) - self.fixupOrderForward(blocks, default_next) - - def fixupOrderHonorNext(self, blocks, default_next): - """Fix one problem with DFS. - - The DFS uses child block, but doesn't know about the special - "next" block. As a result, the DFS can order blocks so that a - block isn't next to the right block for implicit control - transfers. - """ - new_blocks = blocks - blocks = blocks[:] - del new_blocks[:] - i = 0 - while i < len(blocks) - 1: - b = blocks[i] - n = blocks[i + 1] - i += 1 - new_blocks.append(b) - if not b.next or b.next[0] == default_next or b.next[0] == n: - continue - # The blocks are in the wrong order. Find the chain of - # blocks to insert where they belong. - cur = b - chain = [] - elt = cur - while elt.next and elt.next[0] != default_next: - chain.append(elt.next[0]) - elt = elt.next[0] - # Now remove the blocks in the chain from the current - # block list, so that they can be re-inserted. - for b in chain: - for j in range(i + 1, len(blocks)): - if blocks[j] == b: - del blocks[j] - break - else: - assert False, "Can't find block" - - new_blocks.extend(chain) - if i == len(blocks) - 1: - new_blocks.append(blocks[i]) - - def fixupOrderForward(self, blocks, default_next): - """Make sure all JUMP_FORWARDs jump forward""" - index = {} - chains = [] - cur = [] - for b in blocks: - index[b.bid] = len(chains) - cur.append(b) - if b.next and b.next[0] == default_next: - chains.append(cur) - cur = [] - chains.append(cur) - - while 1: - constraints = [] - - for i in range(len(chains)): - l = chains[i] - for b in l: - for c in b.get_children(): - if index[c.bid] < i: - forward_p = 0 - for inst in b.insts: - # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - # other bytecodes need the same logic, but - # trying to do that throws this function into - # an infinite loop. Sad sad sad. - # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - if inst.op == 'JUMP_FORWARD': - assert isinstance(inst, InstrBlock) - if inst.block == c: - forward_p = 1 - if not forward_p: - continue - constraints.append((index[c.bid], i)) - - if not constraints: - break - - # XXX just do one for now - # do swaps to get things in the right order - goes_before, a_chain = constraints[0] - assert a_chain > goes_before >= 0 - c = chains[a_chain] - del chains[a_chain] - chains.insert(goes_before, c) - - del blocks[:] - for c in chains: - for b in c: - blocks.append(b) - - def getBlocks(self): - return self.blocks.elements() - - def getRoot(self): - """Return nodes appropriate for use with dominator""" - return self.entry - - def getContainedGraphs(self): - l = [] - for b in self.getBlocks(): - l.extend(b.getContainedGraphs()) - return l - -def dfs_postorder(b, seen): - """Depth-first search of tree rooted at b, return in postorder""" - order = [] - seen[b.bid] = b - for c in b.get_children(): - if c.bid in seen: - continue - order = order + dfs_postorder(c, seen) - order.append(b) - return order - -BlockCounter = misc.Counter(0) - -class Block: - - def __init__(self, space, label=''): - self.insts = [] - self.inEdges = BlockSet() - self.outEdges = BlockSet() - self.label = label - self.bid = BlockCounter.next() - self.next = [] - self.space = space - - def __repr__(self): - if self.label: - return "" % (self.label, self.bid) - else: - return "" % (self.bid) - - def __str__(self): - insts = [ str(i) for i in self.insts ] - return "" % (self.label, self.bid, - '\n'.join(insts)) - - def emit(self, inst): - op = inst.op - if op[:4] == 'JUMP': - assert isinstance(inst, InstrBlock) - self.outEdges.add(inst.block) -## if op=="LOAD_CONST": -## assert isinstance( inst[1], W_Root ) or hasattr( inst[1], 'getCode') - self.insts.append( inst ) - - def getInstructions(self): - return self.insts - - def addInEdge(self, block): - self.inEdges.add(block) - - def addOutEdge(self, block): - self.outEdges.add(block) - - def addNext(self, block): - self.next.append(block) - assert len(self.next) == 1, [ str(i) for i in self.next ] - - _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE', - 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP') - - def pruneNext(self): - """Remove bogus edge for unconditional transfers - - Each block has a next edge that accounts for implicit control - transfers, e.g. from a JUMP_IF_FALSE to the block that will be - executed if the test is true. - - These edges must remain for the current assembler code to - work. If they are removed, the dfs_postorder gets things in - weird orders. However, they shouldn't be there for other - purposes, e.g. conversion to SSA form. This method will - remove the next edge when it follows an unconditional control - transfer. - """ - try: - inst = self.insts[-1] - except (IndexError, ValueError): - return - if inst.op in self._uncond_transfer: - self.next = [] - - def get_children(self): - if self.next and self.next[0].bid in self.outEdges.elts: - self.outEdges.remove(self.next[0]) - return self.outEdges.elements() + self.next - - def getContainedGraphs(self): - """Return all graphs contained within this block. - - For example, a MAKE_FUNCTION block will contain a reference to - the graph for the function body. - """ - contained = [] - for inst in self.insts: - if isinstance(inst, InstrCode): - gen = inst.gen - if gen: - contained.append(gen) - return contained - -# flags for code objects - -# the FlowGraph is transformed in place; it exists in one of these states -RAW = "RAW" -FLAT = "FLAT" -CONV = "CONV" -DONE = "DONE" - -class PyFlowGraph(FlowGraph): +class PyFlowGraph(object): def __init__(self, space, name, filename, argnames=None, optimized=0, klass=0, newlocals=0): - FlowGraph.__init__(self, space) + self.space = space if argnames is None: argnames = [] self.name = name self.filename = filename - self.docstring = space.w_None + self.w_docstring = space.w_None self.argcount = len(argnames) self.klass = klass self.flags = 0 @@ -457,9 +28,8 @@ if newlocals: self.flags |= CO_NEWLOCALS - # XXX we need to build app-level dict here, bleh + # we need to build an app-level dict here self.w_consts = space.newdict() - #self.const_list = [] self.names = [] # Free variables found by the symbol table scan, including # variables used only in nested scopes, are included here. @@ -471,11 +41,14 @@ # kinds of variables. self.closure = [] self.varnames = list(argnames) - self.stage = RAW - self.orderedblocks = [] + # The bytecode we are building, as a list of characters + self.co_code = [] + # Pending label targets to fix: [(label, index-in-co_code-to-fix, abs)] + self.pending_label_fixes = [] + self.lnotab = None - def setDocstring(self, doc): - self.docstring = doc + def setDocstring(self, w_docstring): + self.w_docstring = w_docstring def setFlag(self, flag): self.flags = self.flags | flag @@ -492,201 +65,76 @@ def setCellVars(self, names): self.cellvars = names - def getCode(self): - """Get a Python code object""" - if self.stage == RAW: - self.computeStackDepth() - self.convertArgs() - if self.stage == CONV: - self.flattenGraph() - if self.stage == FLAT: - self.makeByteCode() - if self.stage == DONE: - return self.newCodeObject() - raise InternalCompilerError("inconsistent PyFlowGraph state") - - def dump(self, io=None): - if io: - save = sys.stdout - sys.stdout = io - pc = 0 - for t in self.insts: - opname = t.op - if opname == "SET_LINENO": - print - if not t.has_arg: - print "\t", "%3d" % pc, opname - pc = pc + 1 - else: - print "\t", "%3d" % pc, opname, t.getArg() - pc = pc + 3 - if io: - sys.stdout = save - - def _max_depth(self, depth, seen, b, d): - if b in seen: - return d - seen[b] = 1 - d = d + depth[b] - children = b.get_children() - if children: - maxd = -1 - for c in children: - childd =self._max_depth(depth, seen, c, d) - if childd > maxd: - maxd = childd - return maxd + # ____________________________________________________________ + # Simple instructions + + def emit(self, opname): + self.co_code.append(chr(pythonopcode.opmap[opname])) + + def emitop_extended_arg(self, intval): + assert intval <= 0x7FFFFFFF + self.emit('EXTENDED_ARG') + self.co_code.append(chr((intval >> 16) & 0xFF)) + self.co_code.append(chr((intval >> 24) & 0xFF)) + return intval & 0xFFFF + emitop_extended_arg._dont_inline_ = True + + def emitop_setlineno(self, lineno): + if self.lnotab is None: + self.lnotab = LineAddrTable(lineno) else: - if not b.label == "exit": - return self._max_depth(depth, seen, self.exit, d) - else: - return d + self.lnotab.nextLine(len(self.co_code), lineno) + emitop_setlineno._dont_inline_ = True - def computeStackDepth(self): - """Compute the max stack depth. + def emitop_int(self, opname, intval): + assert intval >= 0 + if opname == "SET_LINENO": + self.emitop_setlineno(intval) + return + if intval > 0xFFFF: + intval = self.emitop_extended_arg(intval) + self.emit(opname) + self.co_code.append(chr(intval & 0xFF)) + self.co_code.append(chr(intval >> 8)) - Approach is to compute the stack effect of each basic block. - Then find the path through the code with the largest total - effect. - """ - depth = {} - exit = None - for b in self.getBlocks(): - depth[b] = findDepth(b.getInstructions()) - - seen = {} - - self.stacksize = self._max_depth( depth, seen, self.entry, 0) - - def flattenGraph(self): - """Arrange the blocks in order and resolve jumps""" - assert self.stage == CONV - self.insts = insts = [] - firstline = 0 - pc = 0 - begin = {} - end = {} - forward_refs = [] - for b in self.orderedblocks: - # Prune any setlineno before the 'implicit return' block. - if b is self.exit: - while len(insts) and insts[-1].op == "SET_LINENO": - insts.pop() - begin[b] = pc - for inst in b.getInstructions(): - if not inst.has_arg: - insts.append(inst) - pc = pc + 1 - elif inst.op != "SET_LINENO": - if inst.op in self.hasjrel: - assert isinstance(inst, InstrBlock) - # relative jump - no extended arg - block = inst.block - inst = InstrInt(inst.op, 0) - forward_refs.append( (block, inst, pc) ) - insts.append(inst) - pc = pc + 3 - elif inst.op in self.hasjabs: - # absolute jump - can be extended if backward - assert isinstance(inst, InstrBlock) - arg = inst.block - if arg in begin: - # can only extend argument if backward - offset = begin[arg] - hi = offset // 65536 - lo = offset % 65536 - if hi>0: - # extended argument - insts.append( InstrInt("EXTENDED_ARG", hi) ) - pc = pc + 3 - inst = InstrInt(inst.op, lo) - else: - inst = InstrInt(inst.op, 0) - forward_refs.append( (arg, inst, pc ) ) - insts.append(inst) - pc = pc + 3 - else: - assert isinstance(inst, InstrInt) - arg = inst.intval - # numerical arg - hi = arg // 65536 - lo = arg % 65536 - if hi>0: - # extended argument - insts.append( InstrInt("EXTENDED_ARG", hi) ) - inst.intval = lo - pc = pc + 3 - insts.append(inst) - pc = pc + 3 - else: - insts.append(inst) - if firstline == 0: - firstline = inst.intval - end[b] = pc - pc = 0 - - for block, inst, pc in forward_refs: - opname = inst.op - abspos = begin[block] - if opname in self.hasjrel: - offset = abspos - pc - 3 - if offset < 0: - raise InternalCompilerError("unexpected backward jump") - inst.intval = offset - else: - inst.intval = abspos - self.firstline = firstline - self.stage = FLAT + # ____________________________________________________________ + # Instructions with an object argument (LOAD_CONST) - hasjrel = {} - for i in pythonopcode.hasjrel: - hasjrel[pythonopcode.opname[i]] = True - hasjabs = {} - for i in pythonopcode.hasjabs: - hasjabs[pythonopcode.opname[i]] = True + def emitop_obj(self, opname, w_obj): + index = self._lookupConst(w_obj, self.w_consts) + self.emitop_int(opname, index) - def setconst(self, w_consts, w_item, value): - space = self.space - w_item_type = space.type(w_item) - w_key = space.newtuple([w_item, w_item_type]) - space.setitem(w_consts, w_key, space.wrap(value)) - - def convertArgs(self): - """Convert arguments from symbolic to concrete form""" - assert self.stage == RAW + def _lookupConst(self, w_obj, w_dict): space = self.space - self.orderedblocks = self.getBlocksInOrder() - self.setconst(self.w_consts, self.docstring, 0) - #self.const_list.insert(0, self.docstring) - self.sort_cellvars() - - for b in self.orderedblocks: - insts = b.getInstructions() - for i in range(len(insts)): - inst = insts[i] - if inst.has_arg: - opname = inst.op - conv = self._converters.get(opname, None) - if conv: - insts[i] = conv(self, inst) - self.stage = CONV - - def sort_cellvars(self): - """Sort cellvars in the order of varnames and prune from freevars. - """ - cells = {} - for name in self.cellvars: - cells[name] = 1 - self.cellvars = [name for name in self.varnames - if name in cells] - for name in self.cellvars: - del cells[name] - self.cellvars = self.cellvars + cells.keys() - self.closure = self.cellvars + self.freevars + # insert the docstring first, if necessary + if not space.is_true(w_dict): + w_obj_type = space.type(self.w_docstring) + w_key = space.newtuple([self.w_docstring, w_obj_type]) + space.setitem(w_dict, w_key, space.wrap(0)) + # normal logic follows + w_obj_type = space.type(w_obj) + w_key = space.newtuple([w_obj, w_obj_type]) + try: + w_result = space.getitem(w_dict, w_key) + except OperationError, operr: + if not operr.match(space, space.w_KeyError): + raise + w_result = space.len(w_dict) + space.setitem(w_dict, w_key, w_result) + return space.int_w(w_result) + + # ____________________________________________________________ + # Instructions with a name argument + + def emitop_name(self, opname, name): + conv = self._converters[opname] + index = conv(self, name) + self.emitop_int(opname, index) def _lookupName(self, name, list): """Return index of name in list, appending if necessary """ + # XXX use dicts instead of lists assert isinstance(name, str) for i in range(len(list)): if list[i] == name: @@ -695,70 +143,14 @@ list.append(name) return end - def _cmpConsts(self, w_left, w_right): - space = self.space - t = space.type(w_left) - if space.is_w(t, space.type(w_right)): - if space.is_w(t, space.w_tuple): - left_len = space.int_w(space.len(w_left)) - right_len = space.int_w(space.len(w_right)) - if left_len == right_len: - for i in range(left_len): - w_lefti = space.getitem(w_left, space.wrap(i)) - w_righti = space.getitem(w_right, space.wrap(i)) - if not self._cmpConsts(w_lefti, w_righti): - return False - return True - elif space.eq_w(w_left, w_right): - return True - return False - - def _lookupConst(self, w_obj, w_dict): - """ - This routine uses a list instead of a dictionary, because a - dictionary can't store two different keys if the keys have the - same value but different types, e.g. 2 and 2L. The compiler - must treat these two separately, so it does an explicit type - comparison before comparing the values. - """ - space = self.space - w_obj_type = space.type(w_obj) - try: - w_key = space.newtuple([w_obj, w_obj_type]) - return space.int_w(space.getitem(w_dict, w_key)) - except OperationError, operr: - if not operr.match(space, space.w_KeyError): - raise - lgt = space.int_w(space.len(w_dict)) - self.setconst(w_dict, w_obj, lgt) - return lgt - - _converters = {} - - def _convert_LOAD_CONST(self, inst): - if isinstance(inst, InstrCode): - w_obj = inst.gen.getCode() - else: - assert isinstance(inst, InstrObj) - w_obj = inst.obj - #assert w_obj is not None - index = self._lookupConst(w_obj, self.w_consts) - return InstrInt(inst.op, index) - - def _convert_LOAD_FAST(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name + def _convert_LOAD_FAST(self, arg): self._lookupName(arg, self.names) - index= self._lookupName(arg, self.varnames) - return InstrInt(inst.op, index) + return self._lookupName(arg, self.varnames) _convert_STORE_FAST = _convert_LOAD_FAST _convert_DELETE_FAST = _convert_LOAD_FAST - def _convert_NAME(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name - index = self._lookupName(arg, self.names) - return InstrInt(inst.op, index) + def _convert_NAME(self, arg): + return self._lookupName(arg, self.names) _convert_LOAD_NAME = _convert_NAME _convert_STORE_NAME = _convert_NAME _convert_DELETE_NAME = _convert_NAME @@ -772,73 +164,184 @@ _convert_DELETE_GLOBAL = _convert_NAME _convert_LOOKUP_METHOD = _convert_NAME - def _convert_DEREF(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name + def _convert_DEREF(self, arg): self._lookupName(arg, self.names) - index = self._lookupName(arg, self.closure) - return InstrInt(inst.op, index) + return self._lookupName(arg, self.closure) _convert_LOAD_DEREF = _convert_DEREF _convert_STORE_DEREF = _convert_DEREF - def _convert_LOAD_CLOSURE(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name - index = self._lookupName(arg, self.closure) - return InstrInt(inst.op, index) - - _cmp = list(pythonopcode.cmp_op) - def _convert_COMPARE_OP(self, inst): - assert isinstance(inst, InstrName) - arg = inst.name - index = self._cmp.index(arg) - return InstrInt(inst.op, index) - + def _convert_LOAD_CLOSURE(self, arg): + return self._lookupName(arg, self.closure) - # similarly for other opcodes... + _cmp = list(pythonopcode.cmp_op) + def _convert_COMPARE_OP(self, arg): + return self._cmp.index(arg) + _converters = {} for name, obj in locals().items(): if name[:9] == "_convert_": opname = name[9:] _converters[opname] = obj del name, obj, opname - def makeByteCode(self): - assert self.stage == FLAT - self.lnotab = lnotab = LineAddrTable(self.firstline) - for t in self.insts: - opname = t.op - if self._debug: - if not t.has_arg: - print "x",opname + # ____________________________________________________________ + # Labels and jumps + + def newBlock(self): + """This really returns a new label, initially not pointing anywhere.""" + return Label() + + def nextBlock(self, label): + if label.position >= 0: + raise InternalCompilerError("Label target already seen") + label.position = len(self.co_code) + + def emitop_block(self, opname, label): + absolute = opname in self.hasjabs + target = label.position + if target < 0: # unknown yet + i = len(self.co_code) + self.pending_label_fixes.append((label, i, absolute)) + target = 0xFFFF + else: + if not absolute: + # if the target was already seen, it must be backward, + # which is forbidden for these instructions + raise InternalCompilerError("%s cannot do a back jump" % + (opname,)) + self.emitop_int(opname, target) + + hasjrel = {} + for i in pythonopcode.hasjrel: + hasjrel[pythonopcode.opname[i]] = True + hasjabs = {} + for i in pythonopcode.hasjabs: + hasjabs[pythonopcode.opname[i]] = True + del i + + # ____________________________________________________________ + + def dump(self): + try: + self.fixLabelTargets() + except: + pass + if not hasattr(self, 'stacksize'): + self.stacksize = 99 # temporarily + co = self.newCodeObject() + co.dump() + + def getCode(self): + self.fixLabelTargets() + self.computeStackDepth() + return self.newCodeObject() + + def _setdepth(self, i, stackdepth): + if stackdepth < 0: + raise InternalCompilerError("negative stack depth") + depths = self._stackdepths + previous_value = depths[i] + if previous_value < 0: + if i <= self._stackdepth_seen_until: + raise InternalCompilerError("back jump to code that is " + "otherwise not reachable") + depths[i] = stackdepth + else: + if previous_value != stackdepth: + raise InternalCompilerError("inconsistent stack depth") + + def computeStackDepth(self): + UNREACHABLE = -1 + co_code = self.co_code + self._stackdepths = [UNREACHABLE] * len(co_code) + self._stackdepths[0] = 0 + just_loaded_const = None + consts_w = self.getConsts() + finally_targets = {} + largestsize = 0 + i = 0 + + while i < len(co_code): + curstackdepth = self._stackdepths[i] + if curstackdepth > largestsize: + largestsize = curstackdepth + self._stackdepth_seen_until = i + + # decode the next instruction + opcode = ord(co_code[i]) + if opcode >= pythonopcode.HAVE_ARGUMENT: + oparg = ord(co_code[i+1]) | (ord(co_code[i+2]) << 8) + i += 3 + if opcode == pythonopcode.opmap['EXTENDED_ARG']: + opcode = ord(co_code[i]) + assert opcode >= pythonopcode.HAVE_ARGUMENT + oparg = ((oparg << 16) | + ord(co_code[i+1]) | (ord(co_code[i+2]) << 8)) + i += 3 + else: + oparg = sys.maxint + i += 1 + + if curstackdepth == UNREACHABLE: + just_loaded_const = None + continue # ignore unreachable instructions + + if opcode in DEPTH_OP_EFFECT_ALONG_JUMP: + if opcode in pythonopcode.hasjabs: + target_i = oparg else: - print "x",opname, t.getArg() - if not t.has_arg: - lnotab.addCode1(self.opnum[opname]) + target_i = i + oparg + effect = DEPTH_OP_EFFECT_ALONG_JUMP[opcode] + self._setdepth(target_i, curstackdepth + effect) + if opcode == pythonopcode.opmap['SETUP_FINALLY']: + finally_targets[target_i] = None + + try: + tracker = DEPTH_OP_TRACKER[opcode] + except KeyError: + pass else: - assert isinstance(t, InstrInt) - oparg = t.intval - if opname == "SET_LINENO": - lnotab.nextLine(oparg) - continue - hi, lo = twobyte(oparg) - try: - lnotab.addCode3(self.opnum[opname], lo, hi) - except ValueError: - if self._debug: - print opname, oparg - print self.opnum[opname], lo, hi - raise - self.stage = DONE - - opnum = {} - for num in range(len(pythonopcode.opname)): - opnum[pythonopcode.opname[num]] = num - # This seems to duplicate dis.opmap from opcode.opmap - del num + if opcode == pythonopcode.opmap['MAKE_CLOSURE']: + # only supports "LOAD_CONST co / MAKE_CLOSURE n" + if just_loaded_const is None: + raise InternalCompilerError("MAKE_CLOSURE not " + "following LOAD_CONST") + codeobj = self.space.interp_w(PyCode, just_loaded_const) + nfreevars = len(codeobj.co_freevars) + effect = - nfreevars - oparg + else: + effect = tracker(oparg) + curstackdepth += effect + if i in finally_targets: + curstackdepth += 2 # see pyopcode.FinallyBlock.cleanup() + self._setdepth(i, curstackdepth) + + if opcode == pythonopcode.opmap['LOAD_CONST']: + just_loaded_const = consts_w[oparg] + else: + just_loaded_const = None + + self.stacksize = largestsize + + def fixLabelTargets(self): + for label, i, absolute in self.pending_label_fixes: + target = label.position + if target < 0: + raise InternalCompilerError("Label target not found") + if not absolute: + target = target - (i+3) # relative jump + if target < 0: + raise InternalCompilerError("Unexpected backward jump") + if target > 0xFFFF: + # CPython has the same limitation, for the same practical + # reason + msg = "function too large (bytecode would jump too far away)" + space = self.space + raise OperationError(space.w_SystemError, space.wrap(msg)) + self.co_code[i+1] = chr(target & 0xFF) + self.co_code[i+2] = chr(target >> 8) def newCodeObject(self): - assert self.stage == DONE if (self.flags & CO_NEWLOCALS) == 0: nlocals = 0 else: @@ -846,47 +349,48 @@ argcount = self.argcount if self.flags & CO_VARKEYWORDS: argcount = argcount - 1 - # was return new.code, now we just return the parameters and let - # the caller create the code object + if self.lnotab is None: # obscure case + firstline = 0 + lnotab = "" + else: + firstline = self.lnotab.firstline + lnotab = self.lnotab.getTable() return PyCode( self.space, argcount, nlocals, self.stacksize, self.flags, - self.lnotab.getCode(), + ''.join(self.co_code), self.getConsts(), self.names, self.varnames, self.filename, self.name, - self.firstline, - self.lnotab.getTable(), + firstline, + lnotab, self.freevars, self.cellvars ) def getConsts(self): """Return a tuple for the const slot of the code object - - Must convert references to code (MAKE_FUNCTION) to code - objects recursively. """ + # sanity-check + index = self._lookupConst(self.w_docstring, self.w_consts) + if index != 0: + raise InternalCompilerError("setDocstring() called too late") space = self.space - l_w = [None] * space.int_w(space.len(self.w_consts)) keys_w = space.unpackiterable(self.w_consts) + l_w = [None] * len(keys_w) for w_key in keys_w: index = space.int_w(space.getitem(self.w_consts, w_key)) w_v = space.unpacktuple(w_key)[0] l_w[index] = w_v return l_w -def isJump(opname): - if opname[:4] == 'JUMP': - return 1 - -def twobyte(val): - """Convert an int argument into high and low bytes""" - assert isinstance(val,int) - assert 0 <= val < 65536 - hi = val // 256 - lo = val % 256 - return hi, lo +# ____________________________________________________________ + +class Label(object): + position = -1 + +# ____________________________________________________________ +# Encoding the line numbers in lnotab class LineAddrTable: """lnotab @@ -904,26 +408,14 @@ """ def __init__(self, firstline): - self.code = [] - self.codeOffset = 0 self.firstline = firstline self.lastline = firstline self.lastoff = 0 - self.lnotab = [] + self.lnotab = [] # list of characters - def addCode1(self, op ): - self.code.append(chr(op)) - self.codeOffset = self.codeOffset + 1 - - def addCode3(self, op, hi, lo): - self.code.append(chr(op)) - self.code.append(chr(hi)) - self.code.append(chr(lo)) - self.codeOffset = self.codeOffset + 3 - - def nextLine(self, lineno): + def nextLine(self, codeOffset, lineno): # compute deltas - addr = self.codeOffset - self.lastoff + addr = codeOffset - self.lastoff line = lineno - self.lastline # Python assumes that lineno always increases with # increasing bytecode address (lnotab is unsigned char). @@ -938,23 +430,22 @@ if line >= 0: push = self.lnotab.append while addr > 255: - push(255); push(0) + push(chr(255)); push(chr(0)) addr -= 255 while line > 255: - push(addr); push(255) + push(chr(addr)); push(chr(255)) line -= 255 addr = 0 if addr > 0 or line > 0: - push(addr); push(line) + push(chr(addr)); push(chr(line)) self.lastline = lineno - self.lastoff = self.codeOffset - - def getCode(self): - return ''.join(self.code) + self.lastoff = codeOffset def getTable(self): - return ''.join( [ chr(i) for i in self.lnotab ] ) + return ''.join(self.lnotab) +# ____________________________________________________________ +# Stack depth tracking def depth_UNPACK_SEQUENCE(count): return count-1 @@ -974,11 +465,14 @@ return depth_CALL_FUNCTION(argc)-2 def depth_CALL_METHOD(argc): return -argc-1 +def depth_CALL_LIKELY_BUILTIN(argc): + nargs = argc & 0xFF + return -nargs+1 def depth_MAKE_FUNCTION(argc): return -argc def depth_MAKE_CLOSURE(argc): - # XXX need to account for free variables too! - return -argc + raise InternalCompilerError("must special-case this in order to account" + " for the free variables") def depth_BUILD_SLICE(argc): if argc == 2: return -1 @@ -989,57 +483,14 @@ def depth_DUP_TOPX(argc): return argc -DEPTH_OP_TRACKER = { - "UNPACK_SEQUENCE" : depth_UNPACK_SEQUENCE, - "BUILD_TUPLE" : depth_BUILD_TUPLE, - "BUILD_LIST" : depth_BUILD_LIST, - "CALL_FUNCTION" : depth_CALL_FUNCTION, - "CALL_FUNCTION_VAR" : depth_CALL_FUNCTION_VAR, - "CALL_FUNCTION_KW" : depth_CALL_FUNCTION_KW, - "CALL_FUNCTION_VAR_KW" : depth_CALL_FUNCTION_VAR_KW, - "MAKE_FUNCTION" : depth_MAKE_FUNCTION, - "MAKE_CLOSURE" : depth_MAKE_CLOSURE, - "BUILD_SLICE" : depth_BUILD_SLICE, - "DUP_TOPX" : depth_DUP_TOPX, - } - -class StackDepthTracker: - # 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! - - def findDepth(self, insts, debug=0): - depth = 0 - maxDepth = 0 - for i in insts: - opname = i.op - if debug: - print i, - delta = self.effect.get(opname, sys.maxint) - if delta != sys.maxint: - depth = depth + delta - else: - # now check patterns - for pat, pat_delta in self.patterns: - if opname[:len(pat)] == pat: - delta = pat_delta - depth = depth + delta - break - # if we still haven't found a match - if delta == sys.maxint: - meth = DEPTH_OP_TRACKER.get( opname, None ) - if meth is not None: - assert isinstance(i, InstrInt) - depth = depth + meth(i.intval) - if depth > maxDepth: - maxDepth = depth - if debug: - print depth, maxDepth - return maxDepth - +def setup_stack_depth_tracker(): effect = { + 'STOP_CODE': 0, + 'NOP': 0, + 'EXTENDED_ARG': 0, 'POP_TOP': -1, 'DUP_TOP': 1, + 'SLICE+0': 0, 'SLICE+1': -1, 'SLICE+2': -1, 'SLICE+3': -2, @@ -1053,36 +504,104 @@ 'DELETE_SLICE+3': -3, 'STORE_SUBSCR': -3, 'DELETE_SUBSCR': -2, - # PRINT_EXPR? + 'PRINT_EXPR': -1, 'PRINT_ITEM': -1, - 'RETURN_VALUE': -1, + 'PRINT_ITEM_TO': -2, + 'PRINT_NEWLINE': 0, + 'PRINT_NEWLINE_TO': -1, 'YIELD_VALUE': -1, 'EXEC_STMT': -3, 'BUILD_CLASS': -2, 'STORE_NAME': -1, + 'DELETE_NAME': 0, 'STORE_ATTR': -2, 'DELETE_ATTR': -1, 'STORE_GLOBAL': -1, + 'DELETE_GLOBAL': 0, + 'STORE_DEREF': -1, 'BUILD_MAP': 1, 'COMPARE_OP': -1, 'STORE_FAST': -1, + 'DELETE_FAST': 0, 'IMPORT_STAR': -1, 'IMPORT_NAME': 0, 'IMPORT_FROM': 1, 'LOAD_ATTR': 0, # unlike other loads - # close enough... - 'SETUP_EXCEPT': 3, - 'SETUP_FINALLY': 3, + 'GET_ITER': 0, 'FOR_ITER': 1, - 'WITH_CLEANUP': 3, + 'BREAK_LOOP': 0, + 'CONTINUE_LOOP': 0, + 'POP_BLOCK': 0, + 'END_FINALLY': -3, + 'WITH_CLEANUP': -1, 'LOOKUP_METHOD': 1, 'LIST_APPEND': -2, } # use pattern match patterns = [ + ('ROT_', 0), + ('UNARY_', 0), ('BINARY_', -1), + ('INPLACE_', -1), ('LOAD_', 1), + ('SETUP_', 0), + ('JUMP_IF_', 0), ] + def gettracker(opname): + # first look for an explicit tracker + try: + return globals()['depth_' + opname] + except KeyError: + pass + # then look for an explicit constant effect + try: + delta = effect[opname] + except KeyError: + # then do pattern matching + for pat, delta in patterns: + if opname.startswith(pat): + break + else: + raise InternalCompilerError("no stack effect registered for " + + opname) + def tracker(argc): + return delta + return tracker + + effect_along_jump = { + 'JUMP_FORWARD': 0, + 'JUMP_ABSOLUTE': 0, + 'JUMP_IF_TRUE': 0, + 'JUMP_IF_FALSE': 0, + 'FOR_ITER': -1, + 'SETUP_LOOP': 0, + 'SETUP_EXCEPT': 3, + 'SETUP_FINALLY': 3, + } + def geteffect_jump(opname): + try: + return effect_along_jump[opname] + except KeyError: + raise InternalCompilerError("no stack effect registered for " + "the branch of " + opname) -findDepth = StackDepthTracker().findDepth + for opname, opcode in pythonopcode.opmap.items(): + if opname in ops_interrupt_unconditionally: + continue + if opname not in ops_jump_unconditionally: + # the effect on the stack depth when execution goes from + # this instruction to the next one + DEPTH_OP_TRACKER[opcode] = gettracker(opname) + if opname in ops_jumps: + DEPTH_OP_EFFECT_ALONG_JUMP[opcode] = geteffect_jump(opname) + + +ops_interrupt_unconditionally = ('RETURN_VALUE', 'RAISE_VARARGS', + 'CONTINUE_LOOP', 'BREAK_LOOP') +ops_jump_unconditionally = ('JUMP_ABSOLUTE', 'JUMP_FORWARD') +ops_jumps = list(PyFlowGraph.hasjrel) + list(PyFlowGraph.hasjabs) + +DEPTH_OP_TRACKER = {} +DEPTH_OP_EFFECT_ALONG_JUMP = {} +setup_stack_depth_tracker() Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py Mon Jan 7 19:35:37 2008 @@ -161,7 +161,9 @@ return self.graph.emitop_obj( inst, obj ) def emitop_code(self, inst, gen): - return self.graph.emitop_code( inst, gen ) + code = gen.getCode() + w_code = self.space.wrap(code) + return self.graph.emitop_obj( inst, w_code ) def emitop_int(self, inst, op): assert isinstance(op, int) @@ -170,14 +172,10 @@ def emitop_block(self, inst, block): return self.graph.emitop_block( inst, block ) - def nextBlock(self, block=None ): + def nextBlock(self, block ): """graph delegation""" return self.graph.nextBlock( block ) - def startBlock(self, block ): - """graph delegation""" - return self.graph.startBlock( block ) - def newBlock(self): """graph delegation""" return self.graph.newBlock() @@ -315,8 +313,6 @@ def visitFunction(self, node): self._visitFuncOrLambda(node, isLambda=0) space = self.space - if not space.is_w(node.w_doc, space.w_None): - self.setDocstring(node.w_doc) self.storeName(node.name, node.lineno) def visitLambda(self, node): @@ -392,11 +388,10 @@ self.set_lineno(test) nextTest = self.newBlock() test.opt_accept_jump_if(self, False, nextTest) - self.nextBlock() self.emit('POP_TOP') suite.accept( self ) self.emitop_block('JUMP_FORWARD', end) - self.startBlock(nextTest) + self.nextBlock(nextTest) self.emit('POP_TOP') if node.else_: node.else_.accept( self ) @@ -422,15 +417,14 @@ self.set_lineno(node, force=True) if is_constant_true(self.space, node.test): # "while 1:" - self.nextBlock() + pass else: node.test.opt_accept_jump_if(self, False, else_) - self.nextBlock() self.emit('POP_TOP') node.body.accept( self ) self.emitop_block('JUMP_ABSOLUTE', loop) - self.startBlock(else_) # or just the POPs if not else clause + self.nextBlock(else_) # or just the POPs if not else clause self.emit('POP_TOP') self.emit('POP_BLOCK') self.setups.pop() @@ -475,7 +469,6 @@ if kind == LOOP: self.set_lineno(node) self.emitop_block('JUMP_ABSOLUTE', block) - self.nextBlock() elif kind == EXCEPT or kind == TRY_FINALLY: self.set_lineno(node) # find the block that starts the loop @@ -492,7 +485,6 @@ if kind != LOOP: raise SyntaxError( "'continue' not properly in loop", node.lineno) self.emitop_block('CONTINUE_LOOP', loop_block) - self.nextBlock() elif kind == END_FINALLY: msg = "'continue' not supported inside 'finally' clause" raise SyntaxError( msg, node.lineno ) @@ -502,7 +494,6 @@ for child in node.nodes[:-1]: child.accept( self ) self.emitop_block(jump, end) - self.nextBlock() self.emit('POP_TOP') node.nodes[-1].accept( self ) self.nextBlock(end) @@ -585,7 +576,6 @@ self.emit('ROT_THREE') self.emitop('COMPARE_OP', op) self.emitop_block('JUMP_IF_FALSE', cleanup) - self.nextBlock() self.emit('POP_TOP') # now do the last comparison if node.ops: @@ -595,7 +585,7 @@ if len(node.ops) > 1: end = self.newBlock() self.emitop_block('JUMP_FORWARD', end) - self.startBlock(cleanup) + self.nextBlock(cleanup) self.emit('ROT_TWO') self.emit('POP_TOP') self.nextBlock(end) @@ -634,11 +624,11 @@ if cont: skip_one = self.newBlock() self.emitop_block('JUMP_FORWARD', skip_one) - self.startBlock(cont) + self.nextBlock(cont) self.emit('POP_TOP') self.nextBlock(skip_one) self.emitop_block('JUMP_ABSOLUTE', start) - self.startBlock(anchor) + self.nextBlock(anchor) self._implicitNameOp('DELETE', tmpname) self.__list_count = self.__list_count - 1 @@ -652,7 +642,6 @@ self.nextBlock(start) self.set_lineno(node, force=True) self.emitop_block('FOR_ITER', anchor) - self.nextBlock() node.assign.accept( self ) return start, anchor @@ -711,11 +700,11 @@ if cont: skip_one = self.newBlock() self.emitop_block('JUMP_FORWARD', skip_one) - self.startBlock(cont) + self.nextBlock(cont) self.emit('POP_TOP') self.nextBlock(skip_one) self.emitop_block('JUMP_ABSOLUTE', start) - self.startBlock(anchor) + self.nextBlock(anchor) self.emitop_obj('LOAD_CONST', self.space.w_None) def _visitGenExprFor(self, node): @@ -731,7 +720,6 @@ self.nextBlock(start) self.set_lineno(node, force=True) self.emitop_block('FOR_ITER', anchor) - self.nextBlock() node.assign.accept( self ) return start, anchor @@ -752,9 +740,7 @@ # XXX AssertionError appears to be special case -- it is always # loaded as a global even if there is a local name. I guess this # is a sort of renaming op. - self.nextBlock() node.test.opt_accept_jump_if(self, True, end) - self.nextBlock() self.emit('POP_TOP') self.emitop('LOAD_GLOBAL', 'AssertionError') if node.fail: @@ -795,10 +781,9 @@ self.emit('POP_BLOCK') self.setups.pop() self.emitop_block('JUMP_FORWARD', lElse) - self.startBlock(handlers) + self.nextBlock(handlers) last = len(node.handlers) - 1 - next = None for expr, target, body in node.handlers: if expr: self.set_lineno(expr) @@ -807,7 +792,6 @@ self.emitop('COMPARE_OP', 'exception match') next = self.newBlock() self.emitop_block('JUMP_IF_FALSE', next) - self.nextBlock() self.emit('POP_TOP') else: next = None @@ -819,8 +803,8 @@ self.emit('POP_TOP') body.accept( self ) self.emitop_block('JUMP_FORWARD', end) - self.nextBlock(next) if expr: # XXX + self.nextBlock(next) self.emit('POP_TOP') self.emit('END_FINALLY') if node.else_: @@ -1430,7 +1414,7 @@ CodeGenerator.__init__(self, space, graph) self.optimized = 1 - if not isLambda and not space.is_w(func.w_doc, space.w_None): + if not isLambda: self.setDocstring(func.w_doc) if func.varargs: @@ -1444,7 +1428,6 @@ return self.module def finish(self): - self.graph.startExitBlock() if not self.isLambda: self.emitop_obj('LOAD_CONST', self.space.w_None) self.emit('RETURN_VALUE') @@ -1510,14 +1493,12 @@ CodeGenerator.__init__(self, space, graph) self.graph.setFlag(CO_NEWLOCALS) - if not space.is_w(klass.w_doc, space.w_None): - self.setDocstring(klass.w_doc) + self.setDocstring(klass.w_doc) def get_module(self): return self.module def finish(self): - self.graph.startExitBlock() self.emit('LOAD_LOCALS') self.emit('RETURN_VALUE') Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Mon Jan 7 19:35:37 2008 @@ -325,6 +325,11 @@ """doc"""; print 1 a=1 ''', "doc"), + (''' + class Foo(object): pass + foo = Foo() + exec "'moduledoc'" in foo.__dict__ + ''', "moduledoc"), ]: yield self.simple_test, source, "foo.__doc__", expected @@ -363,12 +368,35 @@ yield self.st, "k=2; x = sum(n+2 for n in [6, 1, k])", 'x', 15 yield self.st, "k=2; x = sum(n+2 for n in (6, 1, k))", 'x', 15 + def test_closure(self): + decl = py.code.Source(""" + def make_adder(n): + def add(m): + return n + m + return add + """) + decl = str(decl) + "\n" + yield self.st, decl + "x = make_adder(40)(2)", 'x', 42 + + def test_try_except_finally(self): + yield self.simple_test, """ + try: + x = 5 + try: + if x > 2: + raise ValueError + finally: + x += 1 + except ValueError: + x *= 7 + """, 'x', 42 + def test_pprint(self): # a larger example that showed a bug with jumps # over more than 256 bytes decl = py.code.Source(""" def _safe_repr(object, context, maxlevels, level): - typ = _type(object) + typ = type(object) if typ is str: if 'locale' not in _sys.modules: return repr(object), True, False @@ -392,7 +420,7 @@ if issubclass(typ, dict) and r is dict.__repr__: if not object: return "{}", True, False - objid = _id(object) + objid = id(object) if maxlevels and level > maxlevels: return "{...}", False, objid in context if objid in context: @@ -412,7 +440,7 @@ if krecur or vrecur: recursive = True del context[objid] - return "{%s}" % _commajoin(components), readable, recursive + return "{%s}" % ', '.join(components), readable, recursive if (issubclass(typ, list) and r is list.__repr__) or \ (issubclass(typ, tuple) and r is tuple.__repr__): @@ -426,7 +454,7 @@ if not object: return "()", True, False format = "(%s)" - objid = _id(object) + objid = id(object) if maxlevels and level > maxlevels: return format % "...", False, objid in context if objid in context: @@ -445,10 +473,13 @@ if orecur: recursive = True del context[objid] - return format % _commajoin(components), readable, recursive + return format % ', '.join(components), readable, recursive rep = repr(object) return rep, (rep and not rep.startswith('<')), False """) decl = str(decl) + '\n' - yield self.st, decl + 'x=_safe_repr([5], {}, 3, 0)', 'x', '[5]' + g = {} + exec decl in g + expected = g['_safe_repr']([5], {}, 3, 0) + yield self.st, decl + 'x=_safe_repr([5], {}, 3, 0)', 'x', expected From arigo at codespeak.net Mon Jan 7 19:36:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 19:36:02 +0100 (CET) Subject: [pypy-svn] r50434 - pypy/branch/simpler-pyassem Message-ID: <20080107183602.030A716846C@codespeak.net> Author: arigo Date: Mon Jan 7 19:36:02 2008 New Revision: 50434 Removed: pypy/branch/simpler-pyassem/ Log: Branch merged. From arigo at codespeak.net Mon Jan 7 19:48:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 19:48:37 +0100 (CET) Subject: [pypy-svn] r50435 - pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test Message-ID: <20080107184837.B3F21168480@codespeak.net> Author: arigo Date: Mon Jan 7 19:48:37 2008 New Revision: 50435 Removed: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_peepholer.py Log: This no longer makes much sense. From arigo at codespeak.net Mon Jan 7 20:10:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 20:10:36 +0100 (CET) Subject: [pypy-svn] r50436 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080107191036.2781E168480@codespeak.net> Author: arigo Date: Mon Jan 7 20:10:34 2008 New Revision: 50436 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: Test and fix. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 20:10:34 2008 @@ -494,10 +494,10 @@ 'SLICE+1': -1, 'SLICE+2': -1, 'SLICE+3': -2, - 'STORE_SLICE+0': -1, - 'STORE_SLICE+1': -2, - 'STORE_SLICE+2': -2, - 'STORE_SLICE+3': -3, + 'STORE_SLICE+0': -2, + 'STORE_SLICE+1': -3, + 'STORE_SLICE+2': -3, + 'STORE_SLICE+3': -4, 'DELETE_SLICE+0': -1, 'DELETE_SLICE+1': -2, 'DELETE_SLICE+2': -2, Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Mon Jan 7 20:10:34 2008 @@ -391,6 +391,15 @@ x *= 7 """, 'x', 42 + def test_while_loop(self): + yield self.simple_test, """ + comments = [42] + comment = '# foo' + while comment[:1] == '#': + comments[:0] = [comment] + comment = '' + """, 'comments', ['# foo', 42] + def test_pprint(self): # a larger example that showed a bug with jumps # over more than 256 bytes From arigo at codespeak.net Mon Jan 7 20:17:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 20:17:17 +0100 (CET) Subject: [pypy-svn] r50437 - pypy/branch/astcompilertests/pypy/interpreter/astcompiler Message-ID: <20080107191717.CAEE8168477@codespeak.net> Author: arigo Date: Mon Jan 7 20:17:17 2008 New Revision: 50437 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Log: Remove unnecessary lines. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 20:17:17 2008 @@ -529,8 +529,6 @@ 'LOAD_ATTR': 0, # unlike other loads 'GET_ITER': 0, 'FOR_ITER': 1, - 'BREAK_LOOP': 0, - 'CONTINUE_LOOP': 0, 'POP_BLOCK': 0, 'END_FINALLY': -3, 'WITH_CLEANUP': -1, From arigo at codespeak.net Mon Jan 7 20:33:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 20:33:18 +0100 (CET) Subject: [pypy-svn] r50438 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080107193318.8F1BB168429@codespeak.net> Author: arigo Date: Mon Jan 7 20:33:17 2008 New Revision: 50438 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Log: Toby Watson's dates. Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Mon Jan 7 20:33:17 2008 @@ -14,6 +14,7 @@ Carl Friedrich Bolz 12th-19th? Ermina Antonio Cuni 14th-19th? Ermina Maciej Fijalkowski 11th-20th Ermina (arrive at 10pm) +Toby Watson 12th-19th Ermina ==================== ============== ======================= People on the following list were present at previous sprints: From vinogradov at codespeak.net Mon Jan 7 20:59:56 2008 From: vinogradov at codespeak.net (vinogradov at codespeak.net) Date: Mon, 7 Jan 2008 20:59:56 +0100 (CET) Subject: [pypy-svn] r50439 - pypy/branch/ghop-ropes-classes/pypy/rlib/test Message-ID: <20080107195956.906791684D0@codespeak.net> Author: vinogradov Date: Mon Jan 7 20:59:56 2008 New Revision: 50439 Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Log: Add test for string case functions Modified: pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py ============================================================================== --- pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py (original) +++ pypy/branch/ghop-ropes-classes/pypy/rlib/test/test_ropewrapper.py Mon Jan 7 20:59:56 2008 @@ -63,7 +63,17 @@ def test_str(self): s1 = self.const("abc") assert str(s1) == "abc" - + + def test_str_case(self): + s1 = self.const("hello python") + assert s1.capitalize() == self.const("Hello python") + assert s1.islower() + assert not s1.isupper() + s2 = s1.upper() + assert s2 == self.const("HELLO PYTHON") + assert s2.lower() == s1 + s3 = self.const("Welcome to PyPy World") + assert s3.swapcase() == self.const("wELCOME TO pYpY wORLD") class AbstractRopeTest(object): def test_add_long(self): From arigo at codespeak.net Mon Jan 7 23:29:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 7 Jan 2008 23:29:33 +0100 (CET) Subject: [pypy-svn] r50441 - in pypy/branch/astcompilertests/pypy/interpreter: . astcompiler astcompiler/test Message-ID: <20080107222933.A60C01684E7@codespeak.net> Author: arigo Date: Mon Jan 7 23:29:32 2008 New Revision: 50441 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py pypy/branch/astcompilertests/pypy/interpreter/nestedscope.py pypy/branch/astcompilertests/pypy/interpreter/pycode.py Log: Fix for cleverness that I forgot from the old pyassem.py. The fix consists of removing the cleverness and fixing the interpreter instead; see comments about why I think it's a good idea. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pyassem.py Mon Jan 7 23:29:32 2008 @@ -35,11 +35,6 @@ # variables used only in nested scopes, are included here. self.freevars = [] self.cellvars = [] - # The closure list is used to track the order of cell - # variables and free variables in the resulting code object. - # The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both - # kinds of variables. - self.closure = [] self.varnames = list(argnames) # The bytecode we are building, as a list of characters self.co_code = [] @@ -143,6 +138,21 @@ list.append(name) return end + def _lookupClosureName(self, name): + """Return index of name in (self.cellvars + self.freevars) + """ + assert isinstance(name, str) + list = self.cellvars + for i in range(len(list)): + if list[i] == name: + return i + list = self.freevars + for i in range(len(list)): + if list[i] == name: + return len(self.cellvars) + i + raise InternalCompilerError("name '%s' not found in cell or free vars" + % name) + def _convert_LOAD_FAST(self, arg): self._lookupName(arg, self.names) return self._lookupName(arg, self.varnames) @@ -166,12 +176,12 @@ def _convert_DEREF(self, arg): self._lookupName(arg, self.names) - return self._lookupName(arg, self.closure) + return self._lookupClosureName(arg) _convert_LOAD_DEREF = _convert_DEREF _convert_STORE_DEREF = _convert_DEREF def _convert_LOAD_CLOSURE(self, arg): - return self._lookupName(arg, self.closure) + return self._lookupClosureName(arg) _cmp = list(pythonopcode.cmp_op) def _convert_COMPARE_OP(self, arg): Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Mon Jan 7 23:29:32 2008 @@ -378,6 +378,21 @@ decl = str(decl) + "\n" yield self.st, decl + "x = make_adder(40)(2)", 'x', 42 + decl = py.code.Source(""" + def f(a, g, e, c): + def b(n, d): + return (a, c, d, g, n) + def f(b, a): + return (a, b, c, g) + return (a, g, e, c, b, f) + A, G, E, C, B, F = f(6, 2, 8, 5) + A1, C1, D1, G1, N1 = B(7, 3) + A2, B2, C2, G2 = F(1, 4) + """) + decl = str(decl) + "\n" + yield self.st, decl, 'A,A1,A2,B2,C,C1,C2,D1,E,G,G1,G2,N1', \ + (6,6 ,4 ,1 ,5,5 ,5 ,3 ,8,2,2 ,2 ,7 ) + def test_try_except_finally(self): yield self.simple_test, """ try: Modified: pypy/branch/astcompilertests/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/nestedscope.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/nestedscope.py Mon Jan 7 23:29:32 2008 @@ -149,7 +149,8 @@ args_to_copy = self.pycode._args_as_cellvars for i in range(len(args_to_copy)): argnum = args_to_copy[i] - self.cells[i] = Cell(self.fastlocals_w[argnum]) + if argnum >= 0: + self.cells[i].set(self.fastlocals_w[argnum]) def getfreevarname(self, index): freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars Modified: pypy/branch/astcompilertests/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/pycode.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/pycode.py Mon Jan 7 23:29:32 2008 @@ -89,21 +89,25 @@ argcount += 1 if self.co_flags & CO_VARKEYWORDS: argcount += 1 - # the first few cell vars could shadow already-set arguments, - # in the same order as they appear in co_varnames + # Cell vars could shadow already-set arguments. + # astcompiler.pyassem used to be clever about the order of + # the variables in both co_varnames and co_cellvars, but + # it no longer is for the sake of simplicity. Moreover + # code objects loaded from CPython don't necessarily follow + # an order, which could lead to strange bugs if .pyc files + # produced by CPython are loaded by PyPy. Note that CPython + # contains the following bad-looking nested loops at *every* + # function call! argvars = self.co_varnames cellvars = self.co_cellvars - next = 0 - nextname = cellvars[0] - for i in range(argcount): - if argvars[i] == nextname: - # argument i has the same name as the next cell var - self._args_as_cellvars.append(i) - next += 1 - try: - nextname = cellvars[next] - except IndexError: - break # all cell vars initialized this way + for i in range(len(cellvars)): + cellname = cellvars[i] + for j in range(argcount): + if cellname == argvars[j]: + # argument j has the same name as the cell var i + while len(self._args_as_cellvars) <= i: + self._args_as_cellvars.append(-1) # pad + self._args_as_cellvars[i] = j co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace From arigo at codespeak.net Tue Jan 8 09:59:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jan 2008 09:59:07 +0100 (CET) Subject: [pypy-svn] r50443 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080108085907.D73FF168450@codespeak.net> Author: arigo Date: Tue Jan 8 09:59:06 2008 New Revision: 50443 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Log: Add Paul. Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/people.txt Tue Jan 8 09:59:06 2008 @@ -15,6 +15,7 @@ Antonio Cuni 14th-19th? Ermina Maciej Fijalkowski 11th-20th Ermina (arrive at 10pm) Toby Watson 12th-19th Ermina +Paul deGrandis 12th-19th Ermina ==================== ============== ======================= People on the following list were present at previous sprints: From fijal at codespeak.net Tue Jan 8 19:11:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Jan 2008 19:11:59 +0100 (CET) Subject: [pypy-svn] r50445 - pypy/dist/pypy/doc/discussion Message-ID: <20080108181159.1536A1684F3@codespeak.net> Author: fijal Date: Tue Jan 8 19:11:58 2008 New Revision: 50445 Added: pypy/dist/pypy/doc/discussion/ctypes_modules.txt (contents, props changed) Log: Add stub for ctypes_modules Added: pypy/dist/pypy/doc/discussion/ctypes_modules.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/ctypes_modules.txt Tue Jan 8 19:11:58 2008 @@ -0,0 +1,17 @@ +Few words what we need for ctypes-based pygame and how feasible it is +===================================================================== + +Quick recap for module evaluation: + +1. do we need callbacks? + +2. how sophisticated ctypes usage is (accessing of _objects?) + +3. any specific tricks + +4. does it has tests? + +5. dependencies + +6. does it depend on cpython c-api over ctypes? + From fijal at codespeak.net Tue Jan 8 19:31:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Jan 2008 19:31:53 +0100 (CET) Subject: [pypy-svn] r50446 - pypy/dist/pypy/doc/discussion Message-ID: <20080108183153.9D7D31684F7@codespeak.net> Author: fijal Date: Tue Jan 8 19:31:53 2008 New Revision: 50446 Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt Log: Few details about pygaem Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/ctypes_modules.txt (original) +++ pypy/dist/pypy/doc/discussion/ctypes_modules.txt Tue Jan 8 19:31:53 2008 @@ -15,3 +15,18 @@ 6. does it depend on cpython c-api over ctypes? +Pygame +====== + +1. yes, for various things, but basic functionality can be achieved without + +2. probably not + +3. not that I know of + +4. yes for tests, no for unittests + +5. numpy, but can live without, besides only C-level dependencies. On OS/X + it requires PyObjC. + +6. no From arigo at codespeak.net Tue Jan 8 19:42:29 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jan 2008 19:42:29 +0100 (CET) Subject: [pypy-svn] r50447 - in pypy/branch/astcompilertests/pypy/interpreter: . astcompiler/test Message-ID: <20080108184229.98A4B168464@codespeak.net> Author: arigo Date: Tue Jan 8 19:42:29 2008 New Revision: 50447 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py pypy/branch/astcompilertests/pypy/interpreter/pycode.py Log: Test and fix for another nested scopes bug. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Tue Jan 8 19:42:29 2008 @@ -507,3 +507,74 @@ exec decl in g expected = g['_safe_repr']([5], {}, 3, 0) yield self.st, decl + 'x=_safe_repr([5], {}, 3, 0)', 'x', expected + + def test_mapping_test(self): + decl = py.code.Source(""" + class X(object): + reference = {1:2, "key1":"value1", "key2":(1,2,3)} + key, value = reference.popitem() + other = {key:value} + key, value = reference.popitem() + inmapping = {key:value} + reference[key] = value + def _empty_mapping(self): + return {} + _full_mapping = dict + def assertEqual(self, x, y): + assert x == y + failUnlessRaises = staticmethod(raises) + def assert_(self, x): + assert x + def failIf(self, x): + assert not x + + def test_read(self): + # Test for read only operations on mapping + p = self._empty_mapping() + p1 = dict(p) #workaround for singleton objects + d = self._full_mapping(self.reference) + if d is p: + p = p1 + #Indexing + for key, value in self.reference.items(): + self.assertEqual(d[key], value) + knownkey = self.other.keys()[0] + self.failUnlessRaises(KeyError, lambda:d[knownkey]) + #len + self.assertEqual(len(p), 0) + self.assertEqual(len(d), len(self.reference)) + #has_key + for k in self.reference: + self.assert_(d.has_key(k)) + self.assert_(k in d) + for k in self.other: + self.failIf(d.has_key(k)) + self.failIf(k in d) + #cmp + self.assertEqual(cmp(p,p), 0) + self.assertEqual(cmp(d,d), 0) + self.assertEqual(cmp(p,d), -1) + self.assertEqual(cmp(d,p), 1) + #__non__zero__ + if p: self.fail("Empty mapping must compare to False") + if not d: self.fail("Full mapping must compare to True") + # keys(), items(), iterkeys() ... + def check_iterandlist(iter, lst, ref): + self.assert_(hasattr(iter, 'next')) + self.assert_(hasattr(iter, '__iter__')) + x = list(iter) + self.assert_(set(x)==set(lst)==set(ref)) + check_iterandlist(d.iterkeys(), d.keys(), self.reference.keys()) + check_iterandlist(iter(d), d.keys(), self.reference.keys()) + check_iterandlist(d.itervalues(), d.values(), self.reference.values()) + check_iterandlist(d.iteritems(), d.items(), self.reference.items()) + #get + key, value = d.iteritems().next() + knownkey, knownvalue = self.other.iteritems().next() + self.assertEqual(d.get(key, knownvalue), value) + self.assertEqual(d.get(knownkey, knownvalue), knownvalue) + self.failIf(knownkey in d) + return 42 + """) + decl = str(decl) + '\n' + yield self.simple_test, decl + 'r = test_read(X())', 'r', 42 Modified: pypy/branch/astcompilertests/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/pycode.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/pycode.py Tue Jan 8 19:42:29 2008 @@ -77,7 +77,6 @@ self.co_lnotab = lnotab self.hidden_applevel = hidden_applevel self.magic = magic - self._compute_fastcall() self._signature = cpython_code_signature(self) # Precompute what arguments need to be copied into cellvars self._args_as_cellvars = [] @@ -109,6 +108,8 @@ self._args_as_cellvars.append(-1) # pad self._args_as_cellvars[i] = j + self._compute_fastcall() + co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): @@ -166,11 +167,8 @@ return if self.co_flags & (CO_VARARGS | CO_VARKEYWORDS): return - if self.co_cellvars: - first_cellvar = self.co_cellvars[0] - for i in range(self.co_argcount): - if first_cellvar == self.co_varnames[i]: - return + if len(self._args_as_cellvars) > 0: + return self.do_fastcall = self.co_argcount From arigo at codespeak.net Tue Jan 8 20:10:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jan 2008 20:10:14 +0100 (CET) Subject: [pypy-svn] r50448 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080108191014.16D8816844D@codespeak.net> Author: arigo Date: Tue Jan 8 20:10:13 2008 New Revision: 50448 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py Log: An env var to configure the nursery size at run-time. In this way we can really measure a whole range of sizes on various machines and see if the theory matches the practice. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Tue Jan 8 20:10:13 2008 @@ -61,7 +61,9 @@ self.set_nursery_size(self.initial_nursery_size) # the GC is fully setup now. The rest can make use of it. if self.auto_nursery_size: - newsize = estimate_best_nursery_size() + newsize = nursery_size_from_env() + if newsize <= 0: + newsize = estimate_best_nursery_size() if newsize > 0: self.set_nursery_size(newsize) @@ -374,6 +376,22 @@ # ____________________________________________________________ +import os + +def nursery_size_from_env(): + value = os.environ.get('PYPY_GENERATIONGC_NURSERY') + if value: + if value[-1] in 'kK': + factor = 1024 + value = value[:-1] + else: + factor = 1 + try: + return int(value) * factor + except ValueError: + pass + return -1 + def best_nursery_size_for_L2cache(L2cache): if DEBUG_PRINT: llop.debug_print(lltype.Void, "CCC L2cache =", L2cache) @@ -387,7 +405,6 @@ """Try to estimate the best nursery size at run-time, depending on the machine we are running on. """ - import os L2cache = sys.maxint try: fd = os.open('/proc/cpuinfo', os.O_RDONLY, 0644) From fijal at codespeak.net Tue Jan 8 20:21:19 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 8 Jan 2008 20:21:19 +0100 (CET) Subject: [pypy-svn] r50449 - pypy/dist/pypy/doc/discussion Message-ID: <20080108192119.B92B51684EF@codespeak.net> Author: fijal Date: Tue Jan 8 20:21:19 2008 New Revision: 50449 Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt Log: Few details about sqlite Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/ctypes_modules.txt (original) +++ pypy/dist/pypy/doc/discussion/ctypes_modules.txt Tue Jan 8 20:21:19 2008 @@ -30,3 +30,19 @@ it requires PyObjC. 6. no + +Sqlite +====== + +1. yes, but I think it's not necessary + +2. no + +3. no + +4. yes + +5. datetime + +6. it passes py_object around in few places, not sure why (probably as an + opaque argument). From arigo at codespeak.net Tue Jan 8 22:31:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jan 2008 22:31:26 +0100 (CET) Subject: [pypy-svn] r50450 - in pypy/dist/pypy/objspace: . test Message-ID: <20080108213126.ABAF9168507@codespeak.net> Author: arigo Date: Tue Jan 8 22:31:25 2008 New Revision: 50450 Modified: pypy/dist/pypy/objspace/descroperation.py pypy/dist/pypy/objspace/test/test_descroperation.py Log: Give up on this and add logic similar to CPython to ensure a "consistent" ordering of instances of unrelated types. Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Tue Jan 8 22:31:25 2008 @@ -406,15 +406,37 @@ #print "WARNING, comparison by address!" w_id1 = space.id(w_obj1) w_id2 = space.id(w_obj2) + lt = space.is_true(space.lt(w_id1, w_id2)) else: - #print "WARNING, comparison by address!" - w_id1 = space.id(w_typ1) - w_id2 = space.id(w_typ2) - if space.is_true(space.lt(w_id1, w_id2)): + #print "WARNING, comparison by type name!" + + # the CPython rule is to compare type names; numbers are + # smaller. So we compare the types by the following key: + # (not_a_number_flag, type_name, type_id) + num1 = number_check(space, w_obj1) + num2 = number_check(space, w_obj2) + if num1 != num2: + lt = num1 # if obj1 is a number, it is Lower Than obj2 + else: + name1 = w_typ1.getname(space, "") + name2 = w_typ2.getname(space, "") + if name1 != name2: + lt = name1 < name2 + else: + w_id1 = space.id(w_typ1) + w_id2 = space.id(w_typ2) + lt = space.is_true(space.lt(w_id1, w_id2)) + if lt: return space.wrap(-1) else: return space.wrap(1) +def number_check(space, w_obj): + # avoid this as much as possible. It checks if w_obj "looks like" + # it might be a number-ish thing. + return (space.lookup(w_obj, '__int__') is not None or + space.lookup(w_obj, '__float__') is not None) + # regular methods def helpers def _make_binop_impl(symbol, specialnames): Modified: pypy/dist/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_descroperation.py (original) +++ pypy/dist/pypy/objspace/test/test_descroperation.py Tue Jan 8 22:31:25 2008 @@ -280,3 +280,35 @@ x = X() x.__class__ = Y raises(AttributeError, getattr, x, 'a') + + def test_silly_but_consistent_order(self): + # incomparable objects sort by type name :-/ + class A(object): pass + class zz(object): pass + assert A() < zz() + assert zz() > A() + # if in doubt, CPython sorts numbers before non-numbers + assert 0 < () + assert 0L < () + assert 0.0 < () + assert 0j < () + assert 0 < [] + assert 0L < [] + assert 0.0 < [] + assert 0j < [] + assert 0 < A() + assert 0L < A() + assert 0.0 < A() + assert 0j < A() + assert 0 < zz() + assert 0L < zz() + assert 0.0 < zz() + assert 0j < zz() + # what if the type name is the same... whatever, but + # be consistent + a1 = A() + a2 = A() + class A(object): pass + a3 = A() + a4 = A() + assert (a1 < a3) == (a1 < a4) == (a2 < a3) == (a2 < a4) From arigo at codespeak.net Tue Jan 8 22:45:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 8 Jan 2008 22:45:44 +0100 (CET) Subject: [pypy-svn] r50451 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080108214544.9090E1684FF@codespeak.net> Author: arigo Date: Tue Jan 8 22:45:44 2008 New Revision: 50451 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: Test and fix - just reordering a few lines of code. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py Tue Jan 8 22:45:44 2008 @@ -1375,7 +1375,10 @@ self.emit('PRINT_EXPR') class AbstractFunctionCode(CodeGenerator): - def __init__(self, space, func, isLambda, mod): + def __init__(self, space, scope, func, isLambda, mod): + assert scope is not None + self.scope = scope + self.localsfullyknown = self.scope.locals_fully_known() self.module = mod if isLambda: name = "" @@ -1414,6 +1417,9 @@ CodeGenerator.__init__(self, space, graph) self.optimized = 1 + self.graph.setFreeVars(self.scope.get_free_vars_in_scope()) + self.graph.setCellVars(self.scope.get_cell_vars()) + if not isLambda: self.setDocstring(func.w_doc) @@ -1459,13 +1465,8 @@ class FunctionCodeGenerator(AbstractFunctionCode): def __init__(self, space, func, isLambda, mod): - assert func.scope is not None - self.scope = func.scope - self.localsfullyknown = self.scope.locals_fully_known() - AbstractFunctionCode.__init__(self, space, func, isLambda, mod) - - self.graph.setFreeVars(self.scope.get_free_vars_in_scope()) - self.graph.setCellVars(self.scope.get_cell_vars()) + AbstractFunctionCode.__init__(self, space, func.scope, + func, isLambda, mod) if self.scope.generator: self.graph.setFlag(CO_GENERATOR) if self.scope.return_with_arg is not None: @@ -1476,12 +1477,7 @@ class GenExprCodeGenerator(AbstractFunctionCode): def __init__(self, space, gexp, mod): - assert gexp.scope is not None - self.scope = gexp.scope - self.localsfullyknown = self.scope.locals_fully_known() - AbstractFunctionCode.__init__(self, space, gexp, 1, mod) - self.graph.setFreeVars(self.scope.get_free_vars_in_scope()) - self.graph.setCellVars(self.scope.get_cell_vars()) + AbstractFunctionCode.__init__(self, space, gexp.scope, gexp, 1, mod) self.graph.setFlag(CO_GENERATOR) class AbstractClassCode(CodeGenerator): Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Tue Jan 8 22:45:44 2008 @@ -393,6 +393,16 @@ yield self.st, decl, 'A,A1,A2,B2,C,C1,C2,D1,E,G,G1,G2,N1', \ (6,6 ,4 ,1 ,5,5 ,5 ,3 ,8,2,2 ,2 ,7 ) + decl = py.code.Source(""" + def f((a, b)): + def g((c, d)): + return (a, b, c, d) + return g + x = f((1, 2))((3, 4)) + """) + decl = str(decl) + "\n" + yield self.st, decl, 'x', (1, 2, 3, 4) + def test_try_except_finally(self): yield self.simple_test, """ try: From cfbolz at codespeak.net Wed Jan 9 00:46:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Jan 2008 00:46:17 +0100 (CET) Subject: [pypy-svn] r50453 - pypy/dist/pypy/annotation Message-ID: <20080108234617.2F580168506@codespeak.net> Author: cfbolz Date: Wed Jan 9 00:46:16 2008 New Revision: 50453 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/model.py Log: store the debugging info that SomeObjects keep into the bookkeeper, so that not all of it is kept alive across test runs. Should reduce memory usage of test runs dramatically. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Wed Jan 9 00:46:16 2008 @@ -179,6 +179,9 @@ self.stats = Stats(self) + # used in SomeObject.__new__ for keeping debugging info + self._someobject_coming_from = {} + delayed_imports() def count(self, category, *args): Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Wed Jan 9 00:46:16 2008 @@ -114,7 +114,6 @@ # for debugging, record where each instance comes from # this is disabled if DEBUG is set to False - _coming_from = {} def __new__(cls, *args, **kw): self = super(SomeObject, cls).__new__(cls, *args, **kw) if DEBUG: @@ -124,20 +123,26 @@ except AttributeError: pass else: - SomeObject._coming_from[id(self)] = position_key, None + bookkeeper._someobject_coming_from[id(self)] = position_key, None return self def origin(self): - return SomeObject._coming_from.get(id(self), (None, None))[0] - def set_origin(self, nvalue): - SomeObject._coming_from[id(self)] = nvalue, self.caused_by_merge - origin = property(origin, set_origin) - del set_origin + bookkeeper = pypy.annotation.bookkeeper.getbookkeeper() + if bookkeeper is None: + return None + return bookkeeper._someobject_coming_from.get(id(self), (None, None))[0] + origin = property(origin) def caused_by_merge(self): - return SomeObject._coming_from.get(id(self), (None, None))[1] + bookkeeper = pypy.annotation.bookkeeper.getbookkeeper() + if bookkeeper is None: + return None + return bookkeeper._someobject_coming_from.get(id(self), (None, None))[1] def set_caused_by_merge(self, nvalue): - SomeObject._coming_from[id(self)] = self.origin, nvalue + bookkeeper = pypy.annotation.bookkeeper.getbookkeeper() + if bookkeeper is None: + return + bookkeeper._someobject_coming_from[id(self)] = self.origin, nvalue caused_by_merge = property(caused_by_merge, set_caused_by_merge) del set_caused_by_merge From cfbolz at codespeak.net Wed Jan 9 01:22:31 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Jan 2008 01:22:31 +0100 (CET) Subject: [pypy-svn] r50454 - pypy/dist/pypy/doc/discussion Message-ID: <20080109002231.4008A16850B@codespeak.net> Author: cfbolz Date: Wed Jan 9 01:22:30 2008 New Revision: 50454 Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt Log: add pyopengl Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/ctypes_modules.txt (original) +++ pypy/dist/pypy/doc/discussion/ctypes_modules.txt Wed Jan 9 01:22:30 2008 @@ -1,9 +1,9 @@ -Few words what we need for ctypes-based pygame and how feasible it is -===================================================================== +what is needed for various ctypes-based modules and how feasible they are +========================================================================== Quick recap for module evaluation: -1. do we need callbacks? +1. does the module use callbacks? 2. how sophisticated ctypes usage is (accessing of _objects?) @@ -31,6 +31,23 @@ 6. no + +PyOpenGL +======== + +1. yes, for GLX, but not for the core functionality + +2. probably not + +3. all the code is auto-generated + +4. it has example programs, no tests + +5. numpy, but can live without it. can use various surfaces (including pygame) to draw on + +6. no + + Sqlite ====== From cfbolz at codespeak.net Wed Jan 9 14:19:42 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 9 Jan 2008 14:19:42 +0100 (CET) Subject: [pypy-svn] r50455 - pypy/dist/pypy/translator/c Message-ID: <20080109131942.663C51684FC@codespeak.net> Author: cfbolz Date: Wed Jan 9 14:19:41 2008 New Revision: 50455 Modified: pypy/dist/pypy/translator/c/genc.py Log: a best-effort solution to cleaning up the shared libraries that genc loads Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Wed Jan 9 14:19:41 2008 @@ -161,6 +161,30 @@ return db +class ModuleWithCleanup(object): + def __init__(self, mod): + self.__dict__['mod'] = mod + + def __getattr__(self, name): + mod = self.__dict__['mod'] + return getattr(mod, name) + + def __setattr__(self, name, val): + mod = self.__dict__['mod'] + setattr(mod, name, val) + + def __del__(self): + import sys + from _ctypes import dlclose + # XXX fish fish fish + mod = self.__dict__['mod'] + dlclose(mod._lib._handle) + try: + del sys.modules[mod.__name__] + except KeyError: + pass + + class CExtModuleBuilder(CBuilder): standalone = False _module = None @@ -224,7 +248,7 @@ assert not self._module self._make_wrapper_module() if not isolated: - mod = self._module_path.pyimport() + mod = ModuleWithCleanup(self._module_path.pyimport()) else: mod = isolate.Isolate((str(self._module_path.dirpath()), self._module_path.purebasename)) From fijal at codespeak.net Wed Jan 9 15:26:40 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Jan 2008 15:26:40 +0100 (CET) Subject: [pypy-svn] r50456 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080109142640.12796168458@codespeak.net> Author: fijal Date: Wed Jan 9 15:26:39 2008 New Revision: 50456 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Log: s/if/elif/ Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Wed Jan 9 15:26:39 2008 @@ -209,7 +209,7 @@ else: raise OperationError(space.w_TypeError, w( "Expected structure, array or simple type")) - if tp == "c": + elif tp == "c": s = space.str_w(w_arg) if len(s) != 1: raise OperationError(space.w_ValueError, w( From fijal at codespeak.net Wed Jan 9 15:28:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Jan 2008 15:28:01 +0100 (CET) Subject: [pypy-svn] r50457 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080109142801.2CAA7168458@codespeak.net> Author: fijal Date: Wed Jan 9 15:28:00 2008 New Revision: 50457 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Log: Strike down buggy and untranslatable __new__ (not used anyway) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Wed Jan 9 15:28:00 2008 @@ -94,15 +94,8 @@ self.ll_array = lltype.nullptr(rffi.VOIDP.TO) free.unwrap_spec = ['self', ObjSpace] - -def descr_new_array_instance(space, w_type, w_shape, w_size_or_iterable): - w_shape = space.interp_w(W_Array, w_shape) - return space.wrap(W_ArrayInstance(space, w_shape, w_size_or_iterable)) -descr_new_array_instance.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root] - W_ArrayInstance.typedef = TypeDef( 'ArrayInstance', - __new__ = interp2app(descr_new_array_instance), __setitem__ = interp2app(W_ArrayInstance.setitem), __getitem__ = interp2app(W_ArrayInstance.getitem), buffer = GetSetProperty(W_ArrayInstance.getbuffer), From fijal at codespeak.net Wed Jan 9 15:54:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Jan 2008 15:54:08 +0100 (CET) Subject: [pypy-svn] r50458 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080109145408.19E87168441@codespeak.net> Author: fijal Date: Wed Jan 9 15:54:08 2008 New Revision: 50458 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: * Support for array.fromaddress * Few fixes. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Wed Jan 9 15:54:08 2008 @@ -43,6 +43,10 @@ w_item, None) return space.wrap(result) + def fromaddress(self, space, address, length): + return space.wrap(W_ArrayInstance(space, self, length, address)) + fromaddress.unwrap_spec = ['self', ObjSpace, int, int] + def descr_new_array(space, w_type, of): _get_type(space, of) return space.wrap(W_Array(space, of)) @@ -52,20 +56,25 @@ __new__ = interp2app(descr_new_array, unwrap_spec=[ObjSpace, W_Root, str]), __call__ = interp2app(W_Array.descr_call, unwrap_spec=['self', ObjSpace, W_Root]), + fromaddress = interp2app(W_Array.fromaddress), of = interp_attrproperty('of', W_Array), ) W_Array.typedef.acceptable_as_base_class = False class W_ArrayInstance(Wrappable): - def __init__(self, space, shape, length): + def __init__(self, space, shape, length, address=0): self.ll_array = lltype.nullptr(rffi.VOIDP.TO) self.alloced = False - self.shape = shape self.length = length - size = shape.itemsize * length - self.ll_array = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', - zero=True) + self.shape = shape + if address > 0: + self.ll_array = rffi.cast(rffi.VOIDP, address) + else: + size = shape.itemsize * length + self.ll_array = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', + zero=True) + # XXX don't allow negative indexes, nor slices Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py Wed Jan 9 15:54:08 2008 @@ -68,16 +68,14 @@ def descr_call(self, space, __args__): args_w, kwargs_w = __args__.unpack() if args_w: - if len(args_w) > 1: - raise OperationError( - space.w_TypeError, - space.wrap("Can give at most one non-keyword argument")) - if kwargs_w: - raise OperationError( - space.w_TypeError, - space.wrap("Keyword arguments not allowed when passing address argument")) - return space.wrap(W_StructureInstance(space, self, args_w[0], None)) - return space.wrap(W_StructureInstance(space, self, None, kwargs_w)) + raise OperationError( + space.w_TypeError, + space.wrap("Structure accepts only keyword arguments as field initializers")) + return space.wrap(W_StructureInstance(space, self, 0, kwargs_w)) + + def fromaddress(self, space, address): + return space.wrap(W_StructureInstance(space, self, address, None)) + fromaddress.unwrap_spec = ['self', ObjSpace, int] def descr_new_structure(space, w_type, w_fields): return space.wrap(W_Structure(space, w_fields)) @@ -87,6 +85,7 @@ __new__ = interp2app(descr_new_structure), __call__ = interp2app(W_Structure.descr_call, unwrap_spec=['self', ObjSpace, Arguments]), + fromaddress = interp2app(W_Structure.fromaddress) ) W_Structure.typedef.acceptable_as_base_class = False @@ -109,11 +108,11 @@ return OperationError(w_exception, space.wrap(reason)) class W_StructureInstance(Wrappable): - def __init__(self, space, shape, w_address, fieldinits_w): + def __init__(self, space, shape, address, fieldinits_w): self.free_afterwards = False self.shape = shape - if w_address is not None: - self.ll_buffer = rffi.cast(rffi.VOIDP, space.int_w(w_address)) + if address != 0: + self.ll_buffer = rffi.cast(rffi.VOIDP, address) else: self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, shape.size, flavor='raw', zero=True) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Wed Jan 9 15:54:08 2008 @@ -97,6 +97,13 @@ return x; } + int* allocate_array() + { + int *res = (int*)malloc(sizeof(int)); + res[0] = 3; + return res; + } + ''')) return compile_c_module([c_file], 'x', ExternalCompilationInfo()) prepare_c_example = staticmethod(prepare_c_example) @@ -211,10 +218,10 @@ ("tm_isdst", 'i')]) libc = _ffi.CDLL('libc.so.6') gmtime = libc.ptr('gmtime', ['P'], 'P') - t = Tm(gmtime(x)) + t = Tm.fromaddress(gmtime(x)) assert t.tm_year == 70 assert t.tm_sec == 1 - assert t.tm_min == 2 + assert t.tm_min == 2 x.free() def test_nested_structures(self): @@ -224,13 +231,13 @@ X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) next = X(next=None, x3='x') x = X(next=next, x1=1, x2=2, x3='x') - assert X(x.next).x3 == 'x' + assert X.fromaddress(x.next).x3 == 'x' x.free() next.free() create_double_struct = lib.ptr("create_double_struct", [], 'P') x = create_double_struct() - x = X(x) - assert X(x.next).x2 == 3 + x = X.fromaddress(x) + assert X.fromaddress(x.next).x2 == 3 free_double_struct = lib.ptr("free_double_struct", ['P'], None) free_double_struct(x) @@ -266,7 +273,7 @@ get_array_elem_s = lib.ptr('get_array_elem_s', ['P', 'i'], 'P') ptr1 = get_array_elem_s(a, 0) assert ptr1 is None - assert X(get_array_elem_s(a, 1)).x2 == 3 + assert X.fromaddress(get_array_elem_s(a, 1)).x2 == 3 assert get_array_elem_s(a, 1) == x.buffer x.free() a.free() @@ -342,3 +349,11 @@ assert _ffi.sizeof(k) == s assert _ffi.alignment(k) == a + def test_array_addressof(self): + import _ffi + lib = _ffi.CDLL(self.lib_name) + alloc = lib.ptr('allocate_array', [], 'P') + A = _ffi.Array('i') + a = A.fromaddress(alloc(), 1) + assert a[0] == 3 + # a.free() - don't free as ll2ctypes is complaining massively From fijal at codespeak.net Wed Jan 9 16:08:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Jan 2008 16:08:27 +0100 (CET) Subject: [pypy-svn] r50459 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080109150827.4C9BF168477@codespeak.net> Author: fijal Date: Wed Jan 9 16:08:24 2008 New Revision: 50459 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Log: Fix translation, bad carl Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Wed Jan 9 16:08:24 2008 @@ -9,7 +9,7 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror -from pypy.module._ffi.structure import native_fmttable +from pypy.module._ffi.structure import native_fmttable, segfault_exception from pypy.module._ffi.interp_ffi import unwrap_value, wrap_value, _get_type def push_elem(ll_array, pos, value): From exarkun at codespeak.net Wed Jan 9 20:05:54 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 9 Jan 2008 20:05:54 +0100 (CET) Subject: [pypy-svn] r50467 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20080109190554.23C62168511@codespeak.net> Author: exarkun Date: Wed Jan 9 20:05:50 2008 New Revision: 50467 Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Log: Skip some parsing tests by using the py.test skip API, rather than writing to stdout and not yielding the test from the test generator Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Wed Jan 9 20:05:50 2008 @@ -79,7 +79,8 @@ if fname in SKIP_ALWAYS: continue if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE: - print "Skipping", fname + yield lambda: py.test.skip( + "Grammar mismatch and %s is not native" % (fname,)) continue abspath = osp.join(samples_dir, fname) yield check_parse, abspath From arigo at codespeak.net Wed Jan 9 20:10:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jan 2008 20:10:20 +0100 (CET) Subject: [pypy-svn] r50468 - in pypy/branch/astcompilertests/pypy/interpreter/astcompiler: . test Message-ID: <20080109191020.EDC76168512@codespeak.net> Author: arigo Date: Wed Jan 9 20:10:19 2008 New Revision: 50468 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Log: Test and fix for lib-python's test_trace. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/pycodegen.py Wed Jan 9 20:10:19 2008 @@ -860,7 +860,7 @@ self.loadName(node.varname, node.lineno) def visitPass(self, node): - self.set_lineno(node) + pass # no self.set_lineno(node) unnecessarily! see test_return_lineno def visitImport(self, node): self.set_lineno(node) Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/test_compiler.py Wed Jan 9 20:10:19 2008 @@ -425,6 +425,24 @@ comment = '' """, 'comments', ['# foo', 42] + def test_return_lineno(self): + # the point of this test is to check that there is no code associated + # with any line greater than 4. The implicit return should not have + # any line number - otherwise it would probably show up at line 5, + # which is confusing because it's in the wrong branch of the "if" + # in the case where a == b. + yield self.simple_test, """\ + def ireturn_example(): # line 1 + global b # line 2 + if a == b: # line 3 + b = a+1 # line 4 + else: # line 5 + if 1: pass # line 6 + import dis + co = ireturn_example.func_code + x = [lineno for addr, lineno in dis.findlinestarts(co)] + """, 'x', [3, 4] + def test_pprint(self): # a larger example that showed a bug with jumps # over more than 256 bytes From hpk at codespeak.net Wed Jan 9 20:36:28 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 9 Jan 2008 20:36:28 +0100 (CET) Subject: [pypy-svn] r50469 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20080109193628.7C6101684E2@codespeak.net> Author: hpk Date: Wed Jan 9 20:36:28 2008 New Revision: 50469 Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Log: * use canonical way of accessing relative data dir * "import py" is enough for getting access to all of the py lib (lazily) Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Wed Jan 9 20:36:28 2008 @@ -3,7 +3,7 @@ from symbol import sym_name from pprint import pprint -import py.test +import py from pypy.interpreter.pyparser.pythonutil import python_parsefile, \ pypy_parsefile, pypy_parse, python_parse, get_grammar_file, PYTHON_VERSION @@ -69,21 +69,18 @@ (curpos, name(elt1), name(elt2) ), curpos) def test_samples(): - samples_dir = osp.join(osp.dirname(__file__), 'samples') - # samples_dir = osp.dirname(os.__file__) + samples_dir = py.magic.autopath().dirpath("samples") for use_lookahead in (True, False): grammar.USE_LOOKAHEAD = use_lookahead - for fname in os.listdir(samples_dir): - if not fname.endswith('.py'): - continue + for path in samples_dir.listdir("*.py"): + fname = path.basename if fname in SKIP_ALWAYS: continue if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE: yield lambda: py.test.skip( "Grammar mismatch and %s is not native" % (fname,)) continue - abspath = osp.join(samples_dir, fname) - yield check_parse, abspath + yield check_parse, str(path) def DISABLED_check_tuples_equality(pypy_tuples, python_tuples, testname): """XXX FIXME: refactor with assert_tuples_equal()""" From hpk at codespeak.net Wed Jan 9 20:44:05 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 9 Jan 2008 20:44:05 +0100 (CET) Subject: [pypy-svn] r50470 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20080109194405.07853168518@codespeak.net> Author: hpk Date: Wed Jan 9 20:44:05 2008 New Revision: 50470 Removed: pypy/dist/pypy/interpreter/pyparser/test/autopath.py Modified: pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py Log: there is no real need to have the autopath.py helper when you invoke scripts with py.test. Modified: pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py Wed Jan 9 20:44:05 2008 @@ -1,4 +1,4 @@ -import autopath +import pypy import py from test_astcompiler import compile_with_astcompiler @@ -9,14 +9,13 @@ import pypy.conftest mod.std_space = pypy.conftest.gettestobjspace('std') -def check_file_compile(filename): - print 'Compiling:', filename - source = open(filename).read() +def check_file_compile(filepath): + print 'Compiling:', filepath + source = filepath.read() #check_compile(source, 'exec', quiet=True, space=std_space) - compile_with_astcompiler(source, target='exec', space=std_space) + compile_with_astcompiler(source, mode='exec', space=std_space) def test_all(): - p = py.path.local(autopath.pypydir).dirpath().join('lib-python', '2.4.1') - for s in p.listdir(): - if s.check(ext='.py'): - yield check_file_compile, str(s) + p = py.path.local(pypy.__file__).dirpath().dirpath('lib-python', '2.4.1') + for s in p.listdir("*.py"): + yield check_file_compile, s From arigo at codespeak.net Wed Jan 9 22:53:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jan 2008 22:53:37 +0100 (CET) Subject: [pypy-svn] r50472 - in pypy/dist/pypy/tool: . test Message-ID: <20080109215337.67BBB168511@codespeak.net> Author: arigo Date: Wed Jan 9 22:53:37 2008 New Revision: 50472 Modified: pypy/dist/pypy/tool/gcc_cache.py pypy/dist/pypy/tool/test/test_gcc_cache.py Log: (oesser, arigo) Make gcc_cache robust to detect changing ExternalCompilationInfo's. Also, test and fix for calling both try_compile_cache() and build_executable_cache() with the same arguments. Modified: pypy/dist/pypy/tool/gcc_cache.py ============================================================================== --- pypy/dist/pypy/tool/gcc_cache.py (original) +++ pypy/dist/pypy/tool/gcc_cache.py Wed Jan 9 22:53:37 2008 @@ -6,31 +6,34 @@ import distutils import distutils.errors -py.path.local(pypydir).join('_cache').ensure(dir=1) -cache_dir = py.path.local(pypydir).join('_cache', 'gcc') -cache_dir.ensure(dir=1) +cache_dir_root = py.path.local(pypydir).join('_cache').ensure(dir=1) -def build_executable_cache(c_files, *args, **kwds): - s = "\n\n".join([c_file.read() for c_file in c_files]) - hash = md5.md5(s).hexdigest() +def cache_file_path(c_files, eci, cachename): + cache_dir = cache_dir_root.join(cachename).ensure(dir=1) + filecontents = [c_file.read() for c_file in c_files] + key = repr((filecontents, eci)) + hash = md5.md5(key).hexdigest() + return cache_dir.join(hash) + +def build_executable_cache(c_files, eci): + path = cache_file_path(c_files, eci, 'build_executable_cache') try: - return cache_dir.join(hash).read() + return path.read() except py.error.Error: - result = py.process.cmdexec(build_executable(c_files, *args, **kwds)) - cache_dir.join(hash).write(result) + result = py.process.cmdexec(build_executable(c_files, eci)) + path.write(result) return result -def try_compile_cache(c_files, *args, **kwds): - s = "\n\n".join([c_file.read() for c_file in c_files]) - hash = md5.md5(s).hexdigest() +def try_compile_cache(c_files, eci): + path = cache_file_path(c_files, eci, 'try_compile_cache') try: - return eval(cache_dir.join(hash).read()) + return eval(path.read()) except py.error.Error: try: - build_executable(c_files, *args, **kwds) + build_executable(c_files, eci) result = True except (distutils.errors.CompileError, distutils.errors.LinkError): result = False - cache_dir.join(hash).write(repr(result)) - return bool(result) + path.write(repr(result)) + return result Modified: pypy/dist/pypy/tool/test/test_gcc_cache.py ============================================================================== --- pypy/dist/pypy/tool/test/test_gcc_cache.py (original) +++ pypy/dist/pypy/tool/test/test_gcc_cache.py Wed Jan 9 22:53:37 2008 @@ -8,31 +8,49 @@ f = udir.join("x.c") f.write(""" #include + #include int main() { - printf("3\\n"); + printf("%d\\n", ANSWER); return 0; } """) + dir1 = udir.join('test_gcc_exec_dir1').ensure(dir=1) + dir2 = udir.join('test_gcc_exec_dir2').ensure(dir=1) + dir1.join('test_gcc_exec.h').write('#define ANSWER 3\n') + dir2.join('test_gcc_exec.h').write('#define ANSWER 42\n') + eci = ExternalCompilationInfo(include_dirs=[str(dir1)]) # remove cache - try: - cache_dir.join(md5.md5(f.read()).hexdigest()).remove() - except: - pass - assert build_executable_cache([f], ExternalCompilationInfo()) == "3\n" - assert build_executable_cache([f], ExternalCompilationInfo(), compiler_exe="xxx") == "3\n" + path = cache_file_path([f], eci, 'build_executable_cache') + if path.check(): + path.remove() + assert build_executable_cache([f], eci) == "3\n" + assert build_executable_cache([f], eci) == "3\n" + eci2 = ExternalCompilationInfo(include_dirs=[str(dir2)]) + assert build_executable_cache([f], eci2) == "42\n" def test_gcc_ask(): f = udir.join("y.c") f.write(""" + #include + #include int main() { - return 0; + printf("hello\\n"); + return 0; } """) - try: - cache_dir.join(md5.md5(f.read()).hexdigest()).remove() - except: - pass - assert try_compile_cache([f], ExternalCompilationInfo()) - assert try_compile_cache([f], ExternalCompilationInfo(), compiler_exe="xxx") + dir1 = udir.join('test_gcc_ask_dir1').ensure(dir=1) + dir2 = udir.join('test_gcc_ask_dir2').ensure(dir=1) + dir1.join('test_gcc_ask.h').write('/* hello world */\n') + dir2.join('test_gcc_ask.h').write('#error boom\n') + eci = ExternalCompilationInfo(include_dirs=[str(dir1)]) + # remove cache + path = cache_file_path([f], eci, 'try_compile_cache') + if path.check(): + path.remove() + assert try_compile_cache([f], eci) + assert try_compile_cache([f], eci) + assert build_executable_cache([f], eci) == "hello\n" + eci2 = ExternalCompilationInfo(include_dirs=[str(dir2)]) + assert not try_compile_cache([f], eci2) From arigo at codespeak.net Wed Jan 9 22:55:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jan 2008 22:55:43 +0100 (CET) Subject: [pypy-svn] r50473 - pypy/dist/pypy/rpython/tool Message-ID: <20080109215543.343BF168510@codespeak.net> Author: arigo Date: Wed Jan 9 22:55:42 2008 New Revision: 50473 Modified: pypy/dist/pypy/rpython/tool/rfficache.py Log: Remove deprecated interface. If needed please add it into the ExternalCompilationInfo. Modified: pypy/dist/pypy/rpython/tool/rfficache.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rfficache.py (original) +++ pypy/dist/pypy/rpython/tool/rfficache.py Wed Jan 9 22:55:42 2008 @@ -12,7 +12,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.tool.gcc_cache import build_executable_cache -def ask_gcc(question, add_source="", compiler_exe=None): +def ask_gcc(question, add_source=""): includes = ['stdlib.h', 'sys/types.h'] include_string = "\n".join(["#include <%s>" % i for i in includes]) c_source = py.code.Source(''' @@ -31,7 +31,7 @@ c_file = udir.join("gcctest.c") c_file.write(c_source) eci = ExternalCompilationInfo() - return build_executable_cache([c_file], eci, compiler_exe=compiler_exe) + return build_executable_cache([c_file], eci) def sizeof_c_type(c_typename, **kwds): question = 'printf("%%d", sizeof(%s));' % (c_typename,); From arigo at codespeak.net Wed Jan 9 22:56:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jan 2008 22:56:22 +0100 (CET) Subject: [pypy-svn] r50474 - in pypy/dist/pypy/rpython/tool: . test Message-ID: <20080109215622.529AC168510@codespeak.net> Author: arigo Date: Wed Jan 9 22:56:21 2008 New Revision: 50474 Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py Log: Add rffi_platform.check_eci() that just checks if a set of includes and libraries compiles and links successfully or not. Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Wed Jan 9 22:56:21 2008 @@ -48,6 +48,13 @@ HAS = Has(name) return configure(CConfig)['HAS'] +def check_eci(eci): + """Check if a given ExternalCompilationInfo compiles and links.""" + class CConfig: + _compilation_info_ = eci + WORKS = Works() + return configure(CConfig)['WORKS'] + def sizeof(name, eci, **kwds): class CConfig: _compilation_info_ = eci @@ -421,6 +428,10 @@ def question(self, ask_gcc): return ask_gcc(self.name + ';') +class Works(CConfigSingleEntry): + def question(self, ask_gcc): + return ask_gcc("") + class SizeOf(CConfigEntry): """An entry in a CConfig class that stands for some external opaque type Modified: pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py Wed Jan 9 22:56:21 2008 @@ -195,5 +195,11 @@ # has() should also not crash if it is given an invalid #include assert not rffi_platform.has("x", "#include ") +def test_check_eci(): + eci = ExternalCompilationInfo() + assert rffi_platform.check_eci(eci) + eci = ExternalCompilationInfo(libraries=['some_name_that_doesnt_exist_']) + assert not rffi_platform.check_eci(eci) + def test_sizeof(): assert rffi_platform.sizeof("char", ExternalCompilationInfo()) == 1 From arigo at codespeak.net Wed Jan 9 23:51:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 9 Jan 2008 23:51:51 +0100 (CET) Subject: [pypy-svn] r50475 - in pypy/dist/pypy: module/readline rpython/lltypesystem Message-ID: <20080109225151.10FDB168519@codespeak.net> Author: arigo Date: Wed Jan 9 23:51:50 2008 New Revision: 50475 Modified: pypy/dist/pypy/module/readline/c_readline.py pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: (oesser, arigo) Fight with readline until c_readline.py is happy on both Slackware's and Gentoo's way of building the library. (On Slackware, it is done via "configure --with-curses".) Modified: pypy/dist/pypy/module/readline/c_readline.py ============================================================================== --- pypy/dist/pypy/module/readline/c_readline.py (original) +++ pypy/dist/pypy/module/readline/c_readline.py Wed Jan 9 23:51:50 2008 @@ -4,12 +4,30 @@ from pypy.interpreter.gateway import ObjSpace, interp2app from pypy.translator.tool.cbuild import ExternalCompilationInfo -# at least on Gentoo Linux, readline.h doesn't compile if stdio.h is not -# included before -eci = ExternalCompilationInfo( - includes = ["stdio.h", "readline/readline.h", "readline/history.h"], - libraries = ['readline'] -) +# On various platforms, linking only with libreadline is not enough; +# we also need to link with some variant of curses or libtermcap. +# We follow the logic of CPython below. +def try_with_lib(extralibs, **kwds): + # at least on Gentoo Linux, readline.h doesn't compile if stdio.h is not + # included before + eci = ExternalCompilationInfo( + includes = ["stdio.h", "readline/readline.h", "readline/history.h"], + libraries = extralibs + ['readline'], + ) + if platform.check_eci(eci): + return eci + else: + return None + +eci = (try_with_lib([]) or + try_with_lib(['ncursesw']) or + try_with_lib(['ncurses']) or + try_with_lib(['curses']) or + try_with_lib(['termcap'], library_dirs=['/usr/lib/termcap'])) +if eci is None: + raise Exception("cannot find how to link to the readline library") + +# ____________________________________________________________ def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Wed Jan 9 23:51:50 2008 @@ -548,7 +548,8 @@ libpath = libname if libpath: dllclass = getattr(ctypes, calling_conv + 'dll') - clib = dllclass.LoadLibrary(libpath) + # urgh, cannot pass the flag to dllclass.LoadLibrary + clib = dllclass._dlltype(libpath, ctypes.RTLD_GLOBAL) cfunc = get_on_lib(clib, funcname) if cfunc is not None: break From fijal at codespeak.net Wed Jan 9 23:55:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 9 Jan 2008 23:55:13 +0100 (CET) Subject: [pypy-svn] r50476 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080109225513.868DD1683FD@codespeak.net> Author: fijal Date: Wed Jan 9 23:55:13 2008 New Revision: 50476 Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Log: One skip and one junk Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Wed Jan 9 23:55:13 2008 @@ -61,6 +61,7 @@ assert i.value == 54345 def test_callbacks_with_pointers(self): + py.test.skip("callbacks not supported") # a function type receiving a pointer PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int)) @@ -173,6 +174,3 @@ py.test.raises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted py.test.raises(TypeError, c_void_p, object()) # nor other objects - -if __name__ == '__main__': - unittest.main() From xoraxax at codespeak.net Thu Jan 10 00:19:02 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Thu, 10 Jan 2008 00:19:02 +0100 (CET) Subject: [pypy-svn] r50478 - pypy/dist/pypy/doc/discussion Message-ID: <20080109231902.319BA168512@codespeak.net> Author: xoraxax Date: Thu Jan 10 00:19:00 2008 New Revision: 50478 Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt Log: Fix minor typo. Modified: pypy/dist/pypy/doc/discussion/ctypes_modules.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/ctypes_modules.txt (original) +++ pypy/dist/pypy/doc/discussion/ctypes_modules.txt Thu Jan 10 00:19:00 2008 @@ -9,7 +9,7 @@ 3. any specific tricks -4. does it has tests? +4. does it have tests? 5. dependencies From xoraxax at codespeak.net Thu Jan 10 00:24:13 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Thu, 10 Jan 2008 00:24:13 +0100 (CET) Subject: [pypy-svn] r50479 - pypy/dist/pypy/doc/discussion Message-ID: <20080109232413.8716C168512@codespeak.net> Author: xoraxax Date: Thu Jan 10 00:24:12 2008 New Revision: 50479 Removed: pypy/dist/pypy/doc/discussion/logic-plan.txt Log: Removed logic-plan because the logic objspace is gone as well. From fijal at codespeak.net Thu Jan 10 10:14:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Jan 2008 10:14:39 +0100 (CET) Subject: [pypy-svn] r50482 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080110091439.573B81684D6@codespeak.net> Author: fijal Date: Thu Jan 10 10:14:37 2008 New Revision: 50482 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: Fix after armin, who is checking in tabs Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Thu Jan 10 10:14:37 2008 @@ -548,7 +548,7 @@ libpath = libname if libpath: dllclass = getattr(ctypes, calling_conv + 'dll') - # urgh, cannot pass the flag to dllclass.LoadLibrary + # urgh, cannot pass the flag to dllclass.LoadLibrary clib = dllclass._dlltype(libpath, ctypes.RTLD_GLOBAL) cfunc = get_on_lib(clib, funcname) if cfunc is not None: From fijal at codespeak.net Thu Jan 10 11:01:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Jan 2008 11:01:57 +0100 (CET) Subject: [pypy-svn] r50483 - pypy/branch/applevel-ctypes2/pypy/module/_ffi/test Message-ID: <20080110100157.CB9FE1683FF@codespeak.net> Author: fijal Date: Thu Jan 10 11:01:57 2008 New Revision: 50483 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: Another check, be ultra-paranoid about all this. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Thu Jan 10 11:01:57 2008 @@ -356,4 +356,5 @@ A = _ffi.Array('i') a = A.fromaddress(alloc(), 1) assert a[0] == 3 + assert A.fromaddress(a.buffer, 1)[0] == 3 # a.free() - don't free as ll2ctypes is complaining massively From fijal at codespeak.net Thu Jan 10 11:03:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Jan 2008 11:03:24 +0100 (CET) Subject: [pypy-svn] r50484 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080110100324.34FC016847A@codespeak.net> Author: fijal Date: Thu Jan 10 11:03:23 2008 New Revision: 50484 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Log: Wuaaaa! Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Thu Jan 10 11:03:23 2008 @@ -68,7 +68,7 @@ self.alloced = False self.length = length self.shape = shape - if address > 0: + if address != 0: self.ll_array = rffi.cast(rffi.VOIDP, address) else: size = shape.itemsize * length From fijal at codespeak.net Thu Jan 10 11:55:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 10 Jan 2008 11:55:04 +0100 (CET) Subject: [pypy-svn] r50485 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080110105504.7552C1684D6@codespeak.net> Author: fijal Date: Thu Jan 10 11:55:04 2008 New Revision: 50485 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: Wack enough to make 5 tests of test_pointers pass (no memory clearing yet, it leaks like hell). Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Thu Jan 10 11:55:04 2008 @@ -4,6 +4,7 @@ from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr from _ctypes.dummy import _cast_addr +from _ctypes.basics import _CData from _ctypes.primitive import _SimpleCData, sizeof, alignment, byref from _ctypes.pointer import _Pointer from _ctypes.function import CFuncPtr Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Thu Jan 10 11:55:04 2008 @@ -1,6 +1,7 @@ import _ffi class CFuncPtrType(type): + # XXX write down here defaults and such things pass class CFuncPtr(object): @@ -21,21 +22,43 @@ self.dll = None def __call__(self, *args): - assert self.argtypes is not None #XXX for now - assert self.restype is not None #XXX for now - if len(args) != len(self.argtypes): - raise TypeError("%s takes %s arguments, given %s" % (self.name, - len(self.argtypes), len(args))) - return self._getfuncptr()(*args) + import ctypes + if self.restype is None: + # XXX point to default instead + self.restype = ctypes.c_int + if self.argtypes is not None: + if len(args) != len(self.argtypes): + raise TypeError("%s takes %s arguments, given %s" % + (self.name, len(self.argtypes), len(args))) + res = self._getfuncptr(args)(*[arg.value for arg in args]) + if issubclass(self.restype, ctypes._SimpleCData): + return res + else: + # XXX pointers + return self.restype(address=res) - def _getfuncptr(self): + def _getfuncptr(self, args): if self._funcptr is not None: if (self.argtypes is self._argtypes and self.restype is self._restype): return self._funcptr - argtps = [argtype._type_ for argtype in self.argtypes] - restp = self.restype._type_ + if self.argtypes is None: + argtypes = self._guess_magic_args(args) + else: + argtypes = self.argtypes + argtps = [argtype._ffiletter for argtype in argtypes] + restp = self.restype._ffiletter self._funcptr = funcptr = self.dll._handle.ptr(self.name, argtps, restp) self._argtypes = self.argtypes self._restype = self.restype return funcptr + + def _guess_magic_args(self, args): + import _ctypes + res = [] + for arg in args: + if isinstance(arg, _ctypes._CData): + res.append(type(arg)) + else: + raise TypeError("Cannot convert %s" % arg) + return res Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Thu Jan 10 11:55:04 2008 @@ -1,30 +1,57 @@ import _ffi +from _ctypes.basics import _CData + +DEFAULT_VALUE = object() class PointerType(type): def __new__(self, name, cls, typedict): d = dict( - size = _ffi.sizeof('P'), - align = _ffi.alignment('P'), - length = 1 + size = _ffi.sizeof('P'), + align = _ffi.alignment('P'), + length = 1, + _ffiletter = 'P' ) # XXX check if typedict['_type_'] is any sane # XXX remember about paramfunc obj = type.__new__(self, name, cls, typedict) for k, v in d.iteritems(): setattr(obj, k, v) + if '_type_' in typedict: + ffiarray = _ffi.Array(typedict['_type_']._ffiletter) + def __init__(self, value=0, address=DEFAULT_VALUE): + if address is not DEFAULT_VALUE: + self._array = ffiarray.fromaddress(address, 1) + elif value == 0: + # null pointer + self._array = ffiarray.fromaddress(0, 1) + else: + self._array = ffiarray.fromaddress(value._array.buffer, 1) + obj._ffiarray = ffiarray + else: + def __init__(self, value=0): + raise TypeError("%s has no type" % obj) + obj.__init__ = __init__ return obj -class _Pointer(object): +class _Pointer(_CData): __metaclass__ = PointerType - def __init__(self, value=None): - if value is None: - self.is_null = True - else: - self.value = value - # we should later check why exactly this is the case - try: - type(self).__dict__['_type_'] - except KeyError: - raise TypeError("%s has no _type_" % self.__class__) + def getvalue(self): + return self._array + + value = property(getvalue) + + def getcontents(self): + return self._type_.from_address(self._array.buffer) + + def setcontents(self, value): + self._array = self._ffiarray.fromaddress(value._array.buffer, 1) + + def __getitem__(self, item): + return self._array[item] + + def __setitem__(self, item, value): + self._array[item] = value + + contents = property(getcontents, setcontents) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Thu Jan 10 11:55:04 2008 @@ -2,6 +2,8 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" +from _ctypes.basics import _CData + class NULL(object): pass NULL = NULL() @@ -42,20 +44,27 @@ raise ValueError('%s is not a type character' % (tp)) default = TP_TO_DEFAULT[tp] ffitp = TP_TO_FFITP.get(tp, tp) - ffistruct = _ffi.Structure([("value", ffitp)]) - def __init__(self, value=DEFAULT_VALUE): - self._struct = ffistruct() - if value is not DEFAULT_VALUE: - self._struct.value = value + ffiarray = _ffi.Array(ffitp) + def __init__(self, value=DEFAULT_VALUE, address=DEFAULT_VALUE): + if address is not DEFAULT_VALUE: + self._array = ffiarray.fromaddress(address, 1) + else: + self._array = ffiarray(1) + if value is not DEFAULT_VALUE: + self._array[0] = value dct['__init__'] = __init__ result = type.__new__(self, name, bases, dct) - result._ffistruct = ffistruct + result._ffiarray = ffiarray + result._ffiletter = result._type_ return result + def from_address(self, address): + return self(address=address) + def __mul__(self, other): pass -class _SimpleCData(object): +class _SimpleCData(_CData): __metaclass__ = SimpleType _type_ = 'i' def from_param(cls, *args, **kwargs): @@ -63,10 +72,10 @@ from_param = classmethod(from_param) def _getvalue(self): - return self._struct.value + return self._array[0] def _setvalue(self, val): - self._struct.value = value + self._array[0] = value value = property(_getvalue, _setvalue) def __repr__(self): From arigo at codespeak.net Thu Jan 10 22:35:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 10 Jan 2008 22:35:39 +0100 (CET) Subject: [pypy-svn] r50497 - pypy/branch/astcompilertests/pypy/interpreter/pyparser/test Message-ID: <20080110213539.5A3C716852D@codespeak.net> Author: arigo Date: Thu Jan 10 22:35:37 2008 New Revision: 50497 Removed: pypy/branch/astcompilertests/pypy/interpreter/pyparser/test/autopath.py pypy/branch/astcompilertests/pypy/interpreter/pyparser/test/stdlib_testall.py Log: Removing this to match the trunk state. From arigo at codespeak.net Thu Jan 10 22:36:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 10 Jan 2008 22:36:05 +0100 (CET) Subject: [pypy-svn] r50498 - pypy/branch/astcompilertests/pypy/interpreter/pyparser/test Message-ID: <20080110213605.AA9D216852D@codespeak.net> Author: arigo Date: Thu Jan 10 22:36:05 2008 New Revision: 50498 Added: pypy/branch/astcompilertests/pypy/interpreter/pyparser/test/stdlib_testall.py - copied unchanged from r50496, pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py Log: Copy hpk's updated stdlib_testall from the trunk to the branch. From arigo at codespeak.net Thu Jan 10 22:36:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 10 Jan 2008 22:36:58 +0100 (CET) Subject: [pypy-svn] r50499 - in pypy/branch/astcompilertests/pypy/interpreter: astcompiler/test pyparser/test Message-ID: <20080110213658.C3C8316852D@codespeak.net> Author: arigo Date: Thu Jan 10 22:36:58 2008 New Revision: 50499 Added: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py - copied unchanged from r50498, pypy/branch/astcompilertests/pypy/interpreter/pyparser/test/stdlib_testall.py Removed: pypy/branch/astcompilertests/pypy/interpreter/pyparser/test/stdlib_testall.py Log: Sorry, stdlib_testall should rather be in astcompiler/test/ now. From arigo at codespeak.net Thu Jan 10 22:39:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 10 Jan 2008 22:39:50 +0100 (CET) Subject: [pypy-svn] r50500 - pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test Message-ID: <20080110213950.2117116852D@codespeak.net> Author: arigo Date: Thu Jan 10 22:39:49 2008 New Revision: 50500 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py Log: Fix imports. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py Thu Jan 10 22:39:49 2008 @@ -1,21 +1,18 @@ import pypy import py -from test_astcompiler import compile_with_astcompiler +from pypy.interpreter.astcompiler.test.test_compiler import \ + compile_with_astcompiler -def setup_module(mod): - import sys - if sys.version[:3] != "2.4": - py.test.skip("expected to work only on 2.4") - import pypy.conftest - mod.std_space = pypy.conftest.gettestobjspace('std') +class TestStdlib: -def check_file_compile(filepath): - print 'Compiling:', filepath - source = filepath.read() - #check_compile(source, 'exec', quiet=True, space=std_space) - compile_with_astcompiler(source, mode='exec', space=std_space) + def check_file_compile(self, filepath): + space = self.space + print 'Compiling:', filepath + source = filepath.read() + compile_with_astcompiler(source, mode='exec', space=space) -def test_all(): - p = py.path.local(pypy.__file__).dirpath().dirpath('lib-python', '2.4.1') - for s in p.listdir("*.py"): - yield check_file_compile, s + def test_all(self): + p = py.path.local(pypy.__file__).dirpath().dirpath('lib-python', + '2.4.1') + for s in p.listdir("*.py"): + yield self.check_file_compile, s From arigo at codespeak.net Thu Jan 10 22:43:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 10 Jan 2008 22:43:27 +0100 (CET) Subject: [pypy-svn] r50501 - pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test Message-ID: <20080110214327.083B01684CB@codespeak.net> Author: arigo Date: Thu Jan 10 22:43:27 2008 New Revision: 50501 Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py Log: Run in a predictible (alphabetical) order. Modified: pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py ============================================================================== --- pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py (original) +++ pypy/branch/astcompilertests/pypy/interpreter/astcompiler/test/stdlib_testall.py Thu Jan 10 22:43:27 2008 @@ -14,5 +14,7 @@ def test_all(self): p = py.path.local(pypy.__file__).dirpath().dirpath('lib-python', '2.4.1') - for s in p.listdir("*.py"): + files = p.listdir("*.py") + files.sort() + for s in files: yield self.check_file_compile, s From xoraxax at codespeak.net Fri Jan 11 13:06:43 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Fri, 11 Jan 2008 13:06:43 +0100 (CET) Subject: [pypy-svn] r50513 - pypy/dist Message-ID: <20080111120643.23B651684FA@codespeak.net> Author: xoraxax Date: Fri Jan 11 13:06:42 2008 New Revision: 50513 Modified: pypy/dist/README Log: Remove version number from README Modified: pypy/dist/README ============================================================================== --- pypy/dist/README (original) +++ pypy/dist/README Fri Jan 11 13:06:42 2008 @@ -1,6 +1,6 @@ -======================================================= -PyPy: Python in Python implementation / Version 1.0.0 -======================================================= +====================================== +PyPy: Python in Python implementation +====================================== Welcome to PyPy! From antocuni at codespeak.net Fri Jan 11 13:33:09 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jan 2008 13:33:09 +0100 (CET) Subject: [pypy-svn] r50514 - pypy/dist/pypy/rpython/test Message-ID: <20080111123309.184DE168445@codespeak.net> Author: antocuni Date: Fri Jan 11 13:33:09 2008 New Revision: 50514 Modified: pypy/dist/pypy/rpython/test/test_rclass.py Log: a failing test for ootype, which prevents test_timeshift.test_very_simple to be ported to ootype Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Fri Jan 11 13:33:09 2008 @@ -592,6 +592,24 @@ res = self.interpret(f, []) assert res == -7 + def test_specialize_methods(self): + self._skip_llinterpreter("ootype bug :-(", skipLL=False) + from pypy.rlib.objectmodel import specialize + class A: + @specialize.arg(1) + def revealconst(self, T): + return 1 + class B(A): + @specialize.arg(1) + def revealconst(self, T): + return 2 + + def fn(): + a = A() + b = B() + return a.revealconst('a') + b.revealconst('b') + a.revealconst('c') + assert self.interpret(fn, []) == 4 + class TestLltype(BaseTestRclass, LLRtypeMixin): @@ -769,4 +787,3 @@ assert destra == destrc assert destrb is not None assert destra is not None - From antocuni at codespeak.net Fri Jan 11 15:28:52 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 11 Jan 2008 15:28:52 +0100 (CET) Subject: [pypy-svn] r50517 - in pypy/dist/pypy/rpython: ootypesystem test Message-ID: <20080111142852.891BA16846A@codespeak.net> Author: antocuni Date: Fri Jan 11 15:28:51 2008 New Revision: 50517 Modified: pypy/dist/pypy/rpython/ootypesystem/rpbc.py pypy/dist/pypy/rpython/test/test_rclass.py Log: this fixes the failing test, though I'm not sure it's 100% correct. All relevant tests seem to pass. Modified: pypy/dist/pypy/rpython/ootypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rpbc.py Fri Jan 11 15:28:51 2008 @@ -67,7 +67,7 @@ samplemdesc = methdescs.iterkeys().next() concretetable, uniquerows = get_concrete_calltable(rtyper, samplemdesc.funcdesc.getcallfamily()) - self.row_mapping = {} + self.row_mapping = {} for row in uniquerows: sample_as_static_meth = row.itervalues().next() SM = ootype.typeOf(sample_as_static_meth) @@ -95,8 +95,12 @@ if methdesc is None: m = ootype.meth(M, _name=name, abstract=True, **flags) else: - impl_graph = row[methdesc.funcdesc].graph - m = ootype.meth(M, _name=name, graph=impl_graph, **flags) + try: + impl_graph = row[methdesc.funcdesc].graph + except KeyError: + m = ootype.meth(M, _name=name, abstract=True, **flags) # XXX ??? + else: + m = ootype.meth(M, _name=name, graph=impl_graph, **flags) derived_name = row_method_name(name, rowname) impls[derived_name] = m return impls Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Fri Jan 11 15:28:51 2008 @@ -593,22 +593,23 @@ assert res == -7 def test_specialize_methods(self): - self._skip_llinterpreter("ootype bug :-(", skipLL=False) from pypy.rlib.objectmodel import specialize class A: @specialize.arg(1) def revealconst(self, T): - return 1 + return 3 * T + revealconst.cls = 'A' class B(A): @specialize.arg(1) def revealconst(self, T): - return 2 + return 4 * T + revealconst.cls = 'B' def fn(): a = A() b = B() - return a.revealconst('a') + b.revealconst('b') + a.revealconst('c') - assert self.interpret(fn, []) == 4 + return a.revealconst(1) + b.revealconst(2) + a.revealconst(3) + assert self.interpret(fn, []) == 3 + 8 + 9 class TestLltype(BaseTestRclass, LLRtypeMixin): From fijal at codespeak.net Fri Jan 11 15:50:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 11 Jan 2008 15:50:12 +0100 (CET) Subject: [pypy-svn] r50518 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080111145012.858041684C7@codespeak.net> Author: fijal Date: Fri Jan 11 15:50:11 2008 New Revision: 50518 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: Wack enough to make both test_numbers and test_pointer happy. The solution right now is to create always the intermediate CArgObject which contains raw reference to what it passes down to _ffi. A lot of overhead, but works. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Fri Jan 11 15:50:11 2008 @@ -1,4 +1,5 @@ import _ffi +from _ctypes.param import CArgObject class CFuncPtrType(type): # XXX write down here defaults and such things @@ -30,7 +31,9 @@ if len(args) != len(self.argtypes): raise TypeError("%s takes %s arguments, given %s" % (self.name, len(self.argtypes), len(args))) - res = self._getfuncptr(args)(*[arg.value for arg in args]) + funcptr = self._getfuncptr(args) + argvalues = [tp.from_param(arg).raw_value for tp, arg in zip(self._argtypes, args)] + res = funcptr(*argvalues) if issubclass(self.restype, ctypes._SimpleCData): return res else: @@ -49,7 +52,7 @@ argtps = [argtype._ffiletter for argtype in argtypes] restp = self.restype._ffiletter self._funcptr = funcptr = self.dll._handle.ptr(self.name, argtps, restp) - self._argtypes = self.argtypes + self._argtypes = argtypes self._restype = self.restype return funcptr @@ -59,6 +62,8 @@ for arg in args: if isinstance(arg, _ctypes._CData): res.append(type(arg)) + elif isinstance(arg, CArgObject): + res.append(arg._type) else: raise TypeError("Cannot convert %s" % arg) return res Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Fri Jan 11 15:50:11 2008 @@ -1,6 +1,7 @@ import _ffi from _ctypes.basics import _CData +from _ctypes.param import CArgObject DEFAULT_VALUE = object() @@ -34,6 +35,13 @@ obj.__init__ = __init__ return obj + def from_param(self, param): + # XXX think deeper about that + if isinstance(param, CArgObject): + return param + else: + return self(address=param._array.buffer)._as_ffi() + class _Pointer(_CData): __metaclass__ = PointerType @@ -48,6 +56,9 @@ def setcontents(self, value): self._array = self._ffiarray.fromaddress(value._array.buffer, 1) + def _as_ffi(self): + return CArgObject('P', self._array, type(self)) + def __getitem__(self, item): return self._array[item] Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Fri Jan 11 15:50:11 2008 @@ -3,6 +3,7 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" from _ctypes.basics import _CData +from _ctypes.param import CArgObject class NULL(object): pass @@ -54,22 +55,22 @@ self._array[0] = value dct['__init__'] = __init__ result = type.__new__(self, name, bases, dct) + result._ffiletter = tp result._ffiarray = ffiarray - result._ffiletter = result._type_ return result def from_address(self, address): - return self(address=address) + return self(address=address) def __mul__(self, other): pass + def from_param(self, value): + return self(value)._as_ffi() + class _SimpleCData(_CData): __metaclass__ = SimpleType _type_ = 'i' - def from_param(cls, *args, **kwargs): - pass - from_param = classmethod(from_param) def _getvalue(self): return self._array[0] @@ -78,6 +79,9 @@ self._array[0] = value value = property(_getvalue, _setvalue) + def _as_ffi(self): + return CArgObject(self._type_, self.value, type(self)) + def __repr__(self): return "%s(%s)" % (type(self).__name__, self.value) @@ -91,4 +95,5 @@ from ctypes import pointer if not isinstance(cdata, _SimpleCData): raise TypeError("expected CData instance") - return pointer(cdata) + return pointer(cdata)._as_ffi() + From arigo at codespeak.net Fri Jan 11 18:13:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jan 2008 18:13:56 +0100 (CET) Subject: [pypy-svn] r50523 - pypy/dist/pypy/objspace/std Message-ID: <20080111171356.36B78168469@codespeak.net> Author: arigo Date: Fri Jan 11 18:13:54 2008 New Revision: 50523 Modified: pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/objspace.py Log: Add a shortcut in the stdobjspace to make LIST_APPEND faster. (From the astcompilertests branch) Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jan 11 18:13:54 2008 @@ -23,6 +23,9 @@ items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]# XXX generic mixed types unwrap return list(items) + def append(w_list, w_item): + w_list.wrappeditems.append(w_item) + registerimplementation(W_ListObject) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Jan 11 18:13:54 2008 @@ -103,6 +103,14 @@ w_result = f.space.getitem(w_1, w_2) f.pushvalue(w_result) + def LIST_APPEND(f, *ignored): + w = f.popvalue() + v = f.popvalue() + if type(v) is W_ListObject: + v.append(w) + else: + f.space.call_method(v, 'append', w) + if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN: def CALL_LIKELY_BUILTIN(f, oparg, *ignored): from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module From arigo at codespeak.net Fri Jan 11 18:14:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jan 2008 18:14:56 +0100 (CET) Subject: [pypy-svn] r50524 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20080111171456.C8157168469@codespeak.net> Author: arigo Date: Fri Jan 11 18:14:56 2008 New Revision: 50524 Removed: pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py Log: Remove this file. In the astcompilertests branch there is an updated version of astcompiler/test/. From arigo at codespeak.net Fri Jan 11 18:23:25 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 11 Jan 2008 18:23:25 +0100 (CET) Subject: [pypy-svn] r50525 - in pypy: branch/astcompilertests dist/pypy/interpreter dist/pypy/interpreter/astcompiler dist/pypy/interpreter/pyparser dist/pypy/interpreter/pyparser/test dist/pypy/interpreter/pyparser/test/output dist/pypy/objspace/std Message-ID: <20080111172325.69E40168469@codespeak.net> Author: arigo Date: Fri Jan 11 18:23:25 2008 New Revision: 50525 Added: pypy/dist/pypy/interpreter/astcompiler/ - copied from r50524, pypy/branch/astcompilertests/pypy/interpreter/astcompiler/ pypy/dist/pypy/interpreter/nestedscope.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/interpreter/nestedscope.py pypy/dist/pypy/interpreter/pycode.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/interpreter/pycode.py pypy/dist/pypy/interpreter/pycompiler.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/grammar.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/pythonlexer.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/objspace/std/complexobject.py - copied unchanged from r50524, pypy/branch/astcompilertests/pypy/objspace/std/complexobject.py Removed: pypy/branch/astcompilertests/ pypy/dist/pypy/interpreter/pyparser/test/output/ pypy/dist/pypy/interpreter/pyparser/test/test_astcompiler.py pypy/dist/pypy/interpreter/pyparser/test/test_snippet_out.py Log: Merging the astcompilertests branch: * made the AST compiler tests saner; * added a bytecode optimization pass, performed at the AST level (opt.py); * rewrote pyassem.py to be simpler and saner; * fixed (hopefully) the stack depth computation in pyassem.py. From arigo at codespeak.net Sat Jan 12 12:04:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jan 2008 12:04:22 +0100 (CET) Subject: [pypy-svn] r50529 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080112110422.28D04168547@codespeak.net> Author: arigo Date: Sat Jan 12 12:04:21 2008 New Revision: 50529 Modified: pypy/dist/pypy/objspace/std/rangeobject.py pypy/dist/pypy/objspace/std/test/test_rangeobject.py Log: Test and fix for "Fatal RPython error: IndexError" in rangeobject.py. Modified: pypy/dist/pypy/objspace/std/rangeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/rangeobject.py (original) +++ pypy/dist/pypy/objspace/std/rangeobject.py Sat Jan 12 12:04:21 2008 @@ -59,6 +59,10 @@ raise IndexError return w_self.start + i * w_self.step + def getitem_unchecked(w_self, i): + # bounds not checked, on purpose + return w_self.start + i * w_self.step + def __repr__(w_self): if w_self.w_list is None: return "W_RangeListObject(%s, %s, %s)" % ( @@ -91,7 +95,7 @@ length = w_rangelist.length start, stop, step, slicelength = w_slice.indices4(space, length) assert slicelength >= 0 - rangestart = w_rangelist.getitem(start) + rangestart = w_rangelist.getitem_unchecked(start) rangestep = w_rangelist.step * step return W_RangeListObject(rangestart, rangestep, slicelength) @@ -140,7 +144,7 @@ # probably somewhat useless, but well... if w_rangelist.w_list is not None: raise FailedToImplement - w_rangelist.start = w_rangelist.getitem(-1) + w_rangelist.start = w_rangelist.getitem_unchecked(w_rangelist.length-1) w_rangelist.step = -w_rangelist.step def list_sort__RangeList_None_None_ANY(space, w_rangelist, w_cmp, @@ -155,7 +159,7 @@ factor = 1 reverse = w_rangelist.step * factor < 0 if reverse: - w_rangelist.start = w_rangelist.getitem(-1) + w_rangelist.start = w_rangelist.getitem_unchecked(w_rangelist.length-1) w_rangelist.step = -w_rangelist.step return space.w_None Modified: pypy/dist/pypy/objspace/std/test/test_rangeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_rangeobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_rangeobject.py Sat Jan 12 12:04:21 2008 @@ -33,6 +33,14 @@ assert result == [81, 77, 73, 69, 65] assert self.not_forced(r) + def test_empty_range(self): + r = range(10, 10) + r.sort(reverse=True) + assert len(r) == 0 + assert list(reversed(r)) == [] + assert r[:] == [] + assert self.not_forced(r) + def test_repr(self): r = range(5) assert repr(r) == "[0, 1, 2, 3, 4]" From fijal at codespeak.net Sat Jan 12 15:44:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jan 2008 15:44:56 +0100 (CET) Subject: [pypy-svn] r50530 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080112144456.26ED4168554@codespeak.net> Author: fijal Date: Sat Jan 12 15:44:54 2008 New Revision: 50530 Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (contents, props changed) pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: Shuffle stuff around a bit Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Sat Jan 12 15:44:54 2008 @@ -1,14 +1,15 @@ -from _ctypes.dummy import Union, Structure, Array +from _ctypes.dummy import Union, Array from _ctypes.dummy import ArgumentError, addressof from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr from _ctypes.dummy import _cast_addr -from _ctypes.basics import _CData -from _ctypes.primitive import _SimpleCData, sizeof, alignment, byref +from _ctypes.basics import _CData, sizeof, alignment, byref +from _ctypes.primitive import _SimpleCData from _ctypes.pointer import _Pointer from _ctypes.function import CFuncPtr from _ctypes.dll import dlopen +from _ctypes.structure import Structure __version__ = '1.0.2' Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Sat Jan 12 15:44:54 2008 @@ -0,0 +1,30 @@ + +import _ffi + +class _CData(object): + """ The most basic object for all ctypes types + """ + pass + +class CArgObject(object): + def __init__(self, letter, raw_value, _type): + self.ffiletter = letter + self.raw_value = raw_value + self._type = _type + + def __repr__(self): + return "" % (self.ffiletter, self.raw_value) + + +def sizeof(tp): + return _ffi.sizeof(tp._type_) + +def alignment(tp): + return _ffi.alignment(tp._type_) + +def byref(cdata): + from ctypes import pointer, _SimpleCData + if not isinstance(cdata, _SimpleCData): + raise TypeError("expected CData instance") + return pointer(cdata)._as_ffi() + Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py Sat Jan 12 15:44:54 2008 @@ -4,9 +4,6 @@ class Union(object): __metaclass__ = UnionType -class Structure(type): - pass - class Array(type): pass Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Sat Jan 12 15:44:54 2008 @@ -1,5 +1,5 @@ import _ffi -from _ctypes.param import CArgObject +from _ctypes.basics import CArgObject class CFuncPtrType(type): # XXX write down here defaults and such things Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Sat Jan 12 15:44:54 2008 @@ -1,7 +1,6 @@ import _ffi -from _ctypes.basics import _CData -from _ctypes.param import CArgObject +from _ctypes.basics import _CData, CArgObject DEFAULT_VALUE = object() Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Sat Jan 12 15:44:54 2008 @@ -2,8 +2,7 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" -from _ctypes.basics import _CData -from _ctypes.param import CArgObject +from _ctypes.basics import _CData, CArgObject class NULL(object): pass @@ -84,16 +83,3 @@ def __repr__(self): return "%s(%s)" % (type(self).__name__, self.value) - -def sizeof(tp): - return _ffi.sizeof(tp._type_) - -def alignment(tp): - return _ffi.alignment(tp._type_) - -def byref(cdata): - from ctypes import pointer - if not isinstance(cdata, _SimpleCData): - raise TypeError("expected CData instance") - return pointer(cdata)._as_ffi() - Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Sat Jan 12 15:44:54 2008 @@ -0,0 +1,9 @@ + +from _ctypes.basics import _CData + +class StructureMeta(type): + def __new__(self, name, cls, typedict): + return type.__new__(self, name, cls, typedict) + +class Structure(_CData): + __metaclass__ = StructureMeta From fijal at codespeak.net Sat Jan 12 15:45:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jan 2008 15:45:17 +0100 (CET) Subject: [pypy-svn] r50531 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080112144517.8E9B9168554@codespeak.net> Author: fijal Date: Sat Jan 12 15:45:17 2008 New Revision: 50531 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_sizes.py (contents, props changed) pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Log: Port and add some tests Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Sat Jan 12 15:45:17 2008 @@ -105,6 +105,7 @@ py.test.raises(TypeError, delitem, p, 0) def test_from_address(self): + py.test.skip("It cannot work") from array import array a = array('i', [100, 200, 300, 400, 500]) addr = a.buffer_info()[0] Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_sizes.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_sizes.py Sat Jan 12 15:45:17 2008 @@ -0,0 +1,23 @@ +# Test specifically-sized containers. + +from ctypes import * + +class TestSizes: + def test_8(self): + assert 1 == sizeof(c_int8) + assert 1 == sizeof(c_uint8) + + def test_16(self): + assert 2 == sizeof(c_int16) + assert 2 == sizeof(c_uint16) + + def test_32(self): + assert 4 == sizeof(c_int32) + assert 4 == sizeof(c_uint32) + + def test_64(self): + assert 8 == sizeof(c_int64) + assert 8 == sizeof(c_uint64) + + def test_size_t(self): + assert sizeof(c_void_p) == sizeof(c_size_t) Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py Sat Jan 12 15:45:17 2008 @@ -0,0 +1,214 @@ + +import py +from ctypes import * + +class TestStringArray: + def test_one(self): + BUF = c_char * 4 + + buf = BUF("a", "b", "c") + assert buf.value == "abc" + assert buf.raw == "abc\000" + + buf.value = "ABCD" + assert buf.value == "ABCD" + assert buf.raw == "ABCD" + + buf.value = "x" + assert buf.value == "x" + assert buf.raw == "x\000CD" + + buf[1] = "Z" + assert buf.value == "xZCD" + assert buf.raw == "xZCD" + + py.test.raises(ValueError, setattr, buf, "value", "aaaaaaaa") + py.test.raises(TypeError, setattr, buf, "value", 42) + + def test_c_buffer_value(self): + buf = c_buffer(32) + + buf.value = "Hello, World" + assert buf.value, "Hello == World" + + py.test.raises(TypeError, setattr, buf, "value", buffer("Hello, World")) + py.test.raises(TypeError, setattr, buf, "value", buffer("abc")) + py.test.raises(ValueError, setattr, buf, "raw", buffer("x" * 100)) + + def test_c_buffer_raw(self): + buf = c_buffer(32) + + buf.raw = buffer("Hello, World") + assert buf.value, "Hello == World" + py.test.raises(TypeError, setattr, buf, "value", buffer("abc")) + py.test.raises(ValueError, setattr, buf, "raw", buffer("x" * 100)) + + def test_param_1(self): + BUF = c_char * 4 + buf = BUF() +## print c_char_p.from_param(buf) + + def test_param_2(self): + BUF = c_char * 4 + buf = BUF() +## print BUF.from_param(c_char_p("python")) +## print BUF.from_param(BUF(*"pyth")) + +try: + c_wchar +except NameError: + pass +else: + class TestWString: + def test(self): + BUF = c_wchar * 4 + + buf = BUF(u"a", u"b", u"c") + assert buf.value == u"abc" + + buf.value = u"ABCD" + assert buf.value == u"ABCD" + + buf.value = u"x" + assert buf.value == u"x" + + buf[1] = u"Z" + assert buf.value == u"xZCD" + +class TestString: + def XX_test_basic_strings(self): + cs = c_string("abcdef") + + # Cannot call len on a c_string any longer + py.test.raises(TypeError, len, cs) + assert sizeof(cs) == 7 + + # The value property is the string up to the first terminating NUL. + assert cs.value == "abcdef" + assert c_string("abc\000def").value == "abc" + + # The raw property is the total buffer contents: + assert cs.raw == "abcdef\000" + assert c_string("abc\000def").raw == "abc\000def\000" + + # We can change the value: + cs.value = "ab" + assert cs.value == "ab" + assert cs.raw == "ab\000\000\000\000\000" + + cs.raw = "XY" + assert cs.value == "XY" + assert cs.raw == "XY\000\000\000\000\000" + + py.test.raises(TypeError, c_string, u"123") + + def XX_test_sized_strings(self): + + # New in releases later than 0.4.0: + py.test.raises(TypeError, c_string, None) + + # New in releases later than 0.4.0: + # c_string(number) returns an empty string of size number + assert len(c_string(32).raw) == 32 + py.test.raises(ValueError, c_string, -1) + py.test.raises(ValueError, c_string, 0) + + # These tests fail, because it is no longer initialized +## self.failUnless(c_string(2).value == "") +## self.failUnless(c_string(2).raw == "\000\000") + self.failUnless(c_string(2).raw[-1] == "\000") + self.failUnless(len(c_string(2).raw) == 2) + + def XX_test_initialized_strings(self): + + assert c_string("ab", 4).raw[:2] == "ab" + assert c_string("ab", 4).raw[-1] == "\000" + assert c_string("ab", 2).raw == "a\000" + + def XX_test_toolong(self): + cs = c_string("abcdef") + # Much too long string: + py.test.raises(ValueError, setattr, cs, "value", "123456789012345") + + # One char too long values: + py.test.raises(ValueError, setattr, cs, "value", "1234567") + +## def test_perf(self): +## check_perf() + +try: + c_wchar +except NameError: + pass +else: + class TestWString2: + def test_wchar(self): + c_wchar(u"x") + repr(byref(c_wchar(u"x"))) + c_wchar("x") + + + def X_test_basic_wstrings(self): + cs = c_wstring(u"abcdef") + + # XXX This behaviour is about to change: + # len returns the size of the internal buffer in bytes. + # This includes the terminating NUL character. + self.failUnless(sizeof(cs) == 14) + + # The value property is the string up to the first terminating NUL. + self.failUnless(cs.value == u"abcdef") + self.failUnless(c_wstring(u"abc\000def").value == u"abc") + + self.failUnless(c_wstring(u"abc\000def").value == u"abc") + + # The raw property is the total buffer contents: + self.failUnless(cs.raw == u"abcdef\000") + self.failUnless(c_wstring(u"abc\000def").raw == u"abc\000def\000") + + # We can change the value: + cs.value = u"ab" + self.failUnless(cs.value == u"ab") + self.failUnless(cs.raw == u"ab\000\000\000\000\000") + + py.test.raises(TypeError, c_wstring, "123") + py.test.raises(ValueError, c_wstring, 0) + + def X_test_toolong(self): + cs = c_wstring(u"abcdef") + # Much too long string: + py.test.raises(ValueError, setattr, cs, "value", u"123456789012345") + + # One char too long values: + py.test.raises(ValueError, setattr, cs, "value", u"1234567") + + +def run_test(rep, msg, func, arg): + items = range(rep) + from time import clock + start = clock() + for i in items: + func(arg); func(arg); func(arg); func(arg); func(arg) + stop = clock() + print "%20s: %.2f us" % (msg, ((stop-start)*1e6/5/rep)) + +def check_perf(): + # Construct 5 objects + + REP = 200000 + + run_test(REP, "c_string(None)", c_string, None) + run_test(REP, "c_string('abc')", c_string, 'abc') + +# Python 2.3 -OO, win2k, P4 700 MHz: +# +# c_string(None): 1.75 us +# c_string('abc'): 2.74 us + +# Python 2.2 -OO, win2k, P4 700 MHz: +# +# c_string(None): 2.95 us +# c_string('abc'): 3.67 us + + +## check_perf() From arigo at codespeak.net Sat Jan 12 19:36:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 12 Jan 2008 19:36:15 +0100 (CET) Subject: [pypy-svn] r50532 - pypy/dist/pypy/translator Message-ID: <20080112183615.39C3F168546@codespeak.net> Author: arigo Date: Sat Jan 12 19:36:13 2008 New Revision: 50532 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/transform.py Log: (fijal, arigo) Print the number of stack checks inserted. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sat Jan 12 19:36:13 2008 @@ -51,6 +51,7 @@ def backend_to_typesystem(backend): return _BACKEND_TO_TYPESYSTEM.get(backend, 'ootype') +# set of translation steps to profile PROFILE = set([]) class Instrument(Exception): @@ -450,7 +451,8 @@ def task_stackcheckinsertion_lltype(self): from pypy.translator.transform import insert_ll_stackcheck - insert_ll_stackcheck(self.translator) + count = insert_ll_stackcheck(self.translator) + self.log.info("inserted %d stack checks." % (count,)) task_stackcheckinsertion_lltype = taskdef( task_stackcheckinsertion_lltype, Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Sat Jan 12 19:36:13 2008 @@ -269,7 +269,8 @@ v.concretetype = lltype.Void unwind_op = SpaceOperation('direct_call', [stack_check_ptr_const], v) block.operations.insert(0, unwind_op) - + return len(insert_in) + default_extra_passes = [ transform_allocate, From fijal at codespeak.net Sat Jan 12 22:47:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 12 Jan 2008 22:47:54 +0100 (CET) Subject: [pypy-svn] r50536 - pypy/dist/pypy/tool/algo/test Message-ID: <20080112214754.805A21684D1@codespeak.net> Author: fijal Date: Sat Jan 12 22:47:53 2008 New Revision: 50536 Modified: pypy/dist/pypy/tool/algo/test/test_graphlib.py Log: (cfbolz, fijal) Make stuff a bit less confusing. Modified: pypy/dist/pypy/tool/algo/test/test_graphlib.py ============================================================================== --- pypy/dist/pypy/tool/algo/test/test_graphlib.py (original) +++ pypy/dist/pypy/tool/algo/test/test_graphlib.py Sat Jan 12 22:47:53 2008 @@ -69,10 +69,11 @@ edges[i] = [Edge(i, j)] for i in range(19): edges[i*10].append(Edge(i*10, i*10+15)) + vertices = dict([(i, True) for i in range(200)]) def test_strong_components(self): edges = self.edges - result = list(strong_components(edges, edges)) + result = list(strong_components(self.vertices, edges)) assert len(result) == 20 result.sort() for i in range(20): @@ -82,7 +83,7 @@ def test_break_cycles(self, edges=None): edges = edges or self.edges - result = list(break_cycles(edges, edges)) + result = list(break_cycles(self.vertices, edges)) assert len(result) == 20 result = [(edge.source, edge.target) for edge in result] result.sort() From cfbolz at codespeak.net Sat Jan 12 23:07:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 12 Jan 2008 23:07:17 +0100 (CET) Subject: [pypy-svn] r50537 - pypy/dist/pypy/tool/algo/test Message-ID: <20080112220717.EDAAB1684EA@codespeak.net> Author: cfbolz Date: Sat Jan 12 23:07:16 2008 New Revision: 50537 Modified: pypy/dist/pypy/tool/algo/test/test_graphlib.py Log: a test showing a pretty bad case in the cycle finder. just increase NUM if it's not bad enough. Modified: pypy/dist/pypy/tool/algo/test/test_graphlib.py ============================================================================== --- pypy/dist/pypy/tool/algo/test/test_graphlib.py (original) +++ pypy/dist/pypy/tool/algo/test/test_graphlib.py Sat Jan 12 23:07:16 2008 @@ -144,6 +144,17 @@ assert list(result[0]) == [0] assert list(result[1]) in ([1,2], [2,1]) +class TestBadCase: + # a complete graph + NUM = 30 + edges = make_edge_dict([Edge(i, j) for i in range(NUM) + for j in range(NUM)]) + vertices = dict.fromkeys(range(NUM)) + + def test_break_cycles(self): + result = list(break_cycles(self.edges, self.edges)) + assert result + class TestRandom: edges = make_edge_dict([Edge(random.randrange(0,100), From cfbolz at codespeak.net Sun Jan 13 09:06:39 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 09:06:39 +0100 (CET) Subject: [pypy-svn] r50538 - in pypy/dist/pypy/tool/algo: . test Message-ID: <20080113080639.E75BD1684C8@codespeak.net> Author: cfbolz Date: Sun Jan 13 09:06:38 2008 New Revision: 50538 Modified: pypy/dist/pypy/tool/algo/graphlib.py pypy/dist/pypy/tool/algo/test/test_graphlib.py Log: make the implementation of the cycle breaker algorithm less braindead: don't recompute the cycles every time you break a few, reuse the existing information instead. The algorithm stays exponential but I think it's still reasonable for "practical" call trees which are far from being complete graphs. Modified: pypy/dist/pypy/tool/algo/graphlib.py ============================================================================== --- pypy/dist/pypy/tool/algo/graphlib.py (original) +++ pypy/dist/pypy/tool/algo/graphlib.py Sun Jan 13 09:06:38 2008 @@ -100,26 +100,42 @@ def break_cycles(vertices, edges): """Enumerates a reasonably minimal set of edges that must be removed to make the graph acyclic.""" - graphs = [(vertices, edges)] - for vertices, edges in graphs: - #print ''.join(vertices), - #print [e.source+e.target for l in edges.values() for e in l] - for component in strong_components(vertices, edges): - #print '-->', ''.join(component) - edge_weights = {} - random_vertex = component.iterkeys().next() - for cycle in all_cycles(random_vertex, component, edges): - #print '\tcycle:', [e.source+e.target for e in cycle] - for edge in cycle: - edge_weights[edge] = edge_weights.get(edge, 0) + 1 - if edge_weights: - max_weight = max(edge_weights.values()) - for edge, weight in edge_weights.iteritems(): - if weight == max_weight: - break - # kill this edge - yield edge - new_edges = edges.copy() - new_edges[edge.source] = [e for e in new_edges[edge.source] - if e is not edge] - graphs.append((component, new_edges)) + # the approach is as follows: for each strongly connected component, find + # all cycles (which takens exponential time, potentially). Then break the + # edges that are part of the most cycles, until all cycles in that + # component are broken. + for component in strong_components(vertices, edges): + #print '-->', ''.join(component) + random_vertex = component.iterkeys().next() + cycles = all_cycles(random_vertex, component, edges) + if not cycles: + continue + allcycles = dict.fromkeys([id(cycle) for cycle in cycles]) + edge2cycles = {} + edge_weights = {} + for cycle in cycles: + #print '\tcycle:', [e.source+e.target for e in cycle] + for edge in cycle: + edge2cycles.setdefault(edge, []).append(cycle) + edge_weights[edge] = edge_weights.get(edge, 0) + 1 + while allcycles: + max_weight = 0 + max_edge = None + for edge, weight in edge_weights.iteritems(): + if weight >= max_weight: + max_edge = edge + max_weight = weight + broken_cycles = edge2cycles[max_edge] + assert max_edge is not None + # kill this edge + yield max_edge + for broken_cycle in broken_cycles: + try: + del allcycles[id(broken_cycle)] + except KeyError: + pass + else: + for edge in broken_cycle: + edge_weights[edge] -= 1 + if edge_weights[edge] == 0: + del edge_weights[edge] Modified: pypy/dist/pypy/tool/algo/test/test_graphlib.py ============================================================================== --- pypy/dist/pypy/tool/algo/test/test_graphlib.py (original) +++ pypy/dist/pypy/tool/algo/test/test_graphlib.py Sun Jan 13 09:06:38 2008 @@ -146,7 +146,7 @@ class TestBadCase: # a complete graph - NUM = 30 + NUM = 50 edges = make_edge_dict([Edge(i, j) for i in range(NUM) for j in range(NUM)]) vertices = dict.fromkeys(range(NUM)) From cfbolz at codespeak.net Sun Jan 13 10:46:18 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 10:46:18 +0100 (CET) Subject: [pypy-svn] r50539 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080113094618.0298216844C@codespeak.net> Author: cfbolz Date: Sun Jan 13 10:46:17 2008 New Revision: 50539 Added: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: (all): planning for today Added: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Sun Jan 13 10:46:17 2008 @@ -0,0 +1,22 @@ + +Task ideas +========== + + - try getting debug information in the Java class files (Carl Friedrich, + Paul) + + - benchmark the size of the young nursery for generational GC (Olivier, most + of Armin) + + - look at the RPython microbenchmarks for Java (Toby, Armin around) + + - work on CTypes + + - think about summarizing test outcomes + + - JVM integration (probably only when Anto is here) + + - look at the CLI integration on the clr-module-improvements/ branch and + maybe improve/merge it? + + From arigo at codespeak.net Sun Jan 13 11:17:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 11:17:38 +0100 (CET) Subject: [pypy-svn] r50540 - pypy/dist/pypy/objspace/std/test Message-ID: <20080113101738.2F9D71684C8@codespeak.net> Author: arigo Date: Sun Jan 13 11:17:37 2008 New Revision: 50540 Modified: pypy/dist/pypy/objspace/std/test/test_listmultiobject.py pypy/dist/pypy/objspace/std/test/test_rangeobject.py Log: Fix tests. Modified: pypy/dist/pypy/objspace/std/test/test_listmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_listmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_listmultiobject.py Sun Jan 13 11:17:37 2008 @@ -78,9 +78,7 @@ "RangeImplementation" in __pypy__.internal_repr(r)) return f """) - - def test_sort(self): - pass # won't work with multilists + cls.w_SORT_FORCES_LISTS = cls.space.wrap(True) class AppTest_FastSlice(BaseAppTest_ListMultiObject): Modified: pypy/dist/pypy/objspace/std/test/test_rangeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_rangeobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_rangeobject.py Sun Jan 13 11:17:37 2008 @@ -16,6 +16,7 @@ "W_ListObject" not in __pypy__.internal_repr(r)) return f """) + cls.w_SORT_FORCES_LISTS = cls.space.wrap(False) def test_simple(self): result = [] @@ -35,7 +36,8 @@ def test_empty_range(self): r = range(10, 10) - r.sort(reverse=True) + if not self.SORT_FORCES_LISTS: + r.sort(reverse=True) assert len(r) == 0 assert list(reversed(r)) == [] assert r[:] == [] @@ -64,6 +66,8 @@ assert r == [2, 1, 1] def test_sort(self): + if self.SORT_FORCES_LISTS: + skip("sort() forces these lists") r = range(10, -1, -1) r.sort() assert self.not_forced(r) From arigo at codespeak.net Sun Jan 13 11:19:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 11:19:31 +0100 (CET) Subject: [pypy-svn] r50541 - pypy/dist/pypy/objspace/std/test Message-ID: <20080113101931.0091A1684C8@codespeak.net> Author: arigo Date: Sun Jan 13 11:19:31 2008 New Revision: 50541 Modified: pypy/dist/pypy/objspace/std/test/test_listmultiobject.py Log: Fix importing style - otherwise these test classes from other test files are also executed by test_listmultiobject.py! Modified: pypy/dist/pypy/objspace/std/test/test_listmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_listmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_listmultiobject.py Sun Jan 13 11:19:31 2008 @@ -2,11 +2,11 @@ from pypy.objspace.std.listmultiobject import W_ListMultiObject, \ SliceTrackingListImplementation from pypy.conftest import gettestobjspace -from pypy.objspace.std.test.test_listobject import AppTestW_ListObject +from pypy.objspace.std.test import test_listobject from pypy.objspace.std.test.test_dictmultiobject import FakeSpace -from pypy.objspace.std.test.test_rangeobject import AppTestRangeListObject +from pypy.objspace.std.test import test_rangeobject -class BaseAppTest_ListMultiObject(AppTestW_ListObject): +class BaseAppTest_ListMultiObject(test_listobject.AppTestW_ListObject): @staticmethod def setup_class(cls, conf_switch='withmultilist', impl_tag=''): cls.space = gettestobjspace(**{"objspace.std."+conf_switch: True}) @@ -67,7 +67,7 @@ assert l == ["a", "b", "c", "d", "e", "f"] assert self.impl_used(l, "StrListImplementation") -class AppTestRangeImplementation(AppTestRangeListObject): +class AppTestRangeImplementation(test_rangeobject.AppTestRangeListObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withmultilist": True}) From pdg at codespeak.net Sun Jan 13 11:35:30 2008 From: pdg at codespeak.net (pdg at codespeak.net) Date: Sun, 13 Jan 2008 11:35:30 +0100 (CET) Subject: [pypy-svn] r50542 - pypy/dist/pypy/translator/jvm Message-ID: <20080113103530.158DB1684C6@codespeak.net> Author: pdg Date: Sun Jan 13 11:35:29 2008 New Revision: 50542 Modified: pypy/dist/pypy/translator/jvm/genjvm.py Log: (cfbolz, pdg) Add the -g switch to jasmin command in the compile method to make the resulting jars inspectable by eclipse Modified: pypy/dist/pypy/translator/jvm/genjvm.py ============================================================================== --- pypy/dist/pypy/translator/jvm/genjvm.py (original) +++ pypy/dist/pypy/translator/jvm/genjvm.py Sun Jan 13 11:35:29 2008 @@ -141,7 +141,7 @@ """ Compiles the .java sources into .class files, ready for execution. """ - jascmd = [getoption('jasmin'), '-d', str(self.javadir)] + jascmd = [getoption('jasmin'), '-g', '-d', str(self.javadir)] def split_list(files): "Split the files list into manageable pieces" From cfbolz at codespeak.net Sun Jan 13 11:36:34 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 11:36:34 +0100 (CET) Subject: [pypy-svn] r50543 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080113103634.BDACA1684C8@codespeak.net> Author: cfbolz Date: Sun Jan 13 11:36:33 2008 New Revision: 50543 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: we finished our first task! Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Sun Jan 13 11:36:33 2008 @@ -3,7 +3,7 @@ ========== - try getting debug information in the Java class files (Carl Friedrich, - Paul) + Paul) DONE - benchmark the size of the young nursery for generational GC (Olivier, most of Armin) @@ -17,6 +17,6 @@ - JVM integration (probably only when Anto is here) - look at the CLI integration on the clr-module-improvements/ branch and - maybe improve/merge it? + maybe improve/merge it? (Carl Friedrich Paul) From fijal at codespeak.net Sun Jan 13 13:03:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 13:03:05 +0100 (CET) Subject: [pypy-svn] r50544 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080113120305.DD138168422@codespeak.net> Author: fijal Date: Sun Jan 13 13:03:05 2008 New Revision: 50544 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: Missing coma Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Sun Jan 13 13:03:05 2008 @@ -17,6 +17,6 @@ - JVM integration (probably only when Anto is here) - look at the CLI integration on the clr-module-improvements/ branch and - maybe improve/merge it? (Carl Friedrich Paul) + maybe improve/merge it? (Carl Friedrich, Paul) From cfbolz at codespeak.net Sun Jan 13 13:12:20 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 13:12:20 +0100 (CET) Subject: [pypy-svn] r50545 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080113121220.6DE94168410@codespeak.net> Author: cfbolz Date: Sun Jan 13 13:12:18 2008 New Revision: 50545 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Log: (pdg, cfbolz): small code cleanups Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Sun Jan 13 13:12:18 2008 @@ -50,17 +50,19 @@ sys.modules[fullname] = clr.load_cli_class(leftStr, rightStr) else: # if not a call for actual class (say for namespaces) assign an empty module - mod = imp.new_module(fullname) - mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) - mod.__file__ = "<%s>" % self.__class__.__name__ - mod.__loader__ = self - mod.__name__ = fullname + if fullname not in sys.modules: + mod = imp.new_module(fullname) + mod.__file__ = "<%s>" % self.__class__.__name__ + mod.__loader__ = self + mod.__name__ = fullname + # add it to the modules dict + sys.modules[fullname] = mod + else: + mod = sys.modules[fullname] # if it is a PACKAGE then we are to initialize the __path__ for the module # we won't deal with Packages here - # add it to the modules list - sys.modules[fullname] = mod # treating System.Collections.Generic specially here. # this treatment is done after the empty module insertion @@ -100,10 +102,7 @@ except KeyError: pass - try: - return self.loader - except ImportError: - return None + return self.loader else: # fullname is not a .Net Module return None Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Sun Jan 13 13:12:18 2008 @@ -243,10 +243,7 @@ Return: Boolean """ - if System.Type.GetType(nameFromImporter) != None: - return space.wrap(True) - return space.wrap(False) - + return space.wrap(System.Type.GetType(nameFromImporter) is not None) isDotNetType.unwrap_spec = [ObjSpace, str] def list_of_loadedAssemblies(space): From fijal at codespeak.net Sun Jan 13 13:14:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 13:14:59 +0100 (CET) Subject: [pypy-svn] r50546 - pypy/branch/applevel-ctypes2/pypy/module/fcntl Message-ID: <20080113121459.A7E22168449@codespeak.net> Author: fijal Date: Sun Jan 13 13:14:59 2008 New Revision: 50546 Modified: pypy/branch/applevel-ctypes2/pypy/module/fcntl/interp_fcntl.py Log: Fix an obscure bug in fcntl module which disallowed us from reading terminal size. Not sure how to test it realiably though... Modified: pypy/branch/applevel-ctypes2/pypy/module/fcntl/interp_fcntl.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/fcntl/interp_fcntl.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/fcntl/interp_fcntl.py Sun Jan 13 13:14:59 2008 @@ -125,7 +125,10 @@ if len(arg) > 1024: raise OperationError(space.w_ValueError, space.wrap("fcntl string arg too long")) - rv = fcntl_str(fd, op, arg) + ll_arg = rffi.str2charp(arg) + rv = fcntl_str(fd, op, ll_arg) + arg = rffi.charp2str(ll_arg) + lltype.free(ll_arg, flavor='raw') if rv < 0: raise OperationError(space.w_IOError, space.wrap(_get_error_msg())) @@ -258,7 +261,10 @@ raise OperationError(space.w_ValueError, space.wrap("ioctl string arg too long")) - rv = ioctl_str(fd, op, arg) + ll_arg = rffi.str2charp(arg) + rv = ioctl_str(fd, op, ll_arg) + arg = rffi.charp2str(ll_arg) + lltype.free(ll_arg, flavor='raw') if rv < 0: raise OperationError(space.w_IOError, space.wrap(_get_error_msg())) From arigo at codespeak.net Sun Jan 13 13:52:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 13:52:09 +0100 (CET) Subject: [pypy-svn] r50547 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080113125209.A327E168454@codespeak.net> Author: arigo Date: Sun Jan 13 13:52:08 2008 New Revision: 50547 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/conftest.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Log: (fijal, arigo) Compile _ctypes_test.so automatically before running the tests that depend on it. Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/conftest.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/conftest.py Sun Jan 13 13:52:08 2008 @@ -0,0 +1,39 @@ +import py +import os, sys + + +def compile_so_file(): + from distutils.dist import Distribution + from distutils.extension import Extension + from distutils.ccompiler import get_default_compiler + udir = py.test.ensuretemp('_ctypes_test') + cfile = py.magic.autopath().dirpath().join("_ctypes_test.c") + saved_environ = os.environ.items() + olddir = udir.chdir() + try: + attrs = { + 'name': "_ctypes_test", + 'ext_modules': [ + Extension("_ctypes_test", [str(cfile)]), + ], + 'script_name': 'setup.py', + 'script_args': ['-q', 'build_ext', '--inplace'], + } + dist = Distribution(attrs) + if not dist.parse_command_line(): + raise ValueError, "distutils cmdline parse error" + dist.run_commands() + finally: + olddir.chdir() + for key, value in saved_environ: + if os.environ.get(key) != value: + os.environ[key] = value + + if sys.platform == 'win32': + so_ext = '.dll' + else: + so_ext = '.so' + return udir.join('_ctypes_test' + so_ext) + + +sofile = compile_so_file() Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Sun Jan 13 13:52:08 2008 @@ -7,10 +7,8 @@ int, long, long, long, float, float] def setup_module(mod): - f = py.magic.autopath().dirpath().join('_ctypes_test.so') - if not f.check(): - raise Exception("Grab your _ctypes_test.so from your python lib directory and copy it here") - mod._ctypes_test = str(f) + import conftest + mod._ctypes_test = str(conftest.sofile) class TestPointers: From cfbolz at codespeak.net Sun Jan 13 14:10:25 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 14:10:25 +0100 (CET) Subject: [pypy-svn] r50548 - pypy/branch/clr-module-improvements/pypy/module/clr/test Message-ID: <20080113131025.56C72168460@codespeak.net> Author: cfbolz Date: Sun Jan 13 14:10:22 2008 New Revision: 50548 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Log: (pdg, cfbolz): test that we would like to pass Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Sun Jan 13 14:10:22 2008 @@ -29,8 +29,11 @@ assert ArrayList is System.Collections.ArrayList def test_ImportError(self): - skip('Fixme!') def fn(): import non_existent_module - raises(ImportError, fn()) - + raises(ImportError, fn) + + def test_lazy_import(self): + py.test.skip("not working yet") + import System + System.Xml.Schema # does not raise attribute error From cfbolz at codespeak.net Sun Jan 13 14:25:38 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 14:25:38 +0100 (CET) Subject: [pypy-svn] r50549 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080113132538.EA151168454@codespeak.net> Author: cfbolz Date: Sun Jan 13 14:25:38 2008 New Revision: 50549 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Log: (pdg, cfbolz): simplify the import hook a bit. Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Sun Jan 13 14:25:38 2008 @@ -6,14 +6,32 @@ import imp import sys -class loader(object): - ''' - This method returns the loaded module or raises an exception, ImportError - loader is ONLY calld for proper .NET modules (check done in Importer class +class importer(object): + ''' + If the importer is installed on sys.meta_path, it will + receive a second argument, which is None for a top-level module, or + package.__path__ for submodules or subpackages + + It should return a loader object if the module was found, or None if it wasn't. + If find_module() raises an exception, the caller will abort the import. + When importer.find_module("spam.eggs.ham") is called, "spam.eggs" has already + been imported and added to sys.modules. ''' def __init__(self): - pass + import clr + # this might not be the correct place to load the valid NameSpaces + self.valid_name_spaces = set(clr.list_of_valid_namespaces()) + def find_module(self, fullname, path=None): + # check for true NAMESPACE or .NET TYPE + import clr + if fullname in self.valid_name_spaces or clr.isDotNetType(fullname): + # fullname is a .Net Module + return self + else: + # fullname is not a .Net Module + return None + def load_module(self, fullname): ''' The load_module() must fulfill the following *before* it runs any code: @@ -72,40 +90,3 @@ sys.modules[genericClass[: genericClass.find('`')]] = clr.load_cli_class("System.Collections.Generic", genericClass) return sys.modules[fullname] - -class importer(object): - ''' - If the importer is installed on sys.meta_path, it will - receive a second argument, which is None for a top-level module, or - package.__path__ for submodules or subpackages - - It should return a loader object if the module was found, or None if it wasn't. - If find_module() raises an exception, the caller will abort the import. - When importer.find_module("spam.eggs.ham") is called, "spam.eggs" has already - been imported and added to sys.modules. - ''' - def __init__(self): - import clr - # this might not be the correct place to load the valid NameSpaces - self.ValidNameSpaces = clr.list_of_valid_namespaces() - self.loader = loader() - - def find_module(self, fullname, path = None): - # check for true NAMESPACE or .NET TYPE - import clr - if fullname in self.ValidNameSpaces or clr.isDotNetType(fullname): - # fullname is a .Net Module - if path != None: - __path__ = path - try: - return sys.modules[fullname] - except KeyError: - pass - - return self.loader - else: - # fullname is not a .Net Module - return None - - - Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Sun Jan 13 14:25:38 2008 @@ -33,7 +33,13 @@ import non_existent_module raises(ImportError, fn) + def test_import_twice(self): + import System + s1 = System + import System + assert s1 is System + def test_lazy_import(self): - py.test.skip("not working yet") + skip("not working yet") import System System.Xml.Schema # does not raise attribute error From cfbolz at codespeak.net Sun Jan 13 14:56:23 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 14:56:23 +0100 (CET) Subject: [pypy-svn] r50550 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080113135623.967CF16845F@codespeak.net> Author: cfbolz Date: Sun Jan 13 14:56:23 2008 New Revision: 50550 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Log: (pdg, cfbolz): make the importing of .NET classes lazily: it's now enough to say "import System" and then use System.Collections.Stack, which is loaded as necessary. Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Sun Jan 13 14:56:23 2008 @@ -1,3 +1,4 @@ +"""NOT_RPYTHON""" # Meta hooks are called at the start of Import Processing # Meta hooks can override the sys.path, frozen modules , built-in modules @@ -5,6 +6,7 @@ import imp import sys +import types class importer(object): ''' @@ -64,12 +66,12 @@ rindex = fullname.rfind('.') if rindex != -1: leftStr = fullname[:rindex] - rightStr= fullname[rindex+1:] + rightStr = fullname[rindex+1:] sys.modules[fullname] = clr.load_cli_class(leftStr, rightStr) else: # if not a call for actual class (say for namespaces) assign an empty module if fullname not in sys.modules: - mod = imp.new_module(fullname) + mod = CLRModule(fullname) mod.__file__ = "<%s>" % self.__class__.__name__ mod.__loader__ = self mod.__name__ = fullname @@ -90,3 +92,14 @@ sys.modules[genericClass[: genericClass.find('`')]] = clr.load_cli_class("System.Collections.Generic", genericClass) return sys.modules[fullname] + +class CLRModule(types.ModuleType): + def __getattr__(self, name): + if not name.startswith("__"): + try: + iname = self.__name__ + '.' + name + mod = __import__(iname) + except ImportError: + pass + return types.ModuleType.__getattribute__(self, name) + Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Sun Jan 13 14:56:23 2008 @@ -15,7 +15,7 @@ Math = clr.load_cli_class('System', 'Math') assert Math is System.Math - import System.Collections.Stack + import System a = System.Collections.Stack() a.Push(3) a.Push(44) @@ -40,6 +40,5 @@ assert s1 is System def test_lazy_import(self): - skip("not working yet") import System System.Xml.Schema # does not raise attribute error From cfbolz at codespeak.net Sun Jan 13 15:09:59 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 13 Jan 2008 15:09:59 +0100 (CET) Subject: [pypy-svn] r50551 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080113140959.50E57168454@codespeak.net> Author: cfbolz Date: Sun Jan 13 15:09:57 2008 New Revision: 50551 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Log: (pdg, cfbolz): use the proper reflection way to find out whether a class implements an interface Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Sun Jan 13 15:09:57 2008 @@ -324,10 +324,7 @@ # this is where we locate the interfaces inherited by the class # set the flag hasIEnumerable if IEnumerable interface has been by the class - hasIEnumerable = False - for interface in b_type.GetInterfaces(): - if interface.ToString() == "System.Collections.IEnumerable": - hasIEnumerable = True + hasIEnumerable = b_type.GetInterface("System.Collections.IEnumerable") is not None # this is where we test if the class is Generic # set the flag isClassGeneric From fijal at codespeak.net Sun Jan 13 15:21:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 15:21:28 +0100 (CET) Subject: [pypy-svn] r50552 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080113142128.E19C616845F@codespeak.net> Author: fijal Date: Sun Jan 13 15:21:28 2008 New Revision: 50552 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py Log: (arigo, fijal) Add a shape attribute which points back from array instance to array (same for structure) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Sun Jan 13 15:21:28 2008 @@ -108,6 +108,7 @@ __setitem__ = interp2app(W_ArrayInstance.setitem), __getitem__ = interp2app(W_ArrayInstance.getitem), buffer = GetSetProperty(W_ArrayInstance.getbuffer), + shape = interp_attrproperty('shape', W_ArrayInstance), free = interp2app(W_ArrayInstance.free), ) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py Sun Jan 13 15:21:28 2008 @@ -5,6 +5,7 @@ from pypy.interpreter.baseobjspace import W_Root, Wrappable from pypy.interpreter.gateway import interp2app, ObjSpace +from pypy.interpreter.typedef import interp_attrproperty from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi @@ -161,6 +162,7 @@ __setattr__ = interp2app(W_StructureInstance.setattr), buffer = GetSetProperty(W_StructureInstance.getbuffer), free = interp2app(W_StructureInstance.free), + shape = interp_attrproperty('shape', W_StructureInstance), ) W_StructureInstance.typedef.acceptable_as_base_class = False From fijal at codespeak.net Sun Jan 13 15:22:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 15:22:03 +0100 (CET) Subject: [pypy-svn] r50553 - pypy/branch/applevel-ctypes2/pypy/module/_ffi/test Message-ID: <20080113142203.5EA0216845F@codespeak.net> Author: fijal Date: Sun Jan 13 15:22:02 2008 New Revision: 50553 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: (arigo, fijal) Add a test as well Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 13 15:22:02 2008 @@ -358,3 +358,14 @@ assert a[0] == 3 assert A.fromaddress(a.buffer, 1)[0] == 3 # a.free() - don't free as ll2ctypes is complaining massively + + def test_shape(self): + import _ffi + A = _ffi.Array('i') + a = A(1) + assert a.shape is A + a.free() + S = _ffi.Structure([('v1', 'i')]) + s = S(v1=3) + assert s.shape is S + s.free() From atobe at codespeak.net Sun Jan 13 15:35:08 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Sun, 13 Jan 2008 15:35:08 +0100 (CET) Subject: [pypy-svn] r50554 - in pypy/dist/pypy/translator: . jvm jvm/test Message-ID: <20080113143508.30E2B16845F@codespeak.net> Author: atobe Date: Sun Jan 13 15:35:07 2008 New Revision: 50554 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/jvm/genjvm.py pypy/dist/pypy/translator/jvm/test/runtest.py Log: Bought execution interface of JvmGeneratedSourceWrapper into line with that of CliFunctionWrapper Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sun Jan 13 15:35:07 2008 @@ -708,8 +708,9 @@ def task_compile_jvm(self): from pypy.translator.oosupport.support import unpatch_os + from pypy.translator.jvm.test.runtest import JvmGeneratedSourceWrapper self.jvmsource.compile() - self.c_entryp = lambda *args: eval(self.jvmsource.execute(args)) + self.c_entryp = JvmGeneratedSourceWrapper(self.jvmsource) # restore original os values if hasattr(self, 'old_cli_defs'): unpatch_os(self.old_cli_defs) Modified: pypy/dist/pypy/translator/jvm/genjvm.py ============================================================================== --- pypy/dist/pypy/translator/jvm/genjvm.py (original) +++ pypy/dist/pypy/translator/jvm/genjvm.py Sun Jan 13 15:35:07 2008 @@ -104,7 +104,7 @@ res = subp.wait() if res or (not allow_stderr and stderr): raise JvmSubprogramError(res, args, stdout, stderr) - return stdout, stderr + return stdout, stderr, res def _compile_helper(self): # HACK: compile the Java helper classes. Should eventually @@ -187,15 +187,16 @@ assert self.compiled strargs = [self._make_str(a) for a in args] cmd = [getoption('java'), + '-Xmx256M', # increase the heapsize so the microbenchmarks run '-cp', str(self.javadir), self.package+".Main"] + strargs print "Invoking java to run the code" - stdout, stderr = self._invoke(cmd, True) + stdout, stderr, retval = self._invoke(cmd, True) print "...done!" sys.stderr.write(stderr) - return stdout - + return stdout, stderr, retval + def generate_source_for_function(func, annotation, backendopt=False): """ Modified: pypy/dist/pypy/translator/jvm/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/runtest.py (original) +++ pypy/dist/pypy/translator/jvm/test/runtest.py Sun Jan 13 15:35:07 2008 @@ -60,6 +60,22 @@ """ gensrc is an instance of JvmGeneratedSource """ self.gensrc = gensrc + def run(self,*args): + if not self.gensrc.compiled: + py.test.skip("Assembly disabled") + + if getoption('norun'): + py.test.skip("Execution disabled") + +# if self._exe is None: +# py.test.skip("Compilation disabled") + +# if getoption('norun'): +# py.test.skip("Execution disabled") + + stdout, stderr, retval = self.gensrc.execute(args) + return stdout, stderr, retval + def __call__(self, *args): if not self.gensrc.compiled: py.test.skip("Assembly disabled") @@ -67,9 +83,8 @@ if getoption('norun'): py.test.skip("Execution disabled") - resstr = self.gensrc.execute(args) - print "resstr=%s" % repr(resstr) - res = eval(resstr) + stdout, stderr, retval = self.gensrc.execute(args) + res = eval(stdout.strip()) if isinstance(res, tuple): res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. elif isinstance(res, list): From atobe at codespeak.net Sun Jan 13 15:36:22 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Sun, 13 Jan 2008 15:36:22 +0100 (CET) Subject: [pypy-svn] r50555 - pypy/dist/pypy/rpython/microbench Message-ID: <20080113143622.C9B5A16845F@codespeak.net> Author: atobe Date: Sun Jan 13 15:36:22 2008 New Revision: 50555 Modified: pypy/dist/pypy/rpython/microbench/microbench.py Log: Added microbenchmarks for JVM Modified: pypy/dist/pypy/rpython/microbench/microbench.py ============================================================================== --- pypy/dist/pypy/rpython/microbench/microbench.py (original) +++ pypy/dist/pypy/rpython/microbench/microbench.py Sun Jan 13 15:36:22 2008 @@ -35,14 +35,16 @@ def run_benchmark(exe): from pypy.translator.cli.test.runtest import CliFunctionWrapper - if isinstance(exe, CliFunctionWrapper): + from pypy.translator.jvm.test.runtest import JvmGeneratedSourceWrapper + + if exe.__class__ in [CliFunctionWrapper,JvmGeneratedSourceWrapper]: stdout, stderr, retval = exe.run() else: assert isinstance(exe, str) bench = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = bench.communicate() retval = bench.wait() - + if retval != 0: print 'Running benchmark failed' print 'Standard Output:' @@ -51,7 +53,7 @@ print 'Standard Error:' print stderr raise SystemExit(-1) - + mydict = {} for line in stdout.splitlines(): name, res = line.split(':') @@ -66,7 +68,7 @@ for module in glob('*.py'): if module not in ('__init__.py', 'autopath.py', 'microbench.py'): modules.append(module) - + for module in modules: module = module.rstrip('.py') exec 'from %s import *' % module in globals() @@ -83,25 +85,33 @@ for name, func in benchmarks: print name, ':', func() return 0 - + t = Translation(entry_point, standalone=True, backend='c') c_exe = t.compile() t = Translation(entry_point, standalone=True, backend='cli') cli_exe = t.compile() - + t = Translation(entry_point, standalone=True, backend='jvm') + jvm_exe = t.compile() + c_res = run_benchmark(c_exe) cli_res = run_benchmark(cli_exe) - - print 'benchmark genc gencli ratio' + jvm_res = run_benchmark(jvm_exe) + + print 'benchmark genc gencli cli_ratio genjvm jvm_ratio' print for name, _ in benchmarks: c_time = c_res[name] cli_time = cli_res[name] + jvm_time = jvm_res[name] + if c_time == 0: + cli_ratio = '%10s' % '---' + else: + cli_ratio = '%10.2f' % (cli_time/c_time) if c_time == 0: - ratio = '%10s' % '---' + jvm_ratio = '%10s' % '---' else: - ratio = '%10.2f' % (cli_time/c_time) - print '%-32s %10.2f %10.2f %s' % (name, c_time, cli_time, ratio) + jvm_ratio = '%10.2f' % (jvm_time/c_time) + print '%-32s %10.2f %10.2f %s %10.2f %s' % (name, c_time, cli_time, cli_ratio, jvm_time, jvm_ratio) if __name__ == '__main__': main() From fijal at codespeak.net Sun Jan 13 15:48:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 15:48:51 +0100 (CET) Subject: [pypy-svn] r50556 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080113144851.510CD168436@codespeak.net> Author: fijal Date: Sun Jan 13 15:48:50 2008 New Revision: 50556 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: Support for raw pointers and a test. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sun Jan 13 15:48:50 2008 @@ -189,6 +189,8 @@ # check for NULL ptr if space.is_w(w_arg, space.w_None): push_func(add_arg, argdesc, lltype.nullptr(rffi.VOIDP.TO)) + elif space.is_true(space.isinstance(w_arg, space.w_int)): + push_func(add_arg, argdesc, rffi.cast(rffi.VOIDP, space.int_w(w_arg))) elif space.is_true(space.isinstance(w_arg, space.w_basestring)): if to_free is not None: to_free.append(pack_pointer(space, add_arg, argdesc, w_arg, push_func)) Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 13 15:48:50 2008 @@ -369,3 +369,21 @@ s = S(v1=3) assert s.shape is S s.free() + + def test_negative_pointers(self): + import _ffi + A = _ffi.Array('P') + a = A(1) + a[0] = -1234 + a.free() + + def test_passing_raw_pointers(self): + import _ffi + lib = _ffi.CDLL(self.lib_name) + A = _ffi.Array('i') + get_array_elem = lib.ptr('get_array_elem', ['P', 'i'], 'i') + a = A(1) + a[0] = 3 + res = get_array_elem(a.buffer, 0) + assert res == 3 + a.free() From arigo at codespeak.net Sun Jan 13 15:49:01 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 15:49:01 +0100 (CET) Subject: [pypy-svn] r50557 - in pypy/branch/applevel-ctypes2/pypy/lib: _ctypes ctypes Message-ID: <20080113144901.53BE0168461@codespeak.net> Author: arigo Date: Sun Jan 13 15:49:00 2008 New Revision: 50557 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py pypy/branch/applevel-ctypes2/pypy/lib/ctypes/__init__.py Log: Re-enable the sanity-check that protects against misconfigured libffi. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Sun Jan 13 15:49:00 2008 @@ -16,11 +16,19 @@ return "" % (self.ffiletter, self.raw_value) +TP_TO_FFITP = { # XXX this should die; interp_ffi should just accept them + 'O': 'P', + 'z': 's', +} + + def sizeof(tp): - return _ffi.sizeof(tp._type_) + ffitp = tp._type_ + return _ffi.sizeof(TP_TO_FFITP.get(ffitp, ffitp)) def alignment(tp): - return _ffi.alignment(tp._type_) + ffitp = tp._type_ + return _ffi.alignment(TP_TO_FFITP.get(ffitp, ffitp)) def byref(cdata): from ctypes import pointer, _SimpleCData Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Sun Jan 13 15:49:00 2008 @@ -2,17 +2,12 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" -from _ctypes.basics import _CData, CArgObject +from _ctypes.basics import _CData, CArgObject, TP_TO_FFITP class NULL(object): pass NULL = NULL() -TP_TO_FFITP = { - 'O': 'P', - 'z': 's', -} - TP_TO_DEFAULT = { 'c': 0, 'b': 0, Modified: pypy/branch/applevel-ctypes2/pypy/lib/ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/ctypes/__init__.py Sun Jan 13 15:49:00 2008 @@ -136,7 +136,6 @@ def _check_size(typ, typecode=None): # Check if sizeof(ctypes_type) against struct.calcsize. This # should protect somewhat against a misconfigured libffi. - return # XXXXXXXXX from struct import calcsize if typecode is None: # Most _type_ codes are the same as used in struct From fijal at codespeak.net Sun Jan 13 16:44:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 16:44:43 +0100 (CET) Subject: [pypy-svn] r50558 - pypy/dist/pypy/translator/tool Message-ID: <20080113154443.4BDAC16844A@codespeak.net> Author: fijal Date: Sun Jan 13 16:44:41 2008 New Revision: 50558 Modified: pypy/dist/pypy/translator/tool/cbuild.py Log: Missing header. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sun Jan 13 16:44:41 2008 @@ -130,6 +130,7 @@ f = filename.open("w") if being_main: f.write("#define PYPY_NOT_MAIN_FILE\n") + self.write_c_header(f) f.write(str(source)) f.close() files.append(str(filename)) From fijal at codespeak.net Sun Jan 13 17:02:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 17:02:07 +0100 (CET) Subject: [pypy-svn] r50559 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080113160207.C7425168452@codespeak.net> Author: fijal Date: Sun Jan 13 17:02:07 2008 New Revision: 50559 Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Log: Add additional test for pointer to pointer. Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Sun Jan 13 17:02:07 2008 @@ -102,6 +102,16 @@ py.test.raises(TypeError, delitem, p, 0) + def test_pointer_to_pointer(self): + x = c_int(32) + y = c_int(42) + p1 = pointer(x) + p2 = pointer(p1) + assert p2.contents.contents.value == 32 + p2.contents.contents = y + assert p2.contents.contents.value == 42 + assert p1.contents.value == 42 + def test_from_address(self): py.test.skip("It cannot work") from array import array From fijal at codespeak.net Sun Jan 13 17:03:15 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 17:03:15 +0100 (CET) Subject: [pypy-svn] r50560 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080113160315.581AA168452@codespeak.net> Author: fijal Date: Sun Jan 13 17:03:14 2008 New Revision: 50560 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: (arigo, fijal) Sort out ctypes a bit. Fix pointer situation, start arrays. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Sun Jan 13 17:03:14 2008 @@ -1,4 +1,4 @@ -from _ctypes.dummy import Union, Array +from _ctypes.dummy import Union from _ctypes.dummy import ArgumentError, addressof from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr @@ -10,7 +10,7 @@ from _ctypes.function import CFuncPtr from _ctypes.dll import dlopen from _ctypes.structure import Structure - +from _ctypes.array import Array __version__ = '1.0.2' #XXX platform dependant? Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Sun Jan 13 17:03:14 2008 @@ -4,7 +4,8 @@ class _CData(object): """ The most basic object for all ctypes types """ - pass + def __ctypes_from_outparam__(self): + return self class CArgObject(object): def __init__(self, letter, raw_value, _type): @@ -36,3 +37,7 @@ raise TypeError("expected CData instance") return pointer(cdata)._as_ffi() +def cdata_from_address(self, address): + instance = self.__new__(self) + instance._array = self._ffiarray.fromaddress(address, 1) + return instance Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dummy.py Sun Jan 13 17:03:14 2008 @@ -4,9 +4,6 @@ class Union(object): __metaclass__ = UnionType -class Array(type): - pass - class ArgumentError(Exception): pass Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Sun Jan 13 17:03:14 2008 @@ -13,7 +13,6 @@ _restype = None def __init__(self, stuff): if isinstance(stuff, tuple): - print stuff name, dll = stuff self.name = name self.dll = dll @@ -38,7 +37,7 @@ return res else: # XXX pointers - return self.restype(address=res) + return self.restype(res) def _getfuncptr(self, args): if self._funcptr is not None: Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Sun Jan 13 17:03:14 2008 @@ -1,6 +1,6 @@ import _ffi -from _ctypes.basics import _CData, CArgObject +from _ctypes.basics import _CData, CArgObject, cdata_from_address DEFAULT_VALUE = object() @@ -18,15 +18,10 @@ for k, v in d.iteritems(): setattr(obj, k, v) if '_type_' in typedict: - ffiarray = _ffi.Array(typedict['_type_']._ffiletter) - def __init__(self, value=0, address=DEFAULT_VALUE): - if address is not DEFAULT_VALUE: - self._array = ffiarray.fromaddress(address, 1) - elif value == 0: - # null pointer - self._array = ffiarray.fromaddress(0, 1) - else: - self._array = ffiarray.fromaddress(value._array.buffer, 1) + ffiarray = _ffi.Array('P') + def __init__(self, value=0): + self._array = ffiarray(1) + self.contents = value obj._ffiarray = ffiarray else: def __init__(self, value=0): @@ -34,12 +29,14 @@ obj.__init__ = __init__ return obj + from_address = cdata_from_address + def from_param(self, param): # XXX think deeper about that if isinstance(param, CArgObject): return param else: - return self(address=param._array.buffer)._as_ffi() + return self.from_address(param._array.buffer)._as_ffi() class _Pointer(_CData): __metaclass__ = PointerType @@ -50,18 +47,25 @@ value = property(getvalue) def getcontents(self): - return self._type_.from_address(self._array.buffer) + return self._type_.from_address(self._array[0]) def setcontents(self, value): - self._array = self._ffiarray.fromaddress(value._array.buffer, 1) + if isinstance(value, int): + self._array[0] = value + else: + self._array[0] = value._array def _as_ffi(self): - return CArgObject('P', self._array, type(self)) + # XXX performance + return CArgObject('P', self._type_.from_address(self._array[0])._array, type(self)) def __getitem__(self, item): - return self._array[item] + assert item == 0 + return self._type_.from_address(self._array[0]).__ctypes_from_outparam__() def __setitem__(self, item, value): - self._array[item] = value + if item != 0: + raise IndexError + self._type_.from_address(self._array[item]).value = value contents = property(getcontents, setcontents) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Sun Jan 13 17:03:14 2008 @@ -2,7 +2,8 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" -from _ctypes.basics import _CData, CArgObject, TP_TO_FFITP +from _ctypes.basics import _CData, CArgObject, cdata_from_address, TP_TO_FFITP +from _ctypes.array import create_array_type class NULL(object): pass @@ -40,24 +41,15 @@ default = TP_TO_DEFAULT[tp] ffitp = TP_TO_FFITP.get(tp, tp) ffiarray = _ffi.Array(ffitp) - def __init__(self, value=DEFAULT_VALUE, address=DEFAULT_VALUE): - if address is not DEFAULT_VALUE: - self._array = ffiarray.fromaddress(address, 1) - else: - self._array = ffiarray(1) - if value is not DEFAULT_VALUE: - self._array[0] = value - dct['__init__'] = __init__ result = type.__new__(self, name, bases, dct) result._ffiletter = tp result._ffiarray = ffiarray return result - def from_address(self, address): - return self(address=address) + from_address = cdata_from_address def __mul__(self, other): - pass + return create_array_type(self, other) def from_param(self, value): return self(value)._as_ffi() @@ -66,13 +58,24 @@ __metaclass__ = SimpleType _type_ = 'i' + def __init__(self, value=DEFAULT_VALUE): + #if address is not DEFAULT_VALUE: + # self._array = ffiarray.fromaddress(address, 1) + #else: + self._array = self._ffiarray(1) + if value is not DEFAULT_VALUE: + self._array[0] = value + def _getvalue(self): return self._array[0] - def _setvalue(self, val): + def _setvalue(self, value): self._array[0] = value value = property(_getvalue, _setvalue) + def __ctypes_from_outparam__(self): + return self._array[0] + def _as_ffi(self): return CArgObject(self._type_, self.value, type(self)) From fijal at codespeak.net Sun Jan 13 17:03:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 17:03:39 +0100 (CET) Subject: [pypy-svn] r50561 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080113160339.9DAFF168452@codespeak.net> Author: fijal Date: Sun Jan 13 17:03:38 2008 New Revision: 50561 Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (contents, props changed) Log: (arigo, fijal) Add array file as well Added: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Sun Jan 13 17:03:38 2008 @@ -0,0 +1,45 @@ + +import _ffi + +from _ctypes.basics import _CData + +class ArrayMeta(type): + def __new__(self, name, cls, typedict): + res = type.__new__(self, name, cls, typedict) + res._ffiletter = 'P' + if '_type_' in typedict: + ffiarray = _ffi.Array(typedict['_type_']._ffiletter) + res._ffiarray = ffiarray + else: + res._ffiarray = None + return res + +class Array(_CData): + __metaclass__ = ArrayMeta + + def __init__(self, *args): + self._array = self._ffiarray(self._length_) + for i, arg in enumerate(args): + self[i] = arg + + def __setitem__(self, item, value): + xxx + + def __getitem__(self, item): + xxx + +ARRAY_CACHE = {} + +def create_array_type(base, length): + key = (base, length) + try: + return ARRAY_CACHE[key] + except KeyError: + name = "%s_Array_%d" % (base.__name__, length) + tpdict = dict( + _length_ = length, + _type_ = base + ) + cls = ArrayMeta(name, (Array,), tpdict) + ARRAY_CACHE[key] = cls + return cls From fijal at codespeak.net Sun Jan 13 17:35:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 17:35:05 +0100 (CET) Subject: [pypy-svn] r50562 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080113163505.6183816844F@codespeak.net> Author: fijal Date: Sun Jan 13 17:35:03 2008 New Revision: 50562 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_array.py (contents, props changed) Log: Port test_array Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_array.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_array.py Sun Jan 13 17:35:03 2008 @@ -0,0 +1,110 @@ + +import py +from ctypes import * + +formats = "bBhHiIlLqQfd" + +formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ + c_long, c_ulonglong, c_float, c_double + +class TestArray: + def test_simple(self): + # create classes holding simple numeric types, and check + # various properties. + + init = range(15, 25) + + for fmt in formats: + alen = len(init) + int_array = ARRAY(fmt, alen) + + ia = int_array(*init) + # length of instance ok? + assert len(ia) == alen + + # slot values ok? + values = [ia[i] for i in range(len(init))] + assert values == init + + # change the items + from operator import setitem + new_values = range(42, 42+alen) + [setitem(ia, n, new_values[n]) for n in range(alen)] + values = [ia[i] for i in range(len(init))] + assert values == new_values + + # are the items initialized to 0? + ia = int_array() + values = [ia[i] for i in range(len(init))] + assert values == [0] * len(init) + + # Too many in itializers should be caught + py.test.raises(IndexError, int_array, *range(alen*2)) + + CharArray = ARRAY(c_char, 3) + + ca = CharArray("a", "b", "c") + + # Should this work? It doesn't: + # CharArray("abc") + py.test.raises(TypeError, CharArray, "abc") + + assert ca[0] == "a" + assert ca[1] == "b" + assert ca[2] == "c" + assert ca[-3] == "a" + assert ca[-2] == "b" + assert ca[-1] == "c" + + assert len(ca) == 3 + + # slicing is now supported, but not extended slicing (3-argument)! + from operator import getslice, delitem + py.test.raises(TypeError, getslice, ca, 0, 1, -1) + + # cannot delete items + py.test.raises(TypeError, delitem, ca, 0) + + def test_numeric_arrays(self): + + alen = 5 + + numarray = ARRAY(c_int, alen) + + na = numarray() + values = [na[i] for i in range(alen)] + assert values == [0] * alen + + na = numarray(*[c_int()] * alen) + values = [na[i] for i in range(alen)] + assert values == [0]*alen + + na = numarray(1, 2, 3, 4, 5) + values = [i for i in na] + assert values, [1, 2, 3, 4 == 5] + + na = numarray(*map(c_int, (1, 2, 3, 4, 5))) + values = [i for i in na] + assert values, [1, 2, 3, 4 == 5] + + def test_classcache(self): + assert not ARRAY(c_int, 3) is ARRAY(c_int, 4) + assert ARRAY(c_int, 3) is ARRAY(c_int, 3) + + def test_from_address(self): + # Failed with 0.9.8, reported by JUrner + p = create_string_buffer("foo") + sz = (c_char * 3).from_address(addressof(p)) + assert sz[:] == "foo" + assert sz.value == "foo" + + try: + create_unicode_buffer + except NameError: + pass + else: + def test_from_addressW(self): + p = create_unicode_buffer("foo") + sz = (c_wchar * 3).from_address(addressof(p)) + assert sz[:] == "foo" + assert sz.value == "foo" From fijal at codespeak.net Sun Jan 13 18:31:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 18:31:58 +0100 (CET) Subject: [pypy-svn] r50563 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080113173158.BDC04168455@codespeak.net> Author: fijal Date: Sun Jan 13 18:31:56 2008 New Revision: 50563 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Log: Wack enough to make test_array pass. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Sun Jan 13 18:31:56 2008 @@ -1,10 +1,10 @@ from _ctypes.dummy import Union -from _ctypes.dummy import ArgumentError, addressof +from _ctypes.dummy import ArgumentError from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr from _ctypes.dummy import _cast_addr -from _ctypes.basics import _CData, sizeof, alignment, byref +from _ctypes.basics import _CData, sizeof, alignment, byref, addressof from _ctypes.primitive import _SimpleCData from _ctypes.pointer import _Pointer from _ctypes.function import CFuncPtr Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Sun Jan 13 18:31:56 2008 @@ -1,7 +1,7 @@ import _ffi -from _ctypes.basics import _CData +from _ctypes.basics import _CData, cdata_from_address class ArrayMeta(type): def __new__(self, name, cls, typedict): @@ -10,10 +10,29 @@ if '_type_' in typedict: ffiarray = _ffi.Array(typedict['_type_']._ffiletter) res._ffiarray = ffiarray + if typedict['_type_']._type_ == 'c': + def getvalue(self): + res = [] + i = 0 + while i < self._length_ and self[i] != '\x00': + res.append(self[i]) + i += 1 + return "".join(res) + def setvalue(self, val): + for i in range(min(len(val), self._length_)): + self[i] = val[i] + self[len(val)] = '\x00' + res.value = property(getvalue, setvalue) + + def getraw(self): + return "".join([self[i] for i in range(self._length_)]) + res.raw = property(getraw) else: res._ffiarray = None return res + from_address = cdata_from_address + class Array(_CData): __metaclass__ = ArrayMeta @@ -22,11 +41,49 @@ for i, arg in enumerate(args): self[i] = arg + def _fix_item(self, item): + if item >= self._length_: + raise IndexError + if item < 0: + return self._length_ + item + return item + + def _get_slice_params(self, item): + if item.step is not None: + raise TypeError("3 arg slices not supported (for no reason)") + start = item.start or 0 + stop = item.stop or self._length_ + return start, stop + + def _slice_setitem(self, item, value): + start, stop = self._get_slice_params(item) + for i in range(start, stop): + self[i] = value[i - start] + + def _slice_getitem(self, item): + start, stop = self._get_slice_params(item) + return "".join([self[i] for i in range(start, stop)]) + def __setitem__(self, item, value): - xxx + if isinstance(item, slice): + self._slice_setitem(item, value) + # XXX + from ctypes import _SimpleCData + if isinstance(value, _SimpleCData): + value = value.value + item = self._fix_item(item) + if self._type_._ffiletter == 'c' and len(value) > 1: + raise TypeError("Expected strings of length 1") + self._array[item] = value def __getitem__(self, item): - xxx + if isinstance(item, slice): + return self._slice_getitem(item) + item = self._fix_item(item) + return self._array[item] + + def __len__(self): + return self._length_ ARRAY_CACHE = {} Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Sun Jan 13 18:31:56 2008 @@ -39,5 +39,10 @@ def cdata_from_address(self, address): instance = self.__new__(self) - instance._array = self._ffiarray.fromaddress(address, 1) + lgt = getattr(self, '_length_', 1) + instance._array = self._ffiarray.fromaddress(address, lgt) return instance + +def addressof(tp): + # XXX we should have a method on each.. + return tp._array.buffer From arigo at codespeak.net Sun Jan 13 18:32:46 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 18:32:46 +0100 (CET) Subject: [pypy-svn] r50564 - pypy/branch/applevel-ctypes2/pypy/config Message-ID: <20080113173246.DA8CE168455@codespeak.net> Author: arigo Date: Sun Jan 13 18:32:46 2008 New Revision: 50564 Modified: pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py Log: The _ffi module needs the interp-level struct module because the default app-level struct has no support for 'P'. Modified: pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py (original) +++ pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py Sun Jan 13 18:32:46 2008 @@ -34,7 +34,8 @@ del working_modules["crypt"] -module_dependencies = { } +module_dependencies = {'_ffi': [("objspace.usemodules.struct", True)], + } if os.name == "posix": module_dependencies['rctime'] = [("objspace.usemodules.select", True),] From arigo at codespeak.net Sun Jan 13 18:33:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 18:33:58 +0100 (CET) Subject: [pypy-svn] r50565 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080113173358.74EDC168455@codespeak.net> Author: arigo Date: Sun Jan 13 18:33:58 2008 New Revision: 50565 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Log: Workaround for an unclear meaning in libffi. Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sun Jan 13 18:33:58 2008 @@ -17,6 +17,19 @@ def __init__(self, msg): self.msg = msg + +def _signed_type_for(TYPE): + sz = rffi.sizeof(TYPE) + if sz == 4: return ffi_type_sint32 + elif sz == 8: return ffi_type_sint64 + else: raise ValueError("unsupported type size for %r" % (TYPE,)) + +def _unsigned_type_for(TYPE): + sz = rffi.sizeof(TYPE) + if sz == 4: return ffi_type_uint32 + elif sz == 8: return ffi_type_uint64 + else: raise ValueError("unsupported type size for %r" % (TYPE,)) + TYPEMAP = { # XXX A mess with unsigned/signed/normal chars :-/ 'c' : ffi_type_uchar, @@ -26,11 +39,12 @@ 'H' : ffi_type_ushort, 'i' : ffi_type_sint, 'I' : ffi_type_uint, - 'l' : ffi_type_slong, - 'L' : ffi_type_ulong, - # XXX I'm not sure what is long long here, let's assume it's 64 bit :-/ - 'q' : ffi_type_sint64, - 'Q' : ffi_type_uint64, + # xxx don't use ffi_type_slong and ffi_type_ulong - their meaning + # changes from a libffi version to another :-(( + 'l' : _signed_type_for(rffi.LONG), + 'L' : _unsigned_type_for(rffi.ULONG), + 'q' : _signed_type_for(rffi.LONGLONG), + 'Q' : _unsigned_type_for(rffi.ULONGLONG), 'f' : ffi_type_float, 'd' : ffi_type_double, 's' : ffi_type_pointer, From fijal at codespeak.net Sun Jan 13 18:46:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 18:46:53 +0100 (CET) Subject: [pypy-svn] r50566 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080113174653.4858D168455@codespeak.net> Author: fijal Date: Sun Jan 13 18:46:52 2008 New Revision: 50566 Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py Log: Delete nonsense tests Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_strings.py Sun Jan 13 18:46:52 2008 @@ -29,19 +29,13 @@ buf = c_buffer(32) buf.value = "Hello, World" - assert buf.value, "Hello == World" - - py.test.raises(TypeError, setattr, buf, "value", buffer("Hello, World")) - py.test.raises(TypeError, setattr, buf, "value", buffer("abc")) - py.test.raises(ValueError, setattr, buf, "raw", buffer("x" * 100)) + assert buf.value == "Hello, World" def test_c_buffer_raw(self): buf = c_buffer(32) - buf.raw = buffer("Hello, World") - assert buf.value, "Hello == World" - py.test.raises(TypeError, setattr, buf, "value", buffer("abc")) - py.test.raises(ValueError, setattr, buf, "raw", buffer("x" * 100)) + buf.raw = "Hello, World" + assert buf.value == "Hello, World" def test_param_1(self): BUF = c_char * 4 @@ -75,112 +69,7 @@ buf[1] = u"Z" assert buf.value == u"xZCD" -class TestString: - def XX_test_basic_strings(self): - cs = c_string("abcdef") - - # Cannot call len on a c_string any longer - py.test.raises(TypeError, len, cs) - assert sizeof(cs) == 7 - - # The value property is the string up to the first terminating NUL. - assert cs.value == "abcdef" - assert c_string("abc\000def").value == "abc" - - # The raw property is the total buffer contents: - assert cs.raw == "abcdef\000" - assert c_string("abc\000def").raw == "abc\000def\000" - - # We can change the value: - cs.value = "ab" - assert cs.value == "ab" - assert cs.raw == "ab\000\000\000\000\000" - - cs.raw = "XY" - assert cs.value == "XY" - assert cs.raw == "XY\000\000\000\000\000" - - py.test.raises(TypeError, c_string, u"123") - - def XX_test_sized_strings(self): - - # New in releases later than 0.4.0: - py.test.raises(TypeError, c_string, None) - - # New in releases later than 0.4.0: - # c_string(number) returns an empty string of size number - assert len(c_string(32).raw) == 32 - py.test.raises(ValueError, c_string, -1) - py.test.raises(ValueError, c_string, 0) - - # These tests fail, because it is no longer initialized -## self.failUnless(c_string(2).value == "") -## self.failUnless(c_string(2).raw == "\000\000") - self.failUnless(c_string(2).raw[-1] == "\000") - self.failUnless(len(c_string(2).raw) == 2) - - def XX_test_initialized_strings(self): - - assert c_string("ab", 4).raw[:2] == "ab" - assert c_string("ab", 4).raw[-1] == "\000" - assert c_string("ab", 2).raw == "a\000" - - def XX_test_toolong(self): - cs = c_string("abcdef") - # Much too long string: - py.test.raises(ValueError, setattr, cs, "value", "123456789012345") - - # One char too long values: - py.test.raises(ValueError, setattr, cs, "value", "1234567") - -## def test_perf(self): -## check_perf() - -try: - c_wchar -except NameError: - pass -else: - class TestWString2: - def test_wchar(self): - c_wchar(u"x") - repr(byref(c_wchar(u"x"))) - c_wchar("x") - - - def X_test_basic_wstrings(self): - cs = c_wstring(u"abcdef") - - # XXX This behaviour is about to change: - # len returns the size of the internal buffer in bytes. - # This includes the terminating NUL character. - self.failUnless(sizeof(cs) == 14) - - # The value property is the string up to the first terminating NUL. - self.failUnless(cs.value == u"abcdef") - self.failUnless(c_wstring(u"abc\000def").value == u"abc") - - self.failUnless(c_wstring(u"abc\000def").value == u"abc") - - # The raw property is the total buffer contents: - self.failUnless(cs.raw == u"abcdef\000") - self.failUnless(c_wstring(u"abc\000def").raw == u"abc\000def\000") - - # We can change the value: - cs.value = u"ab" - self.failUnless(cs.value == u"ab") - self.failUnless(cs.raw == u"ab\000\000\000\000\000") - - py.test.raises(TypeError, c_wstring, "123") - py.test.raises(ValueError, c_wstring, 0) - - def X_test_toolong(self): - cs = c_wstring(u"abcdef") - # Much too long string: - py.test.raises(ValueError, setattr, cs, "value", u"123456789012345") - - # One char too long values: - py.test.raises(ValueError, setattr, cs, "value", u"1234567") +# XXX write real tests for w_char def run_test(rep, msg, func, arg): From arigo at codespeak.net Sun Jan 13 18:52:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 13 Jan 2008 18:52:07 +0100 (CET) Subject: [pypy-svn] r50567 - pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes Message-ID: <20080113175207.3C670168455@codespeak.net> Author: arigo Date: Sun Jan 13 18:52:06 2008 New Revision: 50567 Added: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_extra.py - copied unchanged from r49052, pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py Log: Revive this test from rctypes, which checks how ctypes handles advanced usages of its basic features. From atobe at codespeak.net Sun Jan 13 20:49:58 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Sun, 13 Jan 2008 20:49:58 +0100 (CET) Subject: [pypy-svn] r50568 - pypy/branch/fixed-list-ootype Message-ID: <20080113194958.396B51684D4@codespeak.net> Author: atobe Date: Sun Jan 13 20:49:57 2008 New Revision: 50568 Added: pypy/branch/fixed-list-ootype/ - copied from r50567, pypy/dist/ Log: (cfbolz, atobe): Branch for experimenting with optimising fixed-sized lists in ootype From fijal at codespeak.net Sun Jan 13 21:38:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 21:38:46 +0100 (CET) Subject: [pypy-svn] r50569 - in pypy/branch/applevel-ctypes2/pypy/module/_ffi: . test Message-ID: <20080113203846.8B5C81684C8@codespeak.net> Author: fijal Date: Sun Jan 13 21:38:44 2008 New Revision: 50569 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Log: Use own sizes and alignments instead of relying on struct module Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/array.py Sun Jan 13 21:38:44 2008 @@ -9,8 +9,10 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror -from pypy.module._ffi.structure import native_fmttable, segfault_exception -from pypy.module._ffi.interp_ffi import unwrap_value, wrap_value, _get_type +from pypy.module._ffi.structure import segfault_exception +from pypy.module._ffi.interp_ffi import unwrap_value, wrap_value, _get_type,\ + TYPEMAP +from pypy.rlib.rarithmetic import intmask def push_elem(ll_array, pos, value): TP = lltype.typeOf(value) @@ -27,7 +29,7 @@ def __init__(self, space, of): self.space = space self.of = of - self.itemsize = native_fmttable[of]['size'] + self.itemsize = intmask(TYPEMAP[of].c_size) def descr_call(self, space, w_length_or_iterable): if space.is_true(space.isinstance(w_length_or_iterable, space.w_int)): @@ -80,8 +82,7 @@ def setitem(self, space, num, w_value): if num >= self.length or num < 0: - raise OperationError(space.w_ValueError, space.wrap( - "Setting element %d of array sized %d" % (num, self.length))) + raise OperationError(space.w_IndexError, space.w_None) unwrap_value(space, push_elem, self.ll_array, num, self.shape.of, w_value, None) setitem.unwrap_spec = ['self', ObjSpace, int, W_Root] Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sun Jan 13 21:38:44 2008 @@ -49,6 +49,8 @@ 'd' : ffi_type_double, 's' : ffi_type_pointer, 'P' : ffi_type_pointer, + 'z' : ffi_type_pointer, + 'O' : ffi_type_pointer, } LL_TYPEMAP = { @@ -66,6 +68,8 @@ 'f' : rffi.FLOAT, 'd' : rffi.DOUBLE, 's' : rffi.CCHARP, + 'z' : rffi.CCHARP, + 'O' : rffi.VOIDP, 'P' : rffi.VOIDP, 'v' : lltype.Void, } @@ -194,12 +198,12 @@ else: push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT, space.float_w(w_arg))) - elif tp == "s": + elif tp == "s" or tp =="z": ll_str = rffi.str2charp(space.str_w(w_arg)) if to_free is not None: to_free.append(ll_str) push_func(add_arg, argdesc, ll_str) - elif tp == "P": + elif tp == "P" or tp == "O": # check for NULL ptr if space.is_w(w_arg, space.w_None): push_func(add_arg, argdesc, lltype.nullptr(rffi.VOIDP.TO)) @@ -257,12 +261,12 @@ def wrap_value(space, func, add_arg, argdesc, tp): for c, ll_type in ll_typemap_iter: if tp == c: - if c == 's': + if c == 's' or c == 'z': ptr = func(add_arg, argdesc, rffi.CCHARP) if not ptr: return space.w_None return space.wrap(rffi.charp2str(ptr)) - elif c == 'P': + elif c == 'P' or c == 'O': res = func(add_arg, argdesc, rffi.VOIDP) if not res: return space.w_None Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/structure.py Sun Jan 13 21:38:44 2008 @@ -10,16 +10,9 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror -# XXX we've got the very same info in two places - one is native_fmttable -# the other one is in rlib/libffi, we should refactor it to reuse the same -# logic, I'll not touch it by now, and refactor it later -from pypy.module.struct.nativefmttable import native_fmttable as struct_native_fmttable -from pypy.module._ffi.interp_ffi import wrap_value, unwrap_value, _get_type, TYPEMAP - -native_fmttable = {} -for key, value in struct_native_fmttable.items(): - native_fmttable[key] = {'size': value['size'], - 'alignment': value.get('alignment', value['size'])} +from pypy.module._ffi.interp_ffi import wrap_value, unwrap_value, _get_type,\ + TYPEMAP +from pypy.rlib.rarithmetic import intmask def unpack_fields(space, w_fields): fields_w = space.unpackiterable(w_fields) @@ -35,15 +28,15 @@ return fields def size_and_pos(fields): - size = native_fmttable[fields[0][1]]['size'] + size = intmask(TYPEMAP[fields[0][1]].c_size) pos = [0] for i in range(1, len(fields)): - field_desc = native_fmttable[fields[i][1]] - missing = size % field_desc.get('alignment', 1) + field_desc = TYPEMAP[fields[i][1]] + missing = size % intmask(field_desc.c_alignment) if missing: - size += field_desc['alignment'] - missing + size += intmask(field_desc.c_alignment) - missing pos.append(size) - size += field_desc['size'] + size += intmask(field_desc.c_size) return size, pos Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/test/test__ffi.py Sun Jan 13 21:38:44 2008 @@ -136,6 +136,8 @@ assert get_char('dupa', 1) == 'u' raises(ValueError, "get_char('xxx', 2 ** 17)") raises(ValueError, "get_char('xxx', -1)") + get_char = lib.ptr('get_char', ['z', 'H'], 'c') + assert get_char('dupa', 2) == 'p' def test_returning_str(self): import _ffi From fijal at codespeak.net Sun Jan 13 22:21:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 22:21:20 +0100 (CET) Subject: [pypy-svn] r50570 - pypy/branch/applevel-ctypes2/pypy/module/_ffi Message-ID: <20080113212120.986B11684FA@codespeak.net> Author: fijal Date: Sun Jan 13 22:21:19 2008 New Revision: 50570 Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Log: (arigo, fijal) ctypes expect different type Modified: pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_ffi/interp_ffi.py Sun Jan 13 22:21:19 2008 @@ -232,7 +232,7 @@ elif tp == "c": s = space.str_w(w_arg) if len(s) != 1: - raise OperationError(space.w_ValueError, w( + raise OperationError(space.w_TypeError, w( "Expected string of length one as character")) val = s[0] push_func(add_arg, argdesc, val) From atobe at codespeak.net Sun Jan 13 23:23:03 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Sun, 13 Jan 2008 23:23:03 +0100 (CET) Subject: [pypy-svn] r50571 - in pypy/branch/fixed-list-ootype/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator/cli translator/js translator/jvm translator/oosupport Message-ID: <20080113222303.53C251684FF@codespeak.net> Author: atobe Date: Sun Jan 13 23:23:01 2008 New Revision: 50571 Modified: pypy/branch/fixed-list-ootype/pypy/annotation/builtin.py pypy/branch/fixed-list-ootype/pypy/rpython/llinterp.py pypy/branch/fixed-list-ootype/pypy/rpython/lltypesystem/lloperation.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rlist.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py pypy/branch/fixed-list-ootype/pypy/rpython/test/tool.py pypy/branch/fixed-list-ootype/pypy/translator/cli/constant.py pypy/branch/fixed-list-ootype/pypy/translator/cli/cts.py pypy/branch/fixed-list-ootype/pypy/translator/cli/entrypoint.py pypy/branch/fixed-list-ootype/pypy/translator/cli/oopspec.py pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/node.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py Log: (cfbolz,atobe): Introduced a new ootype for arrays. Made sure fixed-sized lists are rtyped into those arrays. Missing backend support. Modified: pypy/branch/fixed-list-ootype/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/annotation/builtin.py (original) +++ pypy/branch/fixed-list-ootype/pypy/annotation/builtin.py Sun Jan 13 23:23:01 2008 @@ -517,6 +517,10 @@ r = SomeOOInstance(ootype.typeOf(i)) return r +def oonewarray(s_type, length): + assert s_type.is_constant() + return SomeOOInstance(s_type.const) + def null(I_OR_SM): assert I_OR_SM.is_constant() null = ootype.null(I_OR_SM.const) @@ -564,6 +568,7 @@ BUILTIN_ANALYZERS[ootype.instanceof] = instanceof BUILTIN_ANALYZERS[ootype.new] = new +BUILTIN_ANALYZERS[ootype.oonewarray] = oonewarray BUILTIN_ANALYZERS[ootype.null] = null BUILTIN_ANALYZERS[ootype.runtimenew] = runtimenew BUILTIN_ANALYZERS[ootype.classof] = classof Modified: pypy/branch/fixed-list-ootype/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/llinterp.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/llinterp.py Sun Jan 13 23:23:01 2008 @@ -1034,6 +1034,11 @@ def op_new(self, INST): assert isinstance(INST, (ootype.Instance, ootype.BuiltinType)) return ootype.new(INST) + + def op_oonewarray(self, ARRAY, length): + assert isinstance(ARRAY, ootype.Array) + assert isinstance(length, int) + return ootype.oonewarray(ARRAY, length) def op_runtimenew(self, class_): return ootype.runtimenew(class_) Modified: pypy/branch/fixed-list-ootype/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/lltypesystem/lloperation.py Sun Jan 13 23:23:01 2008 @@ -461,6 +461,7 @@ 'new': LLOp(oo=True, canraise=(Exception,)), 'runtimenew': LLOp(oo=True, canraise=(Exception,)), 'oonewcustomdict': LLOp(oo=True, canraise=(Exception,)), + 'oonewarray': LLOp(oo=True, canraise=(Exception,)), 'oosetfield': LLOp(oo=True), 'oogetfield': LLOp(oo=True, sideeffects=False), 'oosend': LLOp(oo=True, canraise=(Exception,)), Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py Sun Jan 13 23:23:01 2008 @@ -453,7 +453,7 @@ ITEMTYPE_T = object() def __init__(self, ITEMTYPE=None): - self._ITEMTYPE = ITEMTYPE + self.ITEM = ITEMTYPE self._null = _null_list(self) if ITEMTYPE is not None: self._init_methods() @@ -464,13 +464,9 @@ # 'ITEMTYPE_T' is used as a placeholder for indicating # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self' - # XXX clean-up later! Rename _ITEMTYPE to ITEM. For now they are - # just synonyms, please use ITEM in new code. - self.ITEM = self._ITEMTYPE - generic_types = { self.SELFTYPE_T: self, - self.ITEMTYPE_T: self._ITEMTYPE, + self.ITEMTYPE_T: self.ITEM, } # the methods are named after the ADT methods of lltypesystem's lists @@ -503,7 +499,7 @@ return True if not isinstance(other, List): return False - if self._ITEMTYPE is None or other._ITEMTYPE is None: + if self.ITEM is None or other.ITEM is None: raise TypeError("Can't compare uninitialized List type.") return BuiltinADTType.__eq__(self, other) @@ -511,28 +507,106 @@ return not (self == other) def __hash__(self): - if self._ITEMTYPE is None: + if self.ITEM is None: raise TypeError("Can't hash uninitialized List type.") return BuiltinADTType.__hash__(self) def __str__(self): return '%s(%s)' % (self.__class__.__name__, - saferecursive(str, "...")(self._ITEMTYPE)) + saferecursive(str, "...")(self.ITEM)) def _get_interp_class(self): return _list def _specialize(self, generic_types): - ITEMTYPE = self._specialize_type(self._ITEMTYPE, generic_types) + ITEMTYPE = self._specialize_type(self.ITEM, generic_types) return self.__class__(ITEMTYPE) def _defl(self): return self._null def _set_itemtype(self, ITEMTYPE): - self._ITEMTYPE = ITEMTYPE + self.ITEM = ITEMTYPE + self._init_methods() + + +class Array(BuiltinADTType): + # placeholders for types + # make sure that each derived class has his own SELFTYPE_T + # placeholder, because we want backends to distinguish that. + + SELFTYPE_T = object() + ITEMTYPE_T = object() + + def __init__(self, ITEMTYPE=None): + self.ITEM = ITEMTYPE + self._null = _null_array(self) + if ITEMTYPE is not None: + self._init_methods() + + def _init_methods(self): + # This defines the abstract list interface that backends will + # have to map to their native list implementations. + # 'ITEMTYPE_T' is used as a placeholder for indicating + # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self' + + generic_types = { + self.SELFTYPE_T: self, + self.ITEMTYPE_T: self.ITEM, + } + + # the methods are named after the ADT methods of lltypesystem's lists + self._GENERIC_METHODS = frozendict({ + # "name": Meth([ARGUMENT1_TYPE, ARGUMENT2_TYPE, ...], RESULT_TYPE) + "ll_length": Meth([], Signed), + "ll_getitem_fast": Meth([Signed], self.ITEMTYPE_T), + "ll_setitem_fast": Meth([Signed, self.ITEMTYPE_T], Void), + }) + + self._setup_methods(generic_types) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, Array): + return False + if self.ITEM is None or other.ITEM is None: + raise TypeError("Can't compare uninitialized List type.") + return BuiltinADTType.__eq__(self, other) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + if self.ITEM is None: + raise TypeError("Can't hash uninitialized List type.") + return BuiltinADTType.__hash__(self) + + def __str__(self): + return '%s(%s)' % (self.__class__.__name__, + saferecursive(str, "...")(self.ITEM)) + + def _get_interp_class(self): + return _array + + def _specialize(self, generic_types): + ITEMTYPE = self._specialize_type(self.ITEM, generic_types) + return self.__class__(ITEMTYPE) + + def _defl(self): + return self._null + + def _example(self): + return oonewarray(self, 1) + + def _set_itemtype(self, ITEMTYPE): + self.ITEM = ITEMTYPE self._init_methods() + def ll_newlist(self, length): + from pypy.rpython.ootypesystem import rlist + return rlist.ll_newarray(self, length) + class Dict(BuiltinADTType): # placeholders for types @@ -1247,6 +1321,8 @@ def __init__(self, WEAK_REFERENCE): self.__dict__["_TYPE"] = WEAK_REFERENCE + + class _list(_builtin_type): def __init__(self, LIST): self._TYPE = LIST @@ -1264,7 +1340,7 @@ # NOT_RPYTHON if len(self._list) < length: diff = length - len(self._list) - self._list += [self._TYPE._ITEMTYPE._defl()] * diff + self._list += [self._TYPE.ITEM._defl()] * diff assert len(self._list) >= length def _ll_resize_le(self, length): @@ -1289,7 +1365,7 @@ def ll_setitem_fast(self, index, item): # NOT_RPYTHON - assert self._TYPE._ITEMTYPE is Void or typeOf(item) == self._TYPE._ITEMTYPE + assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM assert typeOf(index) == Signed assert index >= 0 self._list[index] = item @@ -1299,6 +1375,33 @@ def __init__(self, LIST): self.__dict__["_TYPE"] = LIST +class _array(_builtin_type): + def __init__(self, ARRAY, length): + self._TYPE = ARRAY + self._array = [ARRAY.ITEM._defl()] * length + + def ll_length(self): + # NOT_RPYTHON + return len(self._array) + + def ll_getitem_fast(self, index): + # NOT_RPYTHON + assert typeOf(index) == Signed + assert index >= 0 + return self._array[index] + + def ll_setitem_fast(self, index, item): + # NOT_RPYTHON + assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM + assert typeOf(index) == Signed + assert index >= 0 + self._array[index] = item + +class _null_array(_null_mixin(_array), _array): + + def __init__(self, ARRAY): + self.__dict__["_TYPE"] = ARRAY + class _dict(_builtin_type): def __init__(self, DICT): self._TYPE = DICT @@ -1466,10 +1569,15 @@ return TYPE._get_interp_class()(TYPE) def oonewcustomdict(DICT, ll_eq, ll_hash): + """NOT_RPYTHON""" d = new(DICT) d.ll_set_functions(ll_eq, ll_hash) return d +def oonewarray(ARRAY, length): + """NOT_RPYTHON""" + return _array(ARRAY, length) + def runtimenew(class_): assert isinstance(class_, _class) assert class_ is not nullruntimeclass @@ -1595,7 +1703,7 @@ return LIST._set_itemtype(ITEMTYPE) def hasItemType(LIST): - return LIST._ITEMTYPE is not None + return LIST.ITEM is not None def setDictTypes(DICT, KEYTYPE, VALUETYPE): return DICT._set_types(KEYTYPE, VALUETYPE) Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rbuiltin.py Sun Jan 13 23:23:01 2008 @@ -12,6 +12,13 @@ return hop.genop('new', vlist, resulttype = hop.r_result.lowleveltype) +def rtype_oonewarray(hop): + assert hop.args_s[0].is_constant() + vlist = hop.inputarg(ootype.Void, arg=0) + vlength = hop.inputarg(ootype.Signed, arg=1) + return hop.genop('oonewarray', [vlist, vlength], + resulttype = hop.r_result.lowleveltype) + def rtype_null(hop): assert hop.args_s[0].is_constant() TYPE = hop.args_s[0].const @@ -105,6 +112,7 @@ BUILTIN_TYPER = {} BUILTIN_TYPER[ootype.new] = rtype_new +BUILTIN_TYPER[ootype.oonewarray] = rtype_oonewarray BUILTIN_TYPER[ootype.null] = rtype_null BUILTIN_TYPER[ootype.classof] = rtype_classof BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py Sun Jan 13 23:23:01 2008 @@ -332,7 +332,7 @@ elif func is dum_values: result.ll_setitem_fast(i, it.ll_current_value()) if func is dum_items: - r = ootype.new(LIST._ITEMTYPE) + r = ootype.new(LIST.ITEM) r.item0 = it.ll_current_key() # TODO: do we need casting? r.item1 = it.ll_current_value() result.ll_setitem_fast(i, r) Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rlist.py Sun Jan 13 23:23:01 2008 @@ -1,6 +1,6 @@ from pypy.tool.pairtype import pairtype from pypy.rpython.rlist import AbstractBaseListRepr, AbstractListRepr, \ - AbstractListIteratorRepr, rtype_newlist, rtype_alloc_and_set + AbstractListIteratorRepr, AbstractFixedSizeListRepr, rtype_newlist, rtype_alloc_and_set from pypy.rpython.rmodel import Repr, IntegerRepr from pypy.rpython.rmodel import inputconst, externalvsinternal from pypy.rpython.lltypesystem.lltype import Signed, Void @@ -21,15 +21,12 @@ else: self.external_item_repr, self.item_repr = \ externalvsinternal(rtyper, item_repr) - self.LIST = ootype.List() + self.LIST = self._make_empty_type() self.lowleveltype = self.LIST self.listitem = listitem self.list_cache = {} # setup() needs to be called to finish this initialization - def _externalvsinternal(self, rtyper, item_repr): - return item_repr, item_repr - def _setup_repr(self): if 'item_repr' not in self.__dict__: self.external_item_repr, self.item_repr = \ @@ -37,13 +34,9 @@ if not ootype.hasItemType(self.lowleveltype): ootype.setItemType(self.lowleveltype, self.item_repr.lowleveltype) - def null_const(self): - return self.LIST._null - - def prepare_const(self, n): - result = self.LIST.ll_newlist(n) - return result - + def _externalvsinternal(self, rtyper, item_repr): + return item_repr, item_repr + def send_message(self, hop, message, can_raise=False, v_args=None): if v_args is None: v_args = hop.inputargs(self, *hop.args_r[1:]) @@ -56,9 +49,6 @@ def get_eqfunc(self): return inputconst(Void, self.item_repr.get_ll_eq_function()) - def make_iterator_repr(self): - return ListIteratorRepr(self) - def rtype_hint(self, hop): hints = hop.args_s[-1].const if 'maxlength' in hints: @@ -71,10 +61,26 @@ class ListRepr(AbstractListRepr, BaseListRepr): + def null_const(self): + return self.LIST._null + + def prepare_const(self, n): + result = self.LIST.ll_newlist(n) + return result + + def make_iterator_repr(self): + return ListIteratorRepr(self) - pass + def _make_empty_type(self): + return ootype.List() -FixedSizeListRepr = ListRepr + def _generate_newlist(self, llops, items_v, v_sizehint): + c_list = inputconst(ootype.Void, self.lowleveltype) + v_result = llops.genop("new", [c_list], resulttype=self.lowleveltype) + c_resize = inputconst(ootype.Void, "_ll_resize") + c_length = inputconst(ootype.Signed, len(items_v)) + llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void) + return v_result class __extend__(pairtype(BaseListRepr, BaseListRepr)): @@ -87,11 +93,7 @@ def newlist(llops, r_list, items_v, v_sizehint=None): # XXX do something about v_sizehint - c_list = inputconst(ootype.Void, r_list.lowleveltype) - v_result = llops.genop("new", [c_list], resulttype=r_list.lowleveltype) - c_resize = inputconst(ootype.Void, "_ll_resize") - c_length = inputconst(ootype.Signed, len(items_v)) - llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void) + v_result = r_list._generate_newlist(llops, items_v, v_sizehint) c_setitem = inputconst(ootype.Void, "ll_setitem_fast") for i, v_item in enumerate(items_v): @@ -104,6 +106,31 @@ lst._ll_resize(length) return lst +# Fixed-size list +class FixedSizeListRepr(AbstractFixedSizeListRepr, BaseListRepr): + def compact_repr(self): + return 'FixedSizeListR %s' % (self.item_repr.compact_repr(),) + + def _make_empty_type(self): + return ootype.Array() + + def null_const(self): + return self.LIST._null + + def prepare_const(self, n): + return ll_newarray(self.LIST, n) + + def make_iterator_repr(self): + return ListIteratorRepr(self) + + def _generate_newlist(self, llops, items_v, v_sizehint): + c_array = inputconst(ootype.Void, self.lowleveltype) + c_length = inputconst(ootype.Signed, len(items_v)) + v_result = llops.genop("oonewarray", [c_array, c_length], resulttype=self.lowleveltype) + return v_result + +def ll_newarray(ARRAY, length): + return ootype.oonewarray(ARRAY, length) # ____________________________________________________________ # Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py Sun Jan 13 23:23:01 2008 @@ -170,7 +170,7 @@ return buf.ll_build() def ll_join_chars(length_dummy, lst): - if typeOf(lst)._ITEMTYPE == Char: + if typeOf(lst).ITEM == Char: buf = ootype.new(ootype.StringBuilder) else: buf = ootype.new(ootype.UnicodeBuilder) @@ -183,7 +183,7 @@ return buf.ll_build() def ll_join_strs(length_dummy, lst): - if typeOf(lst)._ITEMTYPE == ootype.String: + if typeOf(lst).ITEM == ootype.String: buf = ootype.new(ootype.StringBuilder) else: buf = ootype.new(ootype.UnicodeBuilder) Modified: pypy/branch/fixed-list-ootype/pypy/rpython/test/tool.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/test/tool.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/test/tool.py Sun Jan 13 23:23:01 2008 @@ -107,7 +107,9 @@ return OOSupport.to_runicode(u) def ll_to_list(self, l): - return l._list[:] + if hasattr(l, '_list'): + return l._list[:] + return l._array[:] def ll_unpack_tuple(self, t, length): return tuple([getattr(t, 'item%d' % i) for i in range(length)]) Modified: pypy/branch/fixed-list-ootype/pypy/translator/cli/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/cli/constant.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/cli/constant.py Sun Jan 13 23:23:01 2008 @@ -351,7 +351,7 @@ def create_pointer(self, gen): self.db.const_count.inc('List') - self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE) + self.db.const_count.inc('List', self.value._TYPE.ITEM) self.db.const_count.inc('List', len(self.value._list)) super(CLIListConst, self).create_pointer(gen) Modified: pypy/branch/fixed-list-ootype/pypy/translator/cli/cts.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/cli/cts.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/cli/cts.py Sun Jan 13 23:23:01 2008 @@ -242,7 +242,7 @@ delegate = self.db.record_delegate(t) return CliClassType(None, delegate) elif isinstance(t, ootype.List): - item_type = self.lltype_to_cts(t._ITEMTYPE) + item_type = self.lltype_to_cts(t.ITEM) if item_type == types.void: # special case: List of Void return types.list_of_void return types.list.specialize(item_type) Modified: pypy/branch/fixed-list-ootype/pypy/translator/cli/entrypoint.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/cli/entrypoint.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/cli/entrypoint.py Sun Jan 13 23:23:01 2008 @@ -9,7 +9,7 @@ ARG0 = graph.getargs()[0].concretetype except IndexError: ARG0 = None - if isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String: + if isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String: return StandaloneEntryPoint(graph) else: return TestEntryPoint(graph) @@ -45,7 +45,7 @@ ARG0 = self.graph.getargs()[0].concretetype except IndexError: ARG0 = None - assert isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String,\ + assert isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String,\ 'Wrong entry point signature: List(String) expected' ilasm.begin_function('main', [('string[]', 'argv')], 'void', True, 'static') Modified: pypy/branch/fixed-list-ootype/pypy/translator/cli/oopspec.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/cli/oopspec.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/cli/oopspec.py Sun Jan 13 23:23:01 2008 @@ -33,7 +33,7 @@ try: # special case: when having List of Void, look at the concrete # methods, not the generic ones - if isinstance(TYPE, ootype.List) and TYPE._ITEMTYPE is ootype.Void: + if isinstance(TYPE, ootype.List) and TYPE.ITEM is ootype.Void: return TYPE._METHODS[name] else: return TYPE._GENERIC_METHODS[name] Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py Sun Jan 13 23:23:01 2008 @@ -135,7 +135,7 @@ ## elif isinstance(t, ootype.StaticMethod): ## return 'void' # TODO: is it correct to ignore StaticMethod? ## elif isinstance(t, ootype.List): -## item_type = self.lltype_to_cts(t._ITEMTYPE) +## item_type = self.lltype_to_cts(t.ITEM) ## return self.__class(PYPY_LIST % item_type, include_class) ## elif isinstance(t, ootype.Dict): ## key_type = self.lltype_to_cts(t._KEYTYPE) Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/node.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/node.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/node.py Sun Jan 13 23:23:01 2008 @@ -141,7 +141,7 @@ # python method expects arg0 = self.graph.getargs()[0] assert isinstance(arg0.concretetype, ootype.List), str(arg0.concretetype) - assert arg0.concretetype._ITEMTYPE is ootype.String + assert arg0.concretetype.ITEM is ootype.String gen.load_jvm_var(jStringArray, 0) gen.emit(jvmgen.PYPYARRAYTOLIST) Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py Sun Jan 13 23:23:01 2008 @@ -260,7 +260,7 @@ if hasattr(self.OOTYPE, 'SELFTYPE_T'): self.generics[self.OOTYPE.SELFTYPE_T] = (self.OOTYPE,self.OOTYPE) - for pname,pval in (('ITEMTYPE_T', '_ITEMTYPE'), + for pname,pval in (('ITEMTYPE_T', 'ITEM'), ('KEYTYPE_T', '_KEYTYPE'), ('VALUETYPE_T', '_VALUETYPE')): if hasattr(self.OOTYPE, pname): Modified: pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py Sun Jan 13 23:23:01 2008 @@ -578,7 +578,7 @@ if not self.value: return for item in self.value._list: - self._record_const_if_complex(self.value._TYPE._ITEMTYPE, item) + self._record_const_if_complex(self.value._TYPE.ITEM, item) def create_pointer(self, gen): assert not self.is_null() @@ -603,7 +603,7 @@ can be overloaded by the backend if your conditions are wider. The default is not to initialize if the list is a list of Void. """ - return self.value._TYPE._ITEMTYPE is ootype.Void + return self.value._TYPE.ITEM is ootype.Void try: return self.value._list == [0] * len(self.value._list) except: @@ -612,7 +612,7 @@ def initialize_data(self, constgen, gen): assert not self.is_null() SELFTYPE = self.value._TYPE - ITEMTYPE = self.value._TYPE._ITEMTYPE + ITEM = self.value._TYPE.ITEM # check for special cases and avoid initialization if self._do_not_initialize(): @@ -623,8 +623,8 @@ constgen._consider_split_current_function(gen) gen.dup(SELFTYPE) push_constant(self.db, ootype.Signed, idx, gen) - push_constant(self.db, ITEMTYPE, item, gen) - gen.prepare_generic_argument(ITEMTYPE) + push_constant(self.db, ITEM, item, gen) + gen.prepare_generic_argument(ITEM) gen.call_method(SELFTYPE, 'll_setitem_fast') # ______________________________________________________________________ From fijal at codespeak.net Sun Jan 13 23:26:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 13 Jan 2008 23:26:41 +0100 (CET) Subject: [pypy-svn] r50572 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080113222641.682FE1684FF@codespeak.net> Author: fijal Date: Sun Jan 13 23:26:40 2008 New Revision: 50572 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Log: (arigo, fijal) ARGH. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Sun Jan 13 23:26:40 2008 @@ -1,9 +1,9 @@ import _ffi -from _ctypes.basics import _CData, cdata_from_address +from _ctypes.basics import _CData, cdata_from_address, _CDataMeta -class ArrayMeta(type): +class ArrayMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) res._ffiletter = 'P' @@ -19,14 +19,23 @@ i += 1 return "".join(res) def setvalue(self, val): - for i in range(min(len(val), self._length_)): + # we don't want to have buffers here + import ctypes + if len(val) > self._length_: + raise ValueError("%s too long" % (val,)) + for i in range(len(val)): self[i] = val[i] - self[len(val)] = '\x00' + if len(val) < self._length_: + self[len(val)] = '\x00' res.value = property(getvalue, setvalue) def getraw(self): return "".join([self[i] for i in range(self._length_)]) - res.raw = property(getraw) + + def setraw(self, buffer): + for i in range(len(buffer)): + self[i] = buffer[i] + res.raw = property(getraw, setraw) else: res._ffiarray = None return res @@ -65,12 +74,11 @@ return "".join([self[i] for i in range(start, stop)]) def __setitem__(self, item, value): + from ctypes import _SimpleCData if isinstance(item, slice): self._slice_setitem(item, value) - # XXX - from ctypes import _SimpleCData - if isinstance(value, _SimpleCData): - value = value.value + return + value = self._type_.from_param(value).value item = self._fix_item(item) if self._type_._ffiletter == 'c' and len(value) > 1: raise TypeError("Expected strings of length 1") Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Sun Jan 13 23:26:40 2008 @@ -1,20 +1,28 @@ import _ffi +class _CDataMeta(type): + def from_param(self, value): + if isinstance(value, self): + return value + raise TypeError("Wrong type") + class _CData(object): """ The most basic object for all ctypes types """ + __metaclass__ = _CDataMeta + def __ctypes_from_outparam__(self): return self -class CArgObject(object): - def __init__(self, letter, raw_value, _type): - self.ffiletter = letter - self.raw_value = raw_value - self._type = _type +#class CArgObject(object): +# def __init__(self, letter, raw_value, _type): +# self.ffiletter = letter +# self._array = raw_value +# self._type = _type - def __repr__(self): - return "" % (self.ffiletter, self.raw_value) +# def __repr__(self): +# return "" % (self.ffiletter, self._array[0]) TP_TO_FFITP = { # XXX this should die; interp_ffi should just accept them @@ -22,7 +30,6 @@ 'z': 's', } - def sizeof(tp): ffitp = tp._type_ return _ffi.sizeof(TP_TO_FFITP.get(ffitp, ffitp)) @@ -35,7 +42,7 @@ from ctypes import pointer, _SimpleCData if not isinstance(cdata, _SimpleCData): raise TypeError("expected CData instance") - return pointer(cdata)._as_ffi() + return pointer(cdata) def cdata_from_address(self, address): instance = self.__new__(self) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Sun Jan 13 23:26:40 2008 @@ -1,68 +1,59 @@ import _ffi -from _ctypes.basics import CArgObject -class CFuncPtrType(type): +from _ctypes.basics import _CData, _CDataMeta + +class CFuncPtrType(_CDataMeta): # XXX write down here defaults and such things pass -class CFuncPtr(object): +class CFuncPtr(_CData): __metaclass__ = CFuncPtrType - argtypes = None - _argtypes = None - restype = None - _restype = None - def __init__(self, stuff): - if isinstance(stuff, tuple): - name, dll = stuff - self.name = name - self.dll = dll - self._funcptr = None + + _argtypes_ = None + _restype_ = None + + def _getargtypes(self): + return self._argtypes_ + def _setargtypes(self, argtypes): + self._argtypes_ = argtypes + argtypes = property(_getargtypes, _setargtypes) + + def _getrestype(self): + return self._restype_ + def _setrestype(self, restype): + self._restype_ = restype + restype = property(_getrestype, _setrestype) + + def __init__(self, address_or_name_and_dll): + if isinstance(address_or_name_and_dll, tuple): + self.name, self.dll = address_or_name_and_dll else: self.name = None - self.dll = None def __call__(self, *args): - import ctypes - if self.restype is None: - # XXX point to default instead - self.restype = ctypes.c_int - if self.argtypes is not None: - if len(args) != len(self.argtypes): - raise TypeError("%s takes %s arguments, given %s" % - (self.name, len(self.argtypes), len(args))) - funcptr = self._getfuncptr(args) - argvalues = [tp.from_param(arg).raw_value for tp, arg in zip(self._argtypes, args)] - res = funcptr(*argvalues) - if issubclass(self.restype, ctypes._SimpleCData): - return res - else: - # XXX pointers - return self.restype(res) + if self.name is None: + raise NotImplementedError("Creation of function pointer to pure addresses is not implemented") + argtypes = self._argtypes_ + if argtypes is None: + argtypes = self._guess_argtypes(args) + restype = self._restype_ + funcptr = self._getfuncptr(argtypes, restype) + res = funcptr(*self._wrap_args(argtypes, args)) + if restype is not None: + return restype(res).__ctypes_from_outparam__() - def _getfuncptr(self, args): - if self._funcptr is not None: - if (self.argtypes is self._argtypes - and self.restype is self._restype): - return self._funcptr - if self.argtypes is None: - argtypes = self._guess_magic_args(args) - else: - argtypes = self.argtypes - argtps = [argtype._ffiletter for argtype in argtypes] - restp = self.restype._ffiletter - self._funcptr = funcptr = self.dll._handle.ptr(self.name, argtps, restp) - self._argtypes = argtypes - self._restype = self.restype - return funcptr + def _getfuncptr(self, argtypes, restype): + argletters = [arg._ffiletter for arg in argtypes] + return self.dll._handle.ptr(self.name, argletters, restype._ffiletter) - def _guess_magic_args(self, args): - import _ctypes + def _guess_argtypes(self, args): + from _ctypes import _CData res = [] for arg in args: - if isinstance(arg, _ctypes._CData): - res.append(type(arg)) - elif isinstance(arg, CArgObject): - res.append(arg._type) - else: - raise TypeError("Cannot convert %s" % arg) + assert isinstance(arg, _CData) + res.append(type(arg)) return res + + def _wrap_args(self, argtypes, args): + return [argtype.from_param(arg)._array[0] for argtype, arg in + zip(argtypes, args)] Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Sun Jan 13 23:26:40 2008 @@ -1,10 +1,10 @@ import _ffi -from _ctypes.basics import _CData, CArgObject, cdata_from_address +from _ctypes.basics import _CData, _CDataMeta, cdata_from_address DEFAULT_VALUE = object() -class PointerType(type): +class PointerType(_CDataMeta): def __new__(self, name, cls, typedict): d = dict( size = _ffi.sizeof('P'), @@ -31,13 +31,6 @@ from_address = cdata_from_address - def from_param(self, param): - # XXX think deeper about that - if isinstance(param, CArgObject): - return param - else: - return self.from_address(param._array.buffer)._as_ffi() - class _Pointer(_CData): __metaclass__ = PointerType @@ -55,10 +48,6 @@ else: self._array[0] = value._array - def _as_ffi(self): - # XXX performance - return CArgObject('P', self._type_.from_address(self._array[0])._array, type(self)) - def __getitem__(self, item): assert item == 0 return self._type_.from_address(self._array[0]).__ctypes_from_outparam__() Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Sun Jan 13 23:26:40 2008 @@ -2,7 +2,7 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" -from _ctypes.basics import _CData, CArgObject, cdata_from_address, TP_TO_FFITP +from _ctypes.basics import _CData, _CDataMeta, cdata_from_address, TP_TO_FFITP from _ctypes.array import create_array_type class NULL(object): @@ -31,7 +31,7 @@ DEFAULT_VALUE = object() -class SimpleType(type): +class SimpleType(_CDataMeta): def __new__(self, name, bases, dct): tp = dct['_type_'] if (not isinstance(tp, str) or @@ -52,16 +52,15 @@ return create_array_type(self, other) def from_param(self, value): - return self(value)._as_ffi() + if not isinstance(value, _CData): + return self(value) + return super(SimpleType, self).from_param(value) class _SimpleCData(_CData): __metaclass__ = SimpleType _type_ = 'i' def __init__(self, value=DEFAULT_VALUE): - #if address is not DEFAULT_VALUE: - # self._array = ffiarray.fromaddress(address, 1) - #else: self._array = self._ffiarray(1) if value is not DEFAULT_VALUE: self._array[0] = value @@ -70,14 +69,15 @@ return self._array[0] def _setvalue(self, value): - self._array[0] = value + # XXX + if isinstance(value, _SimpleCData): + self._array[0] = value.value + else: + self._array[0] = value value = property(_getvalue, _setvalue) def __ctypes_from_outparam__(self): return self._array[0] - def _as_ffi(self): - return CArgObject(self._type_, self.value, type(self)) - def __repr__(self): return "%s(%s)" % (type(self).__name__, self.value) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Sun Jan 13 23:26:40 2008 @@ -1,7 +1,7 @@ -from _ctypes.basics import _CData +from _ctypes.basics import _CData, _CDataMeta -class StructureMeta(type): +class StructureMeta(_CDataMeta): def __new__(self, name, cls, typedict): return type.__new__(self, name, cls, typedict) From cfbolz at codespeak.net Mon Jan 14 00:33:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 00:33:17 +0100 (CET) Subject: [pypy-svn] r50573 - in pypy/branch/fixed-list-ootype/pypy/translator: js oosupport Message-ID: <20080113233317.2E3C916850E@codespeak.net> Author: cfbolz Date: Mon Jan 14 00:33:16 2008 New Revision: 50573 Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/asmgen.py pypy/branch/fixed-list-ootype/pypy/translator/js/database.py pypy/branch/fixed-list-ootype/pypy/translator/js/function.py pypy/branch/fixed-list-ootype/pypy/translator/js/jsbuiltin.py pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py pypy/branch/fixed-list-ootype/pypy/translator/js/opcodes.py pypy/branch/fixed-list-ootype/pypy/translator/oosupport/metavm.py Log: add array support to the js backend Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/asmgen.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/asmgen.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/asmgen.py Mon Jan 14 00:33:16 2008 @@ -219,6 +219,9 @@ def runtimenew(self): self.right_hand.append("new %s()" % self.right_hand.pop()) + def oonewarray(self, obj, length): + self.right_hand.append("new %s(%s)" % (obj, length)) + def load_self(self): self.right_hand.append("this") Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/database.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/database.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/database.py Mon Jan 14 00:33:16 2008 @@ -227,6 +227,8 @@ return InstanceConst(db, const, static_type) elif isinstance(const, ootype._list): return ListConst(db, const) + elif isinstance(const, ootype._array): + return ListConst(db, const) elif isinstance(const, ootype._record): return RecordConst(db, const) elif isinstance(const, ootype._string): @@ -355,6 +357,13 @@ class ListConst(AbstractConst): + def _get_list(self): + if isinstance(self.const, ootype._list): + return self.const._list + else: + return self.const._array + + def get_name(self): return "const_list" @@ -368,7 +377,7 @@ if not self.const: return - for i in self.const._list: + for i in self._get_list(): name = self.db.record_const(i, None, 'const') if name is not None: self.depends.add(name) @@ -381,9 +390,10 @@ if not self.const: return - for i in xrange(len(self.const._list)): + l = self._get_list() + for i in xrange(len(l)): ilasm.load_str("%s.%s"%(const_var.name, name)) - el = self.const._list[i] + el = l[i] self.db.load_const(typeOf(el), el, ilasm) self.db.load_const(typeOf(i), i, ilasm) ilasm.list_setitem() Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/function.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/function.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/function.py Mon Jan 14 00:33:16 2008 @@ -73,6 +73,9 @@ def new(self, obj): self.ilasm.new(self.cts.obj_name(obj)) + def oonewarray(self, obj, length): + self.ilasm.oonewarray(self.cts.obj_name(obj), length) + def set_field(self, obj, name): self.ilasm.set_field(obj, name) #self.ilasm.set_field(self.field_name(obj,name)) Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/jsbuiltin.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/jsbuiltin.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/jsbuiltin.py Mon Jan 14 00:33:16 2008 @@ -59,6 +59,11 @@ '_ll_resize_le' : list_resize, 'll_length' : _GetPredefinedField('length'), }, + ootype.Array: { + 'll_setitem_fast' : ListSetitem, + 'll_getitem_fast' : ListGetitem, + 'll_length' : _GetPredefinedField('length'), + }, ootype.Dict: { 'll_get' : ListGetitem, 'll_set' : ListSetitem, Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/jts.py Mon Jan 14 00:33:16 2008 @@ -43,6 +43,8 @@ return self.escape_name(t._name) elif isinstance(t, ootype.List): return "Array" + elif isinstance(t, ootype.Array): + return "Array" elif isinstance(t, lltype.Primitive): return "var" elif isinstance(t, ootype.Record): Modified: pypy/branch/fixed-list-ootype/pypy/translator/js/opcodes.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/js/opcodes.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/js/opcodes.py Mon Jan 14 00:33:16 2008 @@ -2,7 +2,8 @@ """ from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult,\ - InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive + InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive,\ + OONewArray from pypy.translator.oosupport.metavm import _GetFieldDispatcher, _SetFieldDispatcher, \ _CallDispatcher, _MethodDispatcher, SetField @@ -119,6 +120,7 @@ 'indirect_call' : [IndirectCall], 'same_as' : CopyName, 'new' : [New], + 'oonewarray' : [OONewArray], 'runtimenew' : [RuntimeNew], 'instanceof' : [IsInstance], #'subclassof' : [IsSubclassOf], Modified: pypy/branch/fixed-list-ootype/pypy/translator/oosupport/metavm.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/oosupport/metavm.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/oosupport/metavm.py Mon Jan 14 00:33:16 2008 @@ -214,6 +214,13 @@ Stack: ... -> newobj, ... """ raise NotImplementedError + def oonewarray(self, TYPE, length): + """ Creates a new array of the given type with the given length. + + Stack: ... -> newobj, ... """ + raise NotImplementedError + + def push_null(self, TYPE): """ Push a NULL value onto the stack (the NULL value represents a pointer to an instance of OOType TYPE, if it matters to you). """ @@ -413,6 +420,14 @@ return generator.new(op.args[0].value) + +class _OONewArray(MicroInstruction): + def render(self, generator, op): + if op.args[0].value is ootype.Void: + return + generator.oonewarray(op.args[0].value, op.args[1]) + + class BranchUnconditionally(MicroInstruction): def __init__(self, label): self.label = label @@ -497,6 +512,7 @@ generator.isinstance(class_name) New = _New() +OONewArray = _OONewArray() PushAllArgs = _PushAllArgs() StoreResult = _StoreResult() From arigo at codespeak.net Mon Jan 14 10:27:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 10:27:39 +0100 (CET) Subject: [pypy-svn] r50574 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080114092739.A655616853A@codespeak.net> Author: arigo Date: Mon Jan 14 10:27:37 2008 New Revision: 50574 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py Log: Adjust the default nursery size, based on preliminary benchmarks. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Mon Jan 14 10:27:37 2008 @@ -395,9 +395,9 @@ def best_nursery_size_for_L2cache(L2cache): if DEBUG_PRINT: llop.debug_print(lltype.Void, "CCC L2cache =", L2cache) - # Heuristically, the best nursery size to choose is almost as - # big as the L2 cache. XXX adjust - return L2cache // 8 * 7 + # Heuristically, the best nursery size to choose is about half + # of the L2 cache. XXX benchmark some more. + return L2cache // 2 if sys.platform == 'linux2': From cfbolz at codespeak.net Mon Jan 14 10:29:32 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 10:29:32 +0100 (CET) Subject: [pypy-svn] r50575 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080114092932.16AE6168536@codespeak.net> Author: cfbolz Date: Mon Jan 14 10:29:31 2008 New Revision: 50575 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: (all): planning for today Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Mon Jan 14 10:29:31 2008 @@ -5,18 +5,24 @@ - try getting debug information in the Java class files (Carl Friedrich, Paul) DONE - - benchmark the size of the young nursery for generational GC (Olivier, most - of Armin) + - benchmark the size of the young nursery for generational GC (Olivier, + most of Armin) IN-PROGRESS, the result is that picking half the L2 cache + size for the nursery sounds good - look at the RPython microbenchmarks for Java (Toby, Armin around) + DONE, fixed sized-lists are slow - - work on CTypes + - work on CTypes (Maciek, Armin) general non-progress - think about summarizing test outcomes - JVM integration (probably only when Anto is here) - look at the CLI integration on the clr-module-improvements/ branch and - maybe improve/merge it? (Carl Friedrich, Paul) + maybe improve/merge it? SOME PROGRESS, we gave up because python.net wasn't + working correctly (Anto, Paul) + + - implement fixed-size lists as arrays in the ootypesystem (Carl Friedrich, + Toby) IN PROGRESS, backend support missing From arigo at codespeak.net Mon Jan 14 11:20:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 11:20:53 +0100 (CET) Subject: [pypy-svn] r50578 - in pypy/branch/applevel-ctypes2/pypy/rlib: . test Message-ID: <20080114102053.C2186168528@codespeak.net> Author: arigo Date: Mon Jan 14 11:20:51 2008 New Revision: 50578 Modified: pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py Log: (fijal, arigo) Refactor libffi.py to add a lower-level interface: RawFuncPtr. Modified: pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py Mon Jan 14 11:20:51 2008 @@ -170,33 +170,60 @@ def check_pointer_type(TP): pass -class FuncPtr(object): +class AbstractFuncPtr(object): + ll_cif = lltype.nullptr(FFI_CIFP.TO) + ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) + def __init__(self, name, argtypes, restype, funcsym): - # initialize each one of pointers with null - TP = rffi.CArray(rffi.VOIDP) - self.ll_args = lltype.nullptr(TP) - self.ll_cif = lltype.nullptr(FFI_CIFP.TO) - self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) - self.ll_result = lltype.nullptr(rffi.VOIDP.TO) self.name = name self.argtypes = argtypes self.restype = restype self.funcsym = funcsym argnum = len(argtypes) self.argnum = argnum - self.pushed_args = 0 - self.ll_args = lltype.malloc(TP, argnum, flavor='raw') - self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw') self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw') for i in range(argnum): self.ll_argtypes[i] = argtypes[i] # XXX why cast to FFI_TYPE_PP is needed? ll2ctypes bug? + self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw') res = c_ffi_prep_cif(self.ll_cif, FFI_DEFAULT_ABI, rffi.cast(rffi.UINT, argnum), restype, rffi.cast(FFI_TYPE_PP, self.ll_argtypes)) if not res == FFI_OK: raise OSError(-1, "Wrong typedef") - for i in range(argnum): + + def __del__(self): + if self.ll_cif: + lltype.free(self.ll_cif, flavor='raw') + if self.ll_argtypes: + lltype.free(self.ll_argtypes, flavor='raw') + + +class RawFuncPtr(AbstractFuncPtr): + + def call(self, args_ll, ll_result): + if len(args_ll) != self.argnum: + raise ValueError("wrong number of arguments in call to %s(): " + "%d instead of %d" % (self.name, + len(args_ll), + self.argnum)) + ll_args = lltype.malloc(rffi.VOIDPP.TO, len(args_ll), flavor='raw') + for i in range(len(args_ll)): + ll_args[i] = args_ll[i] + c_ffi_call(self.ll_cif, self.funcsym, ll_result, ll_args) + lltype.free(ll_args, flavor='raw') + + +class FuncPtr(AbstractFuncPtr): + ll_args = lltype.nullptr(rffi.VOIDPP.TO) + ll_result = lltype.nullptr(rffi.VOIDP.TO) + + def __init__(self, name, argtypes, restype, funcsym): + # initialize each one of pointers with null + AbstractFuncPtr.__init__(self, name, argtypes, restype, funcsym) + self.pushed_args = 0 + self.ll_args = lltype.malloc(rffi.VOIDPP.TO, self.argnum, flavor='raw') + for i in range(self.argnum): # space for each argument self.ll_args[i] = lltype.malloc(rffi.VOIDP.TO, intmask(argtypes[i].c_size), @@ -257,10 +284,7 @@ lltype.free(self.ll_args, flavor='raw') if self.ll_result: lltype.free(self.ll_result, flavor='raw') - if self.ll_cif: - lltype.free(self.ll_cif, flavor='raw') - if self.ll_argtypes: - lltype.free(self.ll_argtypes, flavor='raw') + AbstractFuncPtr.__del__(self) class CDLL: def __init__(self, libname): @@ -280,3 +304,7 @@ # structures! return FuncPtr(name, argtypes, restype, dlsym(self.lib, name)) + def getrawpointer(self, name, argtypes, restype): + # these arguments are already casted to proper ffi + # structures! + return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name)) Modified: pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py Mon Jan 14 11:20:51 2008 @@ -121,4 +121,19 @@ res = fn(2.0, 4.0) assert res == 16.0 - + def test_rawfuncptr(self): + libm = CDLL('libm.so') + pow = libm.getrawpointer('pow', [ffi_type_double, ffi_type_double], + ffi_type_double) + buffer = lltype.malloc(rffi.DOUBLEP.TO, 3, flavor='raw') + buffer[0] = 2.0 + buffer[1] = 3.0 + buffer[2] = 43.5 + pow.call([rffi.cast(rffi.VOIDP, buffer), + rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))], + rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 2))) + assert buffer[2] == 8.0 + lltype.free(buffer, flavor='raw') + del pow + del libm + assert len(ALLOCATED) == 1 # ffi_type_double get allocated From arigo at codespeak.net Mon Jan 14 11:24:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 11:24:43 +0100 (CET) Subject: [pypy-svn] r50579 - in pypy/branch/applevel-ctypes2/pypy: config doc/config module/_rawffi Message-ID: <20080114102443.C1BA0168518@codespeak.net> Author: arigo Date: Mon Jan 14 11:24:43 2008 New Revision: 50579 Added: pypy/branch/applevel-ctypes2/pypy/doc/config/objspace.usemodules._rawffi.txt (contents, props changed) pypy/branch/applevel-ctypes2/pypy/module/_rawffi/ - copied from r50577, pypy/branch/applevel-ctypes2/pypy/module/_ffi/ Modified: pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py Log: (fijal, arigo) Copy _ffi to _rawffi. See doc/config. Modified: pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py (original) +++ pypy/branch/applevel-ctypes2/pypy/config/pypyoption.py Mon Jan 14 11:24:43 2008 @@ -35,6 +35,7 @@ module_dependencies = {'_ffi': [("objspace.usemodules.struct", True)], + '_rawffi': [("objspace.usemodules.struct", True)], } if os.name == "posix": module_dependencies['rctime'] = [("objspace.usemodules.select", True),] Added: pypy/branch/applevel-ctypes2/pypy/doc/config/objspace.usemodules._rawffi.txt ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/doc/config/objspace.usemodules._rawffi.txt Mon Jan 14 11:24:43 2008 @@ -0,0 +1,3 @@ +An experimental module providing very low-level interface to +C-level libraries, for use when implementing ctypes, not +indended for a direct use at all. \ No newline at end of file From arigo at codespeak.net Mon Jan 14 11:27:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 11:27:57 +0100 (CET) Subject: [pypy-svn] r50580 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080114102757.470571684F8@codespeak.net> Author: arigo Date: Mon Jan 14 11:27:57 2008 New Revision: 50580 Added: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py - copied, changed from r50579, pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py - copied, changed from r50579, pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__ffi.py Removed: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_ffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__ffi.py Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Log: Rename files and fix imports. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py Mon Jan 14 11:27:57 2008 @@ -3,22 +3,22 @@ """ from pypy.interpreter.mixedmodule import MixedModule -from pypy.module._ffi.interp_ffi import W_CDLL +from pypy.module._rawffi.interp_rawffi import W_CDLL from pypy.rpython.lltypesystem import lltype, rffi class Module(MixedModule): - applevelname = '_ffi' + applevelname = '_rawffi' interpleveldefs = { - 'CDLL' : 'interp_ffi.W_CDLL', - 'FuncPtr' : 'interp_ffi.W_FuncPtr', + 'CDLL' : 'interp_rawffi.W_CDLL', + 'FuncPtr' : 'interp_rawffi.W_FuncPtr', 'Structure' : 'structure.W_Structure', 'StructureInstance' : 'structure.W_StructureInstance', 'Array' : 'array.W_Array', 'ArrayInstance' : 'array.W_ArrayInstance', - '_get_type' : 'interp_ffi._w_get_type', - 'sizeof' : 'interp_ffi.sizeof', - 'alignment' : 'interp_ffi.alignment', + '_get_type' : 'interp_rawffi._w_get_type', + 'sizeof' : 'interp_rawffi.sizeof', + 'alignment' : 'interp_rawffi.alignment', #'CallbackPtr' : 'callback.W_CallbackPtr', } Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Mon Jan 14 11:27:57 2008 @@ -9,8 +9,8 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror -from pypy.module._ffi.structure import segfault_exception -from pypy.module._ffi.interp_ffi import unwrap_value, wrap_value, _get_type,\ +from pypy.module._rawffi.structure import segfault_exception +from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value, _get_type,\ TYPEMAP from pypy.rlib.rarithmetic import intmask Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py Mon Jan 14 11:27:57 2008 @@ -4,7 +4,7 @@ from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi -from pypy.module._ffi.structure import unpack_fields +from pypy.module._rawffi.structure import unpack_fields def stuff(a, b): print "comparing" Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Mon Jan 14 11:27:57 2008 @@ -10,7 +10,7 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror -from pypy.module._ffi.interp_ffi import wrap_value, unwrap_value, _get_type,\ +from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value, _get_type,\ TYPEMAP from pypy.rlib.rarithmetic import intmask @@ -97,7 +97,7 @@ cast_pos._annspecialcase_ = 'specialize:arg(2)' def segfault_exception(space, reason): - w_mod = space.getbuiltinmodule("_ffi") + w_mod = space.getbuiltinmodule("_rawffi") w_exception = space.getattr(w_mod, space.wrap("SegfaultException")) return OperationError(w_exception, space.wrap(reason)) Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Mon Jan 14 11:27:57 2008 @@ -1,5 +1,5 @@ -from pypy.module._ffi.structure import size_and_pos +from pypy.module._rawffi.structure import size_and_pos sizeof = lambda x : size_and_pos(x)[0] From arigo at codespeak.net Mon Jan 14 13:04:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 13:04:21 +0100 (CET) Subject: [pypy-svn] r50581 - pypy/branch/applevel-ctypes2/pypy/rlib/test Message-ID: <20080114120421.B795816855B@codespeak.net> Author: arigo Date: Mon Jan 14 13:04:20 2008 New Revision: 50581 Modified: pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py Log: Fix the checks for ALLOCATED. Modified: pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py Mon Jan 14 13:04:20 2008 @@ -14,6 +14,11 @@ def setup_module(mod): if not sys.platform.startswith('linux'): py.test.skip("Fragile tests, linux only by now") + for name in type_names: + # XXX force this to be seen by ll2ctypes + # so that ALLOCATED.clear() clears it + ffistruct = globals()[name] + rffi.cast(rffi.VOIDP, ffistruct) class TestDLOperations: def setup_method(self, meth): @@ -37,7 +42,7 @@ py.test.raises(KeyError, lib.getpointer, 'xxxxxxxxxxxxxxx', [], ffi_type_void) del ptr del lib - assert len(ALLOCATED) == 1 + assert not ALLOCATED def test_library_func_call(self): lib = self.get_libc() @@ -52,7 +57,7 @@ # not very hard check, but something :] del ptr del lib - assert len(ALLOCATED) == 1 # ffi_type_sint get allocated + assert not ALLOCATED def test_call_args(self): libm = CDLL('libm.so') @@ -68,7 +73,7 @@ assert res == 27.0 del pow del libm - assert len(ALLOCATED) == 1 + assert not ALLOCATED def test_wrong_args(self): libc = CDLL('libc.so.6') @@ -101,7 +106,8 @@ assert l_t[0] == t1 lltype.free(l_t, flavor='raw') del ctime - assert len(ALLOCATED) == 1 + del libc + assert not ALLOCATED def test_compile(self): import py @@ -136,4 +142,4 @@ lltype.free(buffer, flavor='raw') del pow del libm - assert len(ALLOCATED) == 1 # ffi_type_double get allocated + assert not ALLOCATED From arigo at codespeak.net Mon Jan 14 13:04:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 13:04:55 +0100 (CET) Subject: [pypy-svn] r50582 - pypy/branch/applevel-ctypes2/pypy/rlib Message-ID: <20080114120455.96AE516855B@codespeak.net> Author: arigo Date: Mon Jan 14 13:04:55 2008 New Revision: 50582 Modified: pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py Log: (fijal, arigo) Assert instead of ValueError. Modified: pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py Mon Jan 14 13:04:55 2008 @@ -180,7 +180,6 @@ self.restype = restype self.funcsym = funcsym argnum = len(argtypes) - self.argnum = argnum self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw') for i in range(argnum): self.ll_argtypes[i] = argtypes[i] @@ -202,11 +201,9 @@ class RawFuncPtr(AbstractFuncPtr): def call(self, args_ll, ll_result): - if len(args_ll) != self.argnum: - raise ValueError("wrong number of arguments in call to %s(): " - "%d instead of %d" % (self.name, - len(args_ll), - self.argnum)) + assert len(args_ll) == len(self.argtypes), ( + "wrong number of arguments in call to %s(): " + "%d instead of %d" % (self.name, len(args_ll), len(self.argtypes))) ll_args = lltype.malloc(rffi.VOIDPP.TO, len(args_ll), flavor='raw') for i in range(len(args_ll)): ll_args[i] = args_ll[i] @@ -221,6 +218,7 @@ def __init__(self, name, argtypes, restype, funcsym): # initialize each one of pointers with null AbstractFuncPtr.__init__(self, name, argtypes, restype, funcsym) + self.argnum = len(self.argtypes) self.pushed_args = 0 self.ll_args = lltype.malloc(rffi.VOIDPP.TO, self.argnum, flavor='raw') for i in range(self.argnum): From arigo at codespeak.net Mon Jan 14 13:06:16 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 13:06:16 +0100 (CET) Subject: [pypy-svn] r50583 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080114120616.C015A16850E@codespeak.net> Author: arigo Date: Mon Jan 14 13:06:16 2008 New Revision: 50583 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: (fijal, arigo) A first passing test in _rawffi! :-) Basically, _rawffi function pointers can only be called with arguments that are _array's of length 1. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Mon Jan 14 13:06:16 2008 @@ -9,7 +9,8 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror -from pypy.module._rawffi.structure import segfault_exception +from pypy.module._rawffi.interp_rawffi import segfault_exception +from pypy.module._rawffi.interp_rawffi import W_DataInstance from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value, _get_type,\ TYPEMAP from pypy.rlib.rarithmetic import intmask @@ -31,79 +32,83 @@ self.of = of self.itemsize = intmask(TYPEMAP[of].c_size) - def descr_call(self, space, w_length_or_iterable): - if space.is_true(space.isinstance(w_length_or_iterable, space.w_int)): - length = space.int_w(w_length_or_iterable) - return space.wrap(W_ArrayInstance(space, self, length)) - else: - items_w = space.unpackiterable(w_length_or_iterable) - length = len(items_w) - result = W_ArrayInstance(space, self, length) - for num in range(len(items_w)): + def allocate(self, space, length): + return W_ArrayInstance(space, self, length) + + def descr_call(self, space, length, w_iterable=None): + result = self.allocate(space, length) + if not space.is_w(w_iterable, space.w_None): + items_w = space.unpackiterable(w_iterable) + iterlength = len(items_w) + if iterlength > length: + raise OperationError(space.w_ValueError, + space.wrap("too many items for specified" + " array length")) + for num in range(iterlength): w_item = items_w[num] - unwrap_value(space, push_elem, result.ll_array, num, self.of, - w_item, None) - return space.wrap(result) + unwrap_value(space, push_elem, result.ll_buffer, num, self.of, + w_item) + return space.wrap(result) def fromaddress(self, space, address, length): return space.wrap(W_ArrayInstance(space, self, length, address)) fromaddress.unwrap_spec = ['self', ObjSpace, int, int] +class ArrayCache: + def __init__(self, space): + self.space = space + self.cache = {} + self.array_of_ptr = self.get_array_type('P') + + def get_array_type(self, of): + try: + return self.cache[of] + except KeyError: + _get_type(self.space, of) + result = W_Array(self.space, of) + self.cache[of] = result + return result + +def get_array_cache(space): + return space.fromcache(ArrayCache) + def descr_new_array(space, w_type, of): - _get_type(space, of) - return space.wrap(W_Array(space, of)) + array_type = get_array_cache(space).get_array_type(of) + return space.wrap(array_type) W_Array.typedef = TypeDef( 'Array', __new__ = interp2app(descr_new_array, unwrap_spec=[ObjSpace, W_Root, str]), __call__ = interp2app(W_Array.descr_call, - unwrap_spec=['self', ObjSpace, W_Root]), + unwrap_spec=['self', ObjSpace, int, W_Root]), fromaddress = interp2app(W_Array.fromaddress), of = interp_attrproperty('of', W_Array), ) W_Array.typedef.acceptable_as_base_class = False -class W_ArrayInstance(Wrappable): +class W_ArrayInstance(W_DataInstance): def __init__(self, space, shape, length, address=0): - self.ll_array = lltype.nullptr(rffi.VOIDP.TO) - self.alloced = False + W_DataInstance.__init__(self, space, shape.itemsize * length, address) self.length = length self.shape = shape - if address != 0: - self.ll_array = rffi.cast(rffi.VOIDP, address) - else: - size = shape.itemsize * length - self.ll_array = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', - zero=True) - # XXX don't allow negative indexes, nor slices def setitem(self, space, num, w_value): if num >= self.length or num < 0: raise OperationError(space.w_IndexError, space.w_None) - unwrap_value(space, push_elem, self.ll_array, num, self.shape.of, w_value, - None) + unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.of, + w_value) setitem.unwrap_spec = ['self', ObjSpace, int, W_Root] def getitem(self, space, num): if num >= self.length or num < 0: raise OperationError(space.w_ValueError, space.wrap( "Getting element %d of array sized %d" % (num, self.length))) - return wrap_value(space, get_elem, self.ll_array, num, self.shape.of) + return wrap_value(space, get_elem, self.ll_buffer, num, self.shape.of) getitem.unwrap_spec = ['self', ObjSpace, int] - def getbuffer(space, self): - return space.wrap(rffi.cast(rffi.INT, self.ll_array)) - - def free(self, space): - if not self.ll_array: - raise segfault_exception(space, "freeing NULL pointer") - lltype.free(self.ll_array, flavor='raw') - self.ll_array = lltype.nullptr(rffi.VOIDP.TO) - free.unwrap_spec = ['self', ObjSpace] - W_ArrayInstance.typedef = TypeDef( 'ArrayInstance', __setitem__ = interp2app(W_ArrayInstance.setitem), @@ -111,6 +116,6 @@ buffer = GetSetProperty(W_ArrayInstance.getbuffer), shape = interp_attrproperty('shape', W_ArrayInstance), free = interp2app(W_ArrayInstance.free), + byptr = interp2app(W_ArrayInstance.byptr), ) - - +W_ArrayInstance.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Mon Jan 14 13:06:16 2008 @@ -52,6 +52,7 @@ 'z' : ffi_type_pointer, 'O' : ffi_type_pointer, } +TYPEMAP_PTR_LETTERS = "POsz" LL_TYPEMAP = { 'c' : rffi.CHAR, @@ -122,8 +123,8 @@ argtypes = [space.str_w(w_arg) for w_arg in argtypes_w] ffi_argtypes = [self.get_type(arg) for arg in argtypes] try: - ptr = self.cdll.getpointer(name, ffi_argtypes, ffi_restype) - w_funcptr = W_FuncPtr(ptr, argtypes, restype) + ptr = self.cdll.getrawpointer(name, ffi_argtypes, ffi_restype) + w_funcptr = W_FuncPtr(space, ptr, argtypes, restype) space.setitem(self.w_cache, w_key, w_funcptr) return w_funcptr except KeyError: @@ -190,45 +191,53 @@ SIZE_CHECKERS[c] = make_size_checker(c, native_fmttable[c]['size'], signed) unroll_size_checkers = unrolling_iterable(SIZE_CHECKERS.items()) -def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg, to_free): - w = space.wrap - if tp == "d" or tp == "f": - if tp == "d": - push_func(add_arg, argdesc, space.float_w(w_arg)) +def segfault_exception(space, reason): + w_mod = space.getbuiltinmodule("_rawffi") + w_exception = space.getattr(w_mod, space.wrap("SegfaultException")) + return OperationError(w_exception, space.wrap(reason)) + + +class W_DataInstance(Wrappable): + def __init__(self, space, size, address=0): + if address != 0: + self.ll_buffer = rffi.cast(rffi.VOIDP, address) else: - push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT, - space.float_w(w_arg))) - elif tp == "s" or tp =="z": - ll_str = rffi.str2charp(space.str_w(w_arg)) - if to_free is not None: - to_free.append(ll_str) - push_func(add_arg, argdesc, ll_str) - elif tp == "P" or tp == "O": + self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', + zero=True) + + def getbuffer(space, self): + return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) + + def byptr(self, space): + from pypy.module._rawffi.array import get_array_cache + array_of_ptr = get_array_cache(space).array_of_ptr + array = array_of_ptr.allocate(space, 1) + array.setitem(space, 0, space.wrap(self)) + return space.wrap(array) + byptr.unwrap_spec = ['self', ObjSpace] + + def free(self, space): + if not self.ll_buffer: + raise segfault_exception(space, "freeing NULL pointer") + lltype.free(self.ll_buffer, flavor='raw') + self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO) + free.unwrap_spec = ['self', ObjSpace] + + +def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg): + w = space.wrap + if tp == "d": + push_func(add_arg, argdesc, space.float_w(w_arg)) + elif tp == "f": + push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT, + space.float_w(w_arg))) + elif tp in TYPEMAP_PTR_LETTERS: # check for NULL ptr - if space.is_w(w_arg, space.w_None): - push_func(add_arg, argdesc, lltype.nullptr(rffi.VOIDP.TO)) - elif space.is_true(space.isinstance(w_arg, space.w_int)): + if space.is_true(space.isinstance(w_arg, space.w_int)): push_func(add_arg, argdesc, rffi.cast(rffi.VOIDP, space.int_w(w_arg))) - elif space.is_true(space.isinstance(w_arg, space.w_basestring)): - if to_free is not None: - to_free.append(pack_pointer(space, add_arg, argdesc, w_arg, push_func)) else: - mod = space.getbuiltinmodule('_rawffi') - w_StructureInstance = space.getattr(mod, w('StructureInstance')) - w_ArrayInstance = space.getattr(mod, w('ArrayInstance')) - #w_CallbackPtr = space.getattr(mod, w('CallbackPtr')) - if space.is_true(space.isinstance(w_arg, w_StructureInstance)) or\ - space.is_true(space.isinstance(w_arg, w_ArrayInstance)): - ptr = rffi.cast(rffi.VOIDP, space.int_w(space.getattr(w_arg, w('buffer')))) - push_func(add_arg, argdesc, ptr) - #elif space.is_true(space.isinstance(w_arg, w_CallbackPtr)): - # TP = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) - # ptr = rffi.cast(TP, space.int_w(space.getattr(w_arg, w('buffer')))) - # push_func(add_arg, argdesc, ptr) - - else: - raise OperationError(space.w_TypeError, w( - "Expected structure, array or simple type")) + datainstance = space.interp_w(W_DataInstance, w_arg) + push_func(add_arg, argdesc, datainstance.ll_buffer) elif tp == "c": s = space.str_w(w_arg) if len(s) != 1: @@ -298,30 +307,35 @@ push._annspecialcase_ = 'specialize:argtype(2)' class W_FuncPtr(Wrappable): - def __init__(self, ptr, argtypes, restype): + def __init__(self, space, ptr, argtypes, restype): + from pypy.module._rawffi.array import get_array_cache self.ptr = ptr - self.restype = restype + cache = get_array_cache(space) + self.resarray = cache.get_array_type(restype) self.argtypes = argtypes - def call(self, space, arguments): - args_w, kwds_w = arguments.unpack() - # C has no keyword arguments - if kwds_w: - raise OperationError(space.w_TypeError, space.wrap( - "Provided keyword arguments for C function call")) - to_free = [] - i = 0 - for i in range(len(self.argtypes)): + def call(self, space, args_w): + from pypy.module._rawffi.array import W_ArrayInstance + argnum = len(args_w) + if argnum != len(self.argtypes): + msg = "Wrong number of argument: expected %d, got %d" % ( + len(self.argtypes), argnum) + raise OperationError(space.w_TypeError, space.wrap(msg)) + args_ll = [] + for i in range(argnum): argtype = self.argtypes[i] w_arg = args_w[i] - unwrap_value(space, push, self.ptr, i, argtype, w_arg, to_free) - i += 1 - try: - return wrap_value(space, ptr_call, self.ptr, None, self.restype) - finally: - for elem in to_free: - lltype.free(elem, flavor='raw') - call.unwrap_spec = ['self', ObjSpace, Arguments] + arg = space.interp_w(W_ArrayInstance, w_arg) + if arg.shape.of != argtype: + msg = "Argument %d should be typecode %s, got %s" % ( + i+1, argtype, arg.shape.of) + raise OperationError(space.w_TypeError, space.wrap(msg)) + args_ll.append(arg.ll_buffer) + # XXX we could avoid the intermediate list args_ll + result = self.resarray.allocate(space, 1) + self.ptr.call(args_ll, result.ll_buffer) + return space.wrap(result) + call.unwrap_spec = ['self', ObjSpace, 'args_w'] W_FuncPtr.typedef = TypeDef( 'FuncPtr', Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Mon Jan 14 13:06:16 2008 @@ -10,6 +10,8 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError, wrap_oserror +from pypy.module._rawffi.interp_rawffi import segfault_exception +from pypy.module._rawffi.interp_rawffi import W_DataInstance from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value, _get_type,\ TYPEMAP from pypy.rlib.rarithmetic import intmask @@ -96,20 +98,10 @@ return rffi.cast(TP, pos)[0] cast_pos._annspecialcase_ = 'specialize:arg(2)' -def segfault_exception(space, reason): - w_mod = space.getbuiltinmodule("_rawffi") - w_exception = space.getattr(w_mod, space.wrap("SegfaultException")) - return OperationError(w_exception, space.wrap(reason)) - -class W_StructureInstance(Wrappable): +class W_StructureInstance(W_DataInstance): def __init__(self, space, shape, address, fieldinits_w): - self.free_afterwards = False + W_DataInstance.__init__(self, space, shape.size, address) self.shape = shape - if address != 0: - self.ll_buffer = rffi.cast(rffi.VOIDP, address) - else: - self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, shape.size, flavor='raw', - zero=True) if fieldinits_w: for field, w_value in fieldinits_w.iteritems(): self.setattr(space, field, w_value) @@ -138,16 +130,6 @@ unwrap_value(space, push_field, self, i, c, w_value, None) setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] - def free(self, space): - if not self.ll_buffer: - raise segfault_exception(space, "freeing NULL pointer") - lltype.free(self.ll_buffer, flavor='raw') - self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO) - free.unwrap_spec = ['self', ObjSpace] - - def getbuffer(space, self): - return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) - W_StructureInstance.typedef = TypeDef( 'StructureInstance', @@ -156,6 +138,7 @@ buffer = GetSetProperty(W_StructureInstance.getbuffer), free = interp2app(W_StructureInstance.free), shape = interp_attrproperty('shape', W_StructureInstance), + byptr = interp2app(W_StructureInstance.byptr), ) W_StructureInstance.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Mon Jan 14 13:06:16 2008 @@ -131,13 +131,20 @@ def test_getchar(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) - get_char = lib.ptr('get_char', ['s', 'H'], 'c') - assert get_char('dupa', 2) == 'p' - assert get_char('dupa', 1) == 'u' - raises(ValueError, "get_char('xxx', 2 ** 17)") - raises(ValueError, "get_char('xxx', -1)") - get_char = lib.ptr('get_char', ['z', 'H'], 'c') - assert get_char('dupa', 2) == 'p' + get_char = lib.ptr('get_char', ['P', 'H'], 'c') + A = _rawffi.Array('c') + B = _rawffi.Array('H') + dupa = A(5, 'dupa') + dupaptr = dupa.byptr() + for i in range(4): + intptr = B(1) + intptr[0] = i + res = get_char(dupaptr, intptr) + assert res[0] == 'dupa'[i] + res.free() + intptr.free() + dupaptr.free() + dupa.free() def test_returning_str(self): import _rawffi From arigo at codespeak.net Mon Jan 14 13:08:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 13:08:23 +0100 (CET) Subject: [pypy-svn] r50584 - pypy/branch/applevel-ctypes2/pypy/module/_rawffi Message-ID: <20080114120823.D539516850E@codespeak.net> Author: arigo Date: Mon Jan 14 13:08:22 2008 New Revision: 50584 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Log: Forgot to check that the array is of length 1. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Mon Jan 14 13:08:22 2008 @@ -326,6 +326,10 @@ argtype = self.argtypes[i] w_arg = args_w[i] arg = space.interp_w(W_ArrayInstance, w_arg) + if arg.length != 1: + msg = ("Argument %d should be an array of length 1, " + "got length %d" % (i+1, arg.length)) + raise OperationError(space.w_TypeError, space.wrap(msg)) if arg.shape.of != argtype: msg = "Argument %d should be typecode %s, got %s" % ( i+1, argtype, arg.shape.of) From atobe at codespeak.net Mon Jan 14 13:10:01 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Mon, 14 Jan 2008 13:10:01 +0100 (CET) Subject: [pypy-svn] r50585 - pypy/branch/fixed-list-ootype/pypy/translator/jvm Message-ID: <20080114121001.B452816850E@codespeak.net> Author: atobe Date: Mon Jan 14 13:10:01 2008 New Revision: 50585 Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/opcodes.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py Log: (cfbolz,atobe): Implementing Array in JVM backend. Several tests pass. Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py Mon Jan 14 13:10:01 2008 @@ -513,6 +513,8 @@ return jObject if OOT in self.ootype_to_builtin: return JvmBuiltInType(self, self.ootype_to_builtin[OOT], OOT) + if isinstance(OOT, ootype.Array): + return self._array_type(OOT.ITEM) if OOT.__class__ in self.ootype_to_builtin: return JvmBuiltInType( self, self.ootype_to_builtin[OOT.__class__], OOT) @@ -533,6 +535,20 @@ assert False, "Untranslatable type %s!" % OOT + ooitemtype_to_array = { + ootype.Signed : jvmtype.jIntArray, + ootype.Unsigned : jvmtype.jIntArray, + ootype.Char : jvmtype.jCharArray, + ootype.Bool : jvmtype.jByteArray, + ootype.UniChar : jvmtype.jCharArray, + ootype.String : jvmtype.jStringArray, + } + + def _array_type(self, ITEM): + if ITEM in self.ooitemtype_to_array: + return self.ooitemtype_to_array[ITEM] + return jvmtype.jObjectArray + def annotation_to_cts(self, _tp): s_tp = annotation(_tp) TP = annotation_to_lltype(s_tp) Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py Mon Jan 14 13:10:01 2008 @@ -137,6 +137,32 @@ if desc == 'Z': return self._o("b") # Boolean (access as bytes) return OpcodeFamily.for_type(self, argtype) +class NewArrayOpcodeFamily(object): + def __init__(self): + self.cache = {} + + def for_type(self, arraytype): + try: + return self.cache[arraytype] + except KeyError: + pass + desc = arraytype.descriptor + if desc == '[I': + s = "newarray int" + elif desc == '[D': + s = "newarray double" + elif desc == '[C': + s = "newarray char" + elif desc == '[B': + s = "newarray byte" + else: + s = "anewarray" + self.cache[arraytype] = obj = Opcode(s) + return obj + +NEWARRAY = NewArrayOpcodeFamily() +ARRAYLENGTH = Opcode("arraylength") + # Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx # variants compare a single integer arg against 0, and the IF_ICMPxx # variants compare 2 integer arguments against each other. @@ -410,6 +436,47 @@ PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef) PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject) + +# special methods for arrays that are not really methods in the JVM +# XXX slightly hackish +class ArrayMethod(Method): + def __init__(self, arraytype, methodname): + self.arraytype = arraytype + self.ootype_methodname = methodname + Method.__init__(self, "", "", self._argtypes(), self._rettype(), + opcode=None) + + def _argtypes(self): + if self.ootype_methodname == "ll_length": + return [] + elif self.ootype_methodname == "ll_getitem_fast": + return [jInt] + elif self.ootype_methodname == "ll_setitem_fast": + return [jInt, self.arraytype.element_type] + else: + assert 0, "unknown array method" + + def _rettype(self): + if self.ootype_methodname == "ll_length": + return jInt + elif self.ootype_methodname == "ll_getitem_fast": + return self.arraytype.element_type + elif self.ootype_methodname == "ll_setitem_fast": + return jVoid + else: + assert 0, "unknown array method" + + def invoke(self, gen): + if self.ootype_methodname == "ll_length": + gen._instr(ARRAYLENGTH) + elif self.ootype_methodname == "ll_getitem_fast": + gen._instr(ARRLOAD.for_type(self.arraytype.element_type)) + elif self.ootype_methodname == "ll_setitem_fast": + gen._instr(ARRSTORE.for_type(self.arraytype.element_type)) + else: + assert 0, "unknown array method" + + # ___________________________________________________________________________ # Fields # @@ -1117,6 +1184,11 @@ self.emit(DUP) self.emit(ctor) + def oonewarray(self, TYPE, length): + jtype = self.db.lltype_to_cts(TYPE) + self.load(length) + self.emit(NEWARRAY.for_type(jtype)) + def instantiate(self): self.emit(PYPYRUNTIMENEW) Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/opcodes.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/opcodes.py Mon Jan 14 13:10:01 2008 @@ -6,7 +6,7 @@ """ from pypy.translator.oosupport.metavm import \ - PushArg, PushAllArgs, StoreResult, InstructionList, New, DoNothing, Call,\ + PushArg, PushAllArgs, StoreResult, InstructionList, New, OONewArray, DoNothing, Call,\ SetField, GetField, DownCast, RuntimeNew, OOString, OOUnicode, \ CastTo, PushPrimitive from pypy.translator.jvm.metavm import \ @@ -63,6 +63,7 @@ opcodes = _proc_dict({ # __________ object oriented operations __________ 'new': [New, StoreResult], + 'oonewarray': [OONewArray, StoreResult], 'runtimenew': [RuntimeNew, StoreResult], 'oosetfield': [SetField], 'oogetfield': [GetField, StoreResult], Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py Mon Jan 14 13:10:01 2008 @@ -232,12 +232,17 @@ self.element_type = elemtype def lookup_field(self, fieldnm): raise KeyError(fieldnm) # TODO adjust interface to permit opcode here - def lookup_method(self, methodnm): - raise KeyError(methodnm) # Arrays have no methods - + def lookup_method(self, methodnm): + # Arrays don't have methods in Java, but they do in the ootype system + from pypy.translator.jvm.generator import ArrayMethod + return ArrayMethod(self, methodnm) + jByteArray = JvmArrayType(jByte) jObjectArray = JvmArrayType(jObject) jStringArray = JvmArrayType(jString) +jDoubleArray = JvmArrayType(jDouble) +jCharArray = JvmArrayType(jChar) +jIntArray = JvmArrayType(jInt) class Generifier(object): From cfbolz at codespeak.net Mon Jan 14 13:26:00 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 13:26:00 +0100 (CET) Subject: [pypy-svn] r50586 - pypy/dist/pypy/translator/c/src Message-ID: <20080114122600.6B576168552@codespeak.net> Author: cfbolz Date: Mon Jan 14 13:25:58 2008 New Revision: 50586 Modified: pypy/dist/pypy/translator/c/src/stack.h Log: (bigdog) remove unused include Modified: pypy/dist/pypy/translator/c/src/stack.h ============================================================================== --- pypy/dist/pypy/translator/c/src/stack.h (original) +++ pypy/dist/pypy/translator/c/src/stack.h Mon Jan 14 13:25:58 2008 @@ -2,8 +2,6 @@ /************************************************************/ /*** C header subsection: stack operations ***/ -#include - #ifndef MAX_STACK_SIZE # define MAX_STACK_SIZE (1 << 19) #endif From cfbolz at codespeak.net Mon Jan 14 13:30:26 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 13:30:26 +0100 (CET) Subject: [pypy-svn] r50587 - pypy/dist/pypy/translator/c/src Message-ID: <20080114123026.0C5DE168552@codespeak.net> Author: cfbolz Date: Mon Jan 14 13:30:25 2008 New Revision: 50587 Modified: pypy/dist/pypy/translator/c/src/ll_strtod.h Log: (bigdog): add a necessary include for windows Modified: pypy/dist/pypy/translator/c/src/ll_strtod.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_strtod.h (original) +++ pypy/dist/pypy/translator/c/src/ll_strtod.h Mon Jan 14 13:30:25 2008 @@ -1,6 +1,10 @@ #ifndef LL_STRTOD_H #define LL_STRTOD_H +#ifdef MS_WINDOWS +#include +#endif + #include #include #include From fijal at codespeak.net Mon Jan 14 13:32:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jan 2008 13:32:10 +0100 (CET) Subject: [pypy-svn] r50588 - pypy/dist/pypy/rpython/module Message-ID: <20080114123210.352A0168557@codespeak.net> Author: fijal Date: Mon Jan 14 13:32:09 2008 New Revision: 50588 Modified: pypy/dist/pypy/rpython/module/ll_os.py Log: This is no longer necessary Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Mon Jan 14 13:32:09 2008 @@ -90,7 +90,7 @@ data = {'ret_type': 'int', 'name': name} decls.append(decl_snippet % data) defs.append(def_snippet % data) - h_source = ['#include "sys/wait.h"'] + decls + defs + h_source = decls + defs self.compilation_info = self.compilation_info.merge( ExternalCompilationInfo( From fijal at codespeak.net Mon Jan 14 13:37:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jan 2008 13:37:24 +0100 (CET) Subject: [pypy-svn] r50589 - pypy/dist/pypy/translator/c/src Message-ID: <20080114123724.D2DCA16855F@codespeak.net> Author: fijal Date: Mon Jan 14 13:37:24 2008 New Revision: 50589 Modified: pypy/dist/pypy/translator/c/src/signals.h Log: Allow multiple inclusion of signals.h Modified: pypy/dist/pypy/translator/c/src/signals.h ============================================================================== --- pypy/dist/pypy/translator/c/src/signals.h (original) +++ pypy/dist/pypy/translator/c/src/signals.h Mon Jan 14 13:37:24 2008 @@ -1,6 +1,9 @@ /* some ifdefs from CPython's signalmodule.c... */ +#ifndef _PYPY_SIGNALS_H +#define _PYPY_SIGNALS_H + #include #ifdef MS_WINDOWS @@ -121,3 +124,5 @@ } #endif + +#endif From arigo at codespeak.net Mon Jan 14 14:25:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 14:25:56 +0100 (CET) Subject: [pypy-svn] r50590 - in pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem: . test Message-ID: <20080114132556.2547E16855F@codespeak.net> Author: arigo Date: Mon Jan 14 14:25:55 2008 New Revision: 50590 Modified: pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: (fijal, arigo) ctypes bites again. Modified: pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py Mon Jan 14 14:25:55 2008 @@ -619,6 +619,8 @@ return ctypes2lltype(RESTYPE, cptr) # first cast the input pointer to an integer cvalue = ctypes.cast(cvalue, ctypes.c_void_p).value + if cvalue is None: + cvalue = 0 elif isinstance(cvalue, (str, unicode)): cvalue = ord(cvalue) # character -> integer Modified: pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Mon Jan 14 14:25:55 2008 @@ -332,6 +332,10 @@ for i in range(10): assert e[i] == i*i + c = lltype.nullptr(rffi.VOIDP.TO) + addr = rffi.cast(lltype.Signed, c) + assert addr == 0 + lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test From arigo at codespeak.net Mon Jan 14 14:26:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 14:26:52 +0100 (CET) Subject: [pypy-svn] r50591 - pypy/branch/applevel-ctypes2/pypy/interpreter Message-ID: <20080114132652.BFE9816855F@codespeak.net> Author: arigo Date: Mon Jan 14 14:26:52 2008 New Revision: 50591 Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py Log: (fijal, arigo) Don't segfault trying to print error messages about interp_w(BaseClass) if the BaseClass has no typedef attribute. Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py Mon Jan 14 14:26:52 2008 @@ -100,7 +100,7 @@ def descr_call_mismatch(self, space, opname, RequiredClass, args): msg = "'%s' object expected, got '%s' instead" % ( - RequiredClass.typedef.name, + wrappable_class_name(RequiredClass), self.getclass(space).getname(space, '?')) raise OperationError(space.w_TypeError, space.wrap(msg)) @@ -164,6 +164,15 @@ class DescrMismatch(Exception): pass +def wrappable_class_name(Class): + try: + return Class.typedef.name + except AttributeError: + return 'internal subclass of %s' % (Class.__name__,) +wrappable_class_name._annspecialcase_ = 'specialize:memo' + +# ____________________________________________________________ + class ObjSpace(object): """Base class for the interpreter-level implementations of object spaces. http://codespeak.net/pypy/dist/pypy/doc/objspace.html""" @@ -570,8 +579,8 @@ obj = self.interpclass_w(w_obj) if not isinstance(obj, RequiredClass): # or obj is None msg = "'%s' object expected, got '%s' instead" % ( - RequiredClass.typedef.name, - w_obj.getclass(self).getname(self, '?')) + wrappable_class_name(RequiredClass), + w_obj.getclass(self).getname(self, '?')) raise OperationError(self.w_TypeError, self.wrap(msg)) return obj interp_w._annspecialcase_ = 'specialize:arg(1)' From arigo at codespeak.net Mon Jan 14 14:52:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 14:52:43 +0100 (CET) Subject: [pypy-svn] r50592 - in pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem: . test Message-ID: <20080114135243.5CEDC39B592@codespeak.net> Author: arigo Date: Mon Jan 14 14:52:42 2008 New Revision: 50592 Modified: pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Bug test and fix. Modified: pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py Mon Jan 14 14:52:42 2008 @@ -51,7 +51,7 @@ for fieldname in S._names: FIELDTYPE = S._flds[fieldname] if max_n is not None and fieldname == S._arrayfld: - cls = build_ctypes_array(FIELDTYPE, None, max_n) + cls = get_ctypes_array_of_size(FIELDTYPE, max_n) else: cls = get_ctypes_type(FIELDTYPE) fields.append((fieldname, cls)) @@ -100,7 +100,7 @@ def _malloc(cls, n=None): if not isinstance(n, int): raise TypeError, "array length must be an int" - biggercls = build_ctypes_array(A, None, n) + biggercls = get_ctypes_array_of_size(A, n) bigarray = biggercls() if hasattr(bigarray, 'length'): bigarray.length = n @@ -136,6 +136,15 @@ CArray._normalized_ctype = get_ctypes_type(A) return CArray +def get_ctypes_array_of_size(FIELDTYPE, max_n): + if max_n > 0: + # no need to cache the results in this case, because the exact + # type is never seen - the array instances are cast to the + # array's _normalized_ctype, which is always the same. + return build_ctypes_array(FIELDTYPE, None, max_n) + else: + return get_ctypes_type(FIELDTYPE) + def get_ctypes_type(T, delayed_builders=None): try: return _ctypes_cache[T] Modified: pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Mon Jan 14 14:52:42 2008 @@ -758,3 +758,11 @@ qsort(rffi.cast(rffi.VOIDP, a), 5, rffi.sizeof(rffi.INT), compare) for i in range(5): assert a[i] == i + 1 + + def test_array_type_bug(self): + A = lltype.Array(lltype.Signed) + a1 = lltype.malloc(A, 0, flavor='raw') + a2 = lltype.malloc(A, 0, flavor='raw') + c1 = lltype2ctypes(a1) + c2 = lltype2ctypes(a2) + assert type(c1) is type(c2) From atobe at codespeak.net Mon Jan 14 14:53:30 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Mon, 14 Jan 2008 14:53:30 +0100 (CET) Subject: [pypy-svn] r50593 - pypy/branch/fixed-list-ootype/pypy/translator/jvm/src/pypy Message-ID: <20080114135330.8EC2A39B590@codespeak.net> Author: atobe Date: Mon Jan 14 14:53:30 2008 New Revision: 50593 Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/src/pypy/PyPy.java Log: (cfbolz, atobe): some reflection hackery to make java arrays returnable from java code to the test. Used only when testing. Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/src/pypy/PyPy.java ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/src/pypy/PyPy.java (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/src/pypy/PyPy.java Mon Jan 14 14:53:30 2008 @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Map; import java.text.DecimalFormat; +import java.lang.reflect.Array; /** * Class with a number of utility routines. One instance of this is @@ -398,7 +399,16 @@ sb.append("]"); return sb.toString(); } - else if (o instanceof String) { + if (o.getClass().isArray()) { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < Array.getLength(o); i++) { + sb.append(serializeObject(Array.get(o, i))).append(","); + } + sb.append("]"); + return sb.toString(); + } + if (o instanceof String) { return escaped_string((String)o); } return o.toString(); From arigo at codespeak.net Mon Jan 14 15:07:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 15:07:55 +0100 (CET) Subject: [pypy-svn] r50594 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080114140755.82FEE16854E@codespeak.net> Author: arigo Date: Mon Jan 14 15:07:54 2008 New Revision: 50594 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: (fijal, arigo) Finish _rawffi. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py Mon Jan 14 15:07:54 2008 @@ -19,6 +19,7 @@ '_get_type' : 'interp_rawffi._w_get_type', 'sizeof' : 'interp_rawffi.sizeof', 'alignment' : 'interp_rawffi.alignment', + 'charp2string' : 'interp_rawffi.charp2string', #'CallbackPtr' : 'callback.W_CallbackPtr', } Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Mon Jan 14 15:07:54 2008 @@ -104,8 +104,7 @@ def getitem(self, space, num): if num >= self.length or num < 0: - raise OperationError(space.w_ValueError, space.wrap( - "Getting element %d of array sized %d" % (num, self.length))) + raise OperationError(space.w_IndexError, space.w_None) return wrap_value(space, get_elem, self.ll_buffer, num, self.shape.of) getitem.unwrap_spec = ['self', ObjSpace, int] Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Mon Jan 14 15:07:54 2008 @@ -1,4 +1,4 @@ - +import sys from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable, \ Arguments from pypy.interpreter.error import OperationError, wrap_oserror @@ -80,7 +80,7 @@ return TYPEMAP[key] except KeyError: raise OperationError(space.w_ValueError, space.wrap( - "Uknown type letter %s" % (key,))) + "Unknown type letter %s" % (key,))) return lltype.nullptr(FFI_TYPE_P.TO) def _w_get_type(space, key): @@ -154,14 +154,6 @@ buffer.""" ) -def pack_pointer(space, add_arg, argdesc, w_arg, push_func): - arg = space.str_w(w_arg) - ll_str = lltype.malloc(rffi.CCHARP.TO, len(arg), flavor='raw') - for i in range(len(arg)): - ll_str[i] = arg[i] - push_func(add_arg, argdesc, ll_str) - return ll_str - def make_size_checker(format, size, signed): min, max, _ = min_max_acc_method(size, signed) @@ -206,7 +198,7 @@ zero=True) def getbuffer(space, self): - return space.wrap(rffi.cast(rffi.INT, self.ll_buffer)) + return space.wrap(rffi.cast(lltype.Signed, self.ll_buffer)) def byptr(self, space): from pypy.module._rawffi.array import get_array_cache @@ -270,48 +262,33 @@ def wrap_value(space, func, add_arg, argdesc, tp): for c, ll_type in ll_typemap_iter: if tp == c: - if c == 's' or c == 'z': - ptr = func(add_arg, argdesc, rffi.CCHARP) - if not ptr: - return space.w_None - return space.wrap(rffi.charp2str(ptr)) - elif c == 'P' or c == 'O': + if c in TYPEMAP_PTR_LETTERS: res = func(add_arg, argdesc, rffi.VOIDP) - if not res: - return space.w_None - return space.wrap(rffi.cast(rffi.INT, res)) + return space.wrap(rffi.cast(lltype.Signed, res)) elif c == 'v': func(add_arg, argdesc, ll_type) return space.w_None - elif c == 'q' or c == 'Q' or c == 'L': + elif c == 'q' or c == 'Q' or c == 'L' or c == 'c': return space.wrap(func(add_arg, argdesc, ll_type)) elif c == 'f' or c == 'd': return space.wrap(float(func(add_arg, argdesc, ll_type))) - elif c == 'c': - return space.wrap(chr(rffi.cast(rffi.INT, func(add_arg, argdesc, - ll_type)))) elif c == 'h' or c == 'H': - return space.wrap(rffi.cast(rffi.INT, func(add_arg, argdesc, + return space.wrap(rffi.cast(lltype.Signed, func(add_arg, argdesc, ll_type))) else: return space.wrap(intmask(func(add_arg, argdesc, ll_type))) return space.w_None wrap_value._annspecialcase_ = 'specialize:arg(1)' -def ptr_call(ptr, some_arg, ll_type): - return ptr.call(ll_type) -ptr_call._annspecialcase_ = 'specialize:arg(2)' - -def push(ptr, argdesc, value): - ptr.push_arg(value) -push._annspecialcase_ = 'specialize:argtype(2)' - class W_FuncPtr(Wrappable): def __init__(self, space, ptr, argtypes, restype): from pypy.module._rawffi.array import get_array_cache self.ptr = ptr - cache = get_array_cache(space) - self.resarray = cache.get_array_type(restype) + if restype != 'v': + cache = get_array_cache(space) + self.resarray = cache.get_array_type(restype) + else: + self.resarray = None self.argtypes = argtypes def call(self, space, args_w): @@ -336,9 +313,13 @@ raise OperationError(space.w_TypeError, space.wrap(msg)) args_ll.append(arg.ll_buffer) # XXX we could avoid the intermediate list args_ll - result = self.resarray.allocate(space, 1) - self.ptr.call(args_ll, result.ll_buffer) - return space.wrap(result) + if self.resarray is not None: + result = self.resarray.allocate(space, 1) + self.ptr.call(args_ll, result.ll_buffer) + return space.wrap(result) + else: + self.ptr.call(args_ll, lltype.nullptr(rffi.VOIDP.TO)) + return space.w_None call.unwrap_spec = ['self', ObjSpace, 'args_w'] W_FuncPtr.typedef = TypeDef( @@ -362,3 +343,10 @@ sizeof = _create_new_accessor('sizeof', 'c_size') alignment = _create_new_accessor('alignment', 'c_alignment') + +def charp2string(space, address, maxlength=sys.maxint): + if address == 0: + return space.w_None + s = rffi.charp2strn(rffi.cast(rffi.CCHARP, address), maxlength) + return space.wrap(s) +charp2string.unwrap_spec = [ObjSpace, int, int] Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Mon Jan 14 15:07:54 2008 @@ -127,7 +127,7 @@ raise segfault_exception(space, "accessing NULL pointer") i = self.getindex(space, attr) _, c = self.shape.fields[i] - unwrap_value(space, push_field, self, i, c, w_value, None) + unwrap_value(space, push_field, self, i, c, w_value) setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Mon Jan 14 15:07:54 2008 @@ -97,11 +97,11 @@ return x; } + static int prebuilt_array1[] = {3}; + int* allocate_array() { - int *res = (int*)malloc(sizeof(int)); - res[0] = 3; - return res; + return prebuilt_array1; } ''')) @@ -150,52 +150,64 @@ import _rawffi lib = _rawffi.CDLL(self.lib_name) char_check = lib.ptr('char_check', ['c', 'c'], 's') - assert char_check('y', 'x') == 'xxxxxx' - assert char_check('x', 'y') is None + A = _rawffi.Array('c') + arg1 = A(1) + arg2 = A(1) + arg1[0] = 'y' + arg2[0] = 'x' + res = char_check(arg1, arg2) + assert _rawffi.charp2string(res[0]) == 'xxxxxx' + res.free() + arg1[0] = 'x' + arg2[0] = 'y' + res = char_check(arg1, arg2) + assert res[0] == 0 + assert _rawffi.charp2string(res[0]) is None + res.free() + arg1.free() + arg2.free() def test_short_addition(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) short_add = lib.ptr('add_shorts', ['h', 'h'], 'H') - assert short_add(1, 2) == 3 - - def test_rand(self): - import _rawffi - libc = _rawffi.CDLL('libc.so.6') - func = libc.ptr('rand', [], 'i') - first = func() - count = 0 - for i in range(100): - res = func() - if res == first: - count += 1 - assert count != 100 + A = _rawffi.Array('h') + arg1 = A(1) + arg2 = A(1) + arg1[0] = 1 + arg2[0] = 2 + res = short_add(arg1, arg2) + assert res[0] == 3 + res.free() + arg1.free() + arg2.free() def test_pow(self): import _rawffi libm = _rawffi.CDLL('libm.so') pow = libm.ptr('pow', ['d', 'd'], 'd') - assert pow(2.0, 2.0) == 4.0 - assert pow(3.0, 3.0) == 27.0 - assert pow(2, 2) == 4.0 - raises(TypeError, "pow('x', 2.0)") - - def test_strlen(self): - import _rawffi - libc = _rawffi.CDLL('libc.so.6') - strlen = libc.ptr('strlen', ['s'], 'i') - assert strlen("dupa") == 4 - assert strlen("zupa") == 4 - strlen = libc.ptr('strlen', ['P'], 'i') - assert strlen("ddd\x00") == 3 - strdup = libc.ptr('strdup', ['s'], 's') - assert strdup("xxx") == "xxx" + A = _rawffi.Array('d') + arg1 = A(1) + arg2 = A(1) + raises(TypeError, "arg1[0] = 'x'") + arg1[0] = 3 + arg2[0] = 2.0 + res = pow(arg1, arg2) + assert res[0] == 9.0 + res.free() + arg1.free() + arg2.free() def test_time(self): import _rawffi libc = _rawffi.CDLL('libc.so.6') time = libc.ptr('time', ['P'], 'l') - assert time(None) != 0 + arg = _rawffi.Array('P')(1) + arg[0] = 0 + res = time(arg) + assert res[0] != 0 + res.free() + arg.free() def test_gettimeofday(self): import _rawffi @@ -203,13 +215,26 @@ structure = struct_type() libc = _rawffi.CDLL('libc.so.6') gettimeofday = libc.ptr('gettimeofday', ['P', 'P'], 'i') - assert gettimeofday(structure, None) == 0 + + arg1 = structure.byptr() + arg2 = _rawffi.Array('P')(1) + res = gettimeofday(arg1, arg2) + assert res[0] == 0 + res.free() + struct2 = struct_type() - assert gettimeofday(struct2, None) == 0 + arg1[0] = struct2 + res = gettimeofday(arg1, arg2) + assert res[0] == 0 + res.free() + assert structure.tv_usec != struct2.tv_usec assert (structure.tv_sec == struct2.tv_sec) or (structure.tv_sec == struct2.tv_sec - 1) raises(AttributeError, "structure.xxx") structure.free() + struct2.free() + arg1.free() + arg2.free() def test_structreturn(self): import _rawffi @@ -217,17 +242,22 @@ x = X() x.x = 121 Tm = _rawffi.Structure([('tm_sec', 'i'), - ('tm_min', 'i'), - ('tm_hour', 'i'), - ("tm_mday", 'i'), - ("tm_mon", 'i'), - ("tm_year", 'i'), - ("tm_wday", 'i'), - ("tm_yday", 'i'), - ("tm_isdst", 'i')]) + ('tm_min', 'i'), + ('tm_hour', 'i'), + ("tm_mday", 'i'), + ("tm_mon", 'i'), + ("tm_year", 'i'), + ("tm_wday", 'i'), + ("tm_yday", 'i'), + ("tm_isdst", 'i')]) libc = _rawffi.CDLL('libc.so.6') gmtime = libc.ptr('gmtime', ['P'], 'P') - t = Tm.fromaddress(gmtime(x)) + + arg = x.byptr() + res = gmtime(arg) + t = Tm.fromaddress(res[0]) + res.free() + arg.free() assert t.tm_year == 70 assert t.tm_sec == 1 assert t.tm_min == 2 @@ -238,18 +268,18 @@ lib = _rawffi.CDLL(self.lib_name) inner = lib.ptr("inner_struct_elem", ['P'], 'c') X = _rawffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')]) - next = X(next=None, x3='x') + next = X(next=0, x3='x') x = X(next=next, x1=1, x2=2, x3='x') assert X.fromaddress(x.next).x3 == 'x' x.free() next.free() create_double_struct = lib.ptr("create_double_struct", [], 'P') - x = create_double_struct() - x = X.fromaddress(x) + res = create_double_struct() + x = X.fromaddress(res[0]) assert X.fromaddress(x.next).x2 == 3 free_double_struct = lib.ptr("free_double_struct", ['P'], None) - free_double_struct(x) - + free_double_struct(res) + res.free() def test_array(self): import _rawffi @@ -260,16 +290,17 @@ a[8] = 3 a[7] = 1 a[6] = 2 - assert get_array_elem(a, 9) == 0 - assert get_array_elem(a, 8) == 3 - assert get_array_elem(a, 7) == 1 - assert get_array_elem(a, 6) == 2 + arg1 = a.byptr() + arg2 = A(1) + for i, expected in enumerate([0, 0, 0, 0, 0, 0, 2, 1, 3, 0]): + arg2[0] = i + res = get_array_elem(arg1, arg2) + assert res[0] == expected + res.free() + arg1.free() + arg2.free() assert a[3] == 0 a.free() - a = A([1, 2, 3, 4]) - assert get_array_elem(a, 0) == 1 - assert a[3] == 4 - a.free() def test_array_of_structure(self): import _rawffi @@ -280,10 +311,18 @@ a = A(3) a[1] = x get_array_elem_s = lib.ptr('get_array_elem_s', ['P', 'i'], 'P') - ptr1 = get_array_elem_s(a, 0) - assert ptr1 is None - assert X.fromaddress(get_array_elem_s(a, 1)).x2 == 3 - assert get_array_elem_s(a, 1) == x.buffer + arg1 = a.byptr() + arg2 = _rawffi.Array('i')(1) + res = get_array_elem_s(arg1, arg2) + assert res[0] == 0 + res.free() + arg2[0] = 1 + res = get_array_elem_s(arg1, arg2) + assert X.fromaddress(res[0]).x2 == 3 + assert res[0] == x.buffer + res.free() + arg1.free() + arg2.free() x.free() a.free() @@ -300,31 +339,27 @@ raises(ValueError, _rawffi.Structure, [('x1', 'xx')]) raises(ValueError, "_rawffi.Array('xx')") - def test_implicit_structure(self): - skip("Does not work yet") - import _rawffi - lib = _rawffi.CDLL(self.lib_name) - X = _rawffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'self')]) - inner = lib.ptr("inner_struct_elem", [X], 'c') - x = X(next=X(next=None, x3='x'), x1=1, x2=2, x3='x') - assert x.next.x3 == 'x' - assert inner(x) == 'x' - create_double_struct = lib.ptr("create_double_struct", [], X) - x = create_double_struct() - assert x.next.x2 == 3 - - def test_longs_ulongs(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) some_huge_value = lib.ptr('some_huge_value', [], 'q') - assert some_huge_value() == 1<<42 + res = some_huge_value() + assert res[0] == 1<<42 + res.free() some_huge_uvalue = lib.ptr('some_huge_uvalue', [], 'Q') - assert some_huge_uvalue() == 1<<42 - x = lib.ptr('some_huge_value', ['Q'], None) - raises(ValueError, "x(-1)") + res = some_huge_uvalue() + assert res[0] == 1<<42 + res.free() + arg1 = _rawffi.Array('Q')(1) + raises(ValueError, "arg1[0] = -1") + arg1.free() pass_ll = lib.ptr('pass_ll', ['q'], 'q') - assert pass_ll(1<<42) == 1<<42 + arg1 = _rawffi.Array('q')(1) + arg1[0] = 1<<42 + res = pass_ll(arg1) + assert res[0] == 1<<42 + res.free() + arg1.free() def test_callback(self): skip("Not working") @@ -363,10 +398,11 @@ lib = _rawffi.CDLL(self.lib_name) alloc = lib.ptr('allocate_array', [], 'P') A = _rawffi.Array('i') - a = A.fromaddress(alloc(), 1) + res = alloc() + a = A.fromaddress(res[0], 1) + res.free() assert a[0] == 3 assert A.fromaddress(a.buffer, 1)[0] == 3 - # a.free() - don't free as ll2ctypes is complaining massively def test_shape(self): import _rawffi @@ -393,6 +429,12 @@ get_array_elem = lib.ptr('get_array_elem', ['P', 'i'], 'i') a = A(1) a[0] = 3 - res = get_array_elem(a.buffer, 0) - assert res == 3 + arg1 = _rawffi.Array('P')(1) + arg1[0] = a.buffer + arg2 = _rawffi.Array('i')(1) + res = get_array_elem(arg1, arg2) + assert res[0] == 3 + res.free() + arg1.free() + arg2.free() a.free() From arigo at codespeak.net Mon Jan 14 15:24:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 15:24:05 +0100 (CET) Subject: [pypy-svn] r50595 - pypy/branch/applevel-ctypes2/pypy/interpreter Message-ID: <20080114142405.B0AF5168560@codespeak.net> Author: arigo Date: Mon Jan 14 15:23:58 2008 New Revision: 50595 Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py Log: Translation fixes. Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py Mon Jan 14 15:23:58 2008 @@ -99,9 +99,12 @@ raise NotImplementedError def descr_call_mismatch(self, space, opname, RequiredClass, args): + if RequiredClass is None: + classname = '?' + else: + classname = wrappable_class_name(RequiredClass) msg = "'%s' object expected, got '%s' instead" % ( - wrappable_class_name(RequiredClass), - self.getclass(space).getname(space, '?')) + classname, self.getclass(space).getname(space, '?')) raise OperationError(space.w_TypeError, space.wrap(msg)) # used by _weakref implemenation @@ -574,6 +577,7 @@ Unwrap w_obj, checking that it is an instance of the required internal interpreter class (a subclass of Wrappable). """ + assert RequiredClass is not None if can_be_None and self.is_w(w_obj, self.w_None): return None obj = self.interpclass_w(w_obj) From exarkun at codespeak.net Mon Jan 14 15:55:52 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Mon, 14 Jan 2008 15:55:52 +0100 (CET) Subject: [pypy-svn] r50596 - pypy/build/buildbot Message-ID: <20080114145552.0CF151684D9@codespeak.net> Author: exarkun Date: Mon Jan 14 15:55:51 2008 New Revision: 50596 Added: pypy/build/buildbot/ pypy/build/buildbot/master.cfg pypy/build/buildbot/pypy_status.py pypy/build/buildbot/pypybuilders.py pypy/build/buildbot/slaveinfo.py pypy/build/buildbot/text-conftest.py Log: master configuration for pypy buildbot Added: pypy/build/buildbot/master.cfg ============================================================================== --- (empty file) +++ pypy/build/buildbot/master.cfg Mon Jan 14 15:55:51 2008 @@ -0,0 +1,69 @@ + +from buildbot.scheduler import Nightly +from buildbot.buildslave import BuildSlave +from buildbot.status.html import WebStatus + +from pypybuilders import PyPyBuildFactory +from slaveinfo import passwords + +httpPortNumber = 10408 + +# I really wanted to pass logPath to Site +from twisted.web.server import Site +class LoggingSite(Site): + def __init__(self, *a, **kw): + Site.__init__(self, logPath='httpd.log', *a, **kw) +from twisted.web import server +server.Site = LoggingSite +# So I did. + +BuildmasterConfig = { + 'slavePortnum': "tcp:10407", + + 'change_source': [], + 'schedulers': [Nightly("nightly", [ + "pypy-c-allworkingmodules-32", + "pypy-c-allworkingmodules-faassen-32", + "pypy-c-allworkingmodules-faassen-64", + "pypy-c-allworkingmodules-faassen-winxp32"], + hour=19)], + 'status': [WebStatus(httpPortNumber, allowForce=True)], + + 'slaves': [BuildSlave(name, password) + for (name, password) + in passwords.iteritems()], + + 'builders': [{"name": "pypy-c-allworkingmodules-32", + "slavenames": ["charm"], + "builddir": "pypy-c-allworkingmodules-32", + "factory": PyPyBuildFactory(["--boxed"], + [], + ["--allworkingmodules"])}, + + {"name": "pypy-c-allworkingmodules-faassen-32", + "slavenames": ["charm"], + "builddir": "pypy-c-allworkingmodules-faassen-32", + "factory": PyPyBuildFactory(None, + ["--gc=semispace"], + ["--allworkingmodules", + "--faassen"])}, + + {"name": "pypy-c-allworkingmodules-faassen-64", + "slavenames": ["linux-dvs0"], + "builddir": "pypy-c-allworkingmodules-faassen-64", + "factory": PyPyBuildFactory([], + [], + ["--allworkingmodules", + "--faassen"])}, + + {"name": "pypy-c-allworkingmodules-faassen-winxp32", + "slavenames": ["winxp32-py2.5"], + "builddir": "pypy-c-allworkingmodules-faassen-winxp32", + "factory": PyPyBuildFactory([], + [], + [])}, + ], + + 'buildbotURL': 'http://office.divmod.com:%d/' % (httpPortNumber,), + 'projectURL': 'http://codespeak.net/pypy/', + 'projectName': 'PyPy'} Added: pypy/build/buildbot/pypy_status.py ============================================================================== --- (empty file) +++ pypy/build/buildbot/pypy_status.py Mon Jan 14 15:55:51 2008 @@ -0,0 +1,61 @@ + +from sets import Set + +from nevow import tags +from nevow.url import URL +from nevow.flat import flatten + +from buildbot.status.web.base import ICurrentBox, HtmlResource, map_branches, build_get_class + +class RecentlyFailingTests(HtmlResource): + def body(self, request): + status = self.getStatus(req) + builderNames = status.getBuilderNames() + + # Keys are the names of tests which failed recently. Each + # value is a list the elements of which is a group of test + # results for a particular build. The group is a dict the + # keys of which are a builder name and the values of which are + # the result for that test on that builder for that build. + # eg + # + # {'foo.tests.test_foo.FooTests.test_foo': [ + # {'win32': 'passed', 'linux': 'failed'}, + # {'win32': 'passed', 'linux': 'passed'}, + # {'win32': 'failed', 'linux': 'passed'}]} + failedTests = {} + + for name in builderNames: + recentFailures = Set() + builder = status.getBuilder(name) + recentBuilds = builder.generateFinishedBuilds(branches=[None], num_builds=10) + for build in recentBuilds: + recentFailures.update(build.getLog('failed').splitlines()) + + for name in builderNames: + builder = status.getBuilder(name) + recentBuilds = builder.generateFinishedBuilds(branches=[None], num_builds=10) + for build in recentBuilds: + results = {} + for passed in build.getLog('passed').splitlines(): + results[passed] = 'passed' + for failed in build.getLog('failed').splitlines(): + results[failed] = 'failed' + for skipped in build.getLog('skipped').splitlines(): + results[skipped] = 'skipped' + for recentFailed in recentFailures: + + + + + table = tags.table[[ + tags.tr[[ + tags.td[[ + testResult[0] + for testResult + in testResultsForBuild], + tags.td[testName]] + for testResultsForBuild + in testResultsOverTime]] + for (testName, testResultsOverTime) + in failedTests.iteritems()]] Added: pypy/build/buildbot/pypybuilders.py ============================================================================== --- (empty file) +++ pypy/build/buildbot/pypybuilders.py Mon Jan 14 15:55:51 2008 @@ -0,0 +1,132 @@ + +from buildbot.interfaces import LOG_CHANNEL_STDOUT +from buildbot.process.factory import BuildFactory +from buildbot.steps.source import SVN +from buildbot.steps.shell import ShellCommand +from buildbot.steps.transfer import FileUpload, FileDownload +from buildbot.steps.python_twisted import Trial + +class Translate(ShellCommand): + name = "translate" + description = ["Translating"] + descriptionDone = ["Translation"] + + command = ["python", "translate.py", "--batch"] + translationTarget = "targetpypystandalone" + haltOnFailure = True + + def __init__(self, translationArgs, targetArgs, + workdir="build/pypy-src/pypy/translator/goal", + *a, **kw): + self.command = self.command + translationArgs + [self.translationTarget] + targetArgs + ShellCommand.__init__(self, workdir, *a, **kw) + + + +class PyTest(ShellCommand): + name = "py.test pypy" + description = ["PyPy", "Tests"] + + command = ["find", "-name", "test", "-type", "d", "-exec", "python", "py/bin/py.test", "--session=MySession", "{}", ";"] + haltOnFailure = False + + def __init__(self, testPackage, testArguments, workdir="build/pypy-src", *a, **kw): + ShellCommand.__init__(self, workdir, *a, **kw) + self.command = list(self.command) + self.command[1:1] = [testPackage] + self.command[-2:-2] = testArguments + + + def createSummary(self, log): + """ + foo.test.test_foo.py.AppTestFoo.().test_foo passed + foo.test.test_foo.py.AppTestFoo.().test_bar failed + foo.test.test_foo.py.AppTestFoo.().test_baz skipped + """ + stdout = ''.join( + log.getChunks(channels=[LOG_CHANNEL_STDOUT], + onlyText=True)) + + resultLists = { + 'passed': [], + 'failed': [], + 'skipped': [], + } + weird = [] + for result in stdout.splitlines(): + testName, testResult = result.rsplit(None, 1) + if testResult in resultLists: + resultLists[testResult].append(testName) + else: + weird.append(result) + resultLists['weird'] = weird + + for testGroup, testNames in resultLists.iteritems(): + if testNames: + self.addCompleteLog( + '%d %s' % (len(testNames), testGroup), + '\n'.join(testNames)) + + + +class PySwitch(ShellCommand): + name = "switch" + description = ["Switch", "Py", "to", "reporter-merge"] + + command = ["svn", "switch", + "http://codespeak.net/svn/py/branch/reporter-merge/py"] + haltOnFailure = True + + def __init__(self, workdir="build/pypy-src/py", *a, **kw): + ShellCommand.__init__(self, workdir, *a, **kw) + + + +class PyPyBuildFactory(BuildFactory): + def __init__(self, pytestArguments, translationArguments, + targetArguments, *a, **kw): + BuildFactory.__init__(self, *a, **kw) + + self.addStep( + SVN, + workdir="build/pypy-src", + svnurl="http://codespeak.net/svn/pypy/dist", + mode="copy") + + self.addStep(PySwitch) + self.addStep( + FileDownload, + mastersrc="text-conftest.py", + slavedest="conftest.py", + workdir="build/pypy-src") + + if pytestArguments is not None: + self.addStep( + PyTest, + testPackage="pypy", + testArguments=pytestArguments, + timeout=60 * 60) + + self.addStep( + Translate, + translationArgs=translationArguments, + targetArgs=targetArguments) + + # self.addStep(FileUpload, + # slavesrc="pypy-src/pypy/translator/goal/pypy-c", + # masterdest="pypy-c") + + self.addStep( + SVN, + workdir="build/twisted-src", + svnurl="svn://svn.twistedmatrix.com/svn/Twisted/trunk", + mode="copy") + + self.addStep( + Trial, + workdir="build/twisted-src", + python=["../pypy-src/pypy/translator/goal/pypy-c", + "--oldstyle"], + testpath=None, + trial="bin/trial", + tests=["twisted"]) Added: pypy/build/buildbot/slaveinfo.py ============================================================================== --- (empty file) +++ pypy/build/buildbot/slaveinfo.py Mon Jan 14 15:55:51 2008 @@ -0,0 +1,3 @@ + +# Mapping from slave name to slave password +passwords = {} Added: pypy/build/buildbot/text-conftest.py ============================================================================== --- (empty file) +++ pypy/build/buildbot/text-conftest.py Mon Jan 14 15:55:51 2008 @@ -0,0 +1,42 @@ + +import sys + +import py +from py.__.test.session import Session +from py.__.test.reporter import AbstractReporter + +class MyReporter(AbstractReporter): + def __init__(self, *args, **kwds): + super(MyReporter, self).__init__(*args, **kwds) + + # XXXXXXXXXXXXXXx SUPER HACK mostly broken only works if you run + # py.test just how I run py.test, sorry. -exarkun + self.name = filter(None, sys.argv[-1].split('/')[:-1]) + + def report_unknown(self, event): + pass + + def report_TestStarted(self, event): + pass + + def report_TestFinished(self, event): + pass + + def report_ReceivedItemOutcome(self, event): + if event.outcome.passed: + result = 'passed' + elif event.outcome.skipped: + result = 'skipped' + else: + result = 'failed' + self.out.line('%s %s' % ('.'.join(self.name), result)) + + def report_ItemStart(self, event): + self.name.append(event.item.name) + + def report_ItemFinish(self, event): + self.name.pop() + +class MySession(Session): + reporterclass = MyReporter + From fijal at codespeak.net Mon Jan 14 15:57:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jan 2008 15:57:32 +0100 (CET) Subject: [pypy-svn] r50597 - pypy/dist/pypy/doc Message-ID: <20080114145732.EAE781684D9@codespeak.net> Author: fijal Date: Mon Jan 14 15:57:32 2008 New Revision: 50597 Modified: pypy/dist/pypy/doc/confrest.py Log: s/downloads/blog/, makes more sense Modified: pypy/dist/pypy/doc/confrest.py ============================================================================== --- pypy/dist/pypy/doc/confrest.py (original) +++ pypy/dist/pypy/doc/confrest.py Mon Jan 14 15:57:32 2008 @@ -12,6 +12,7 @@ class_="menu"), " ", html.a("documentation", href=self.get_doclink("index.html"), class_="menu"), " ", + html.a("blog", href="http://morepypy.blogspot.com", class_="menu"), html.a("downloads", href=self.get_doclink("download.html"), class_="menu"), " ", html.a("svn", href="https://codespeak.net/viewvc/pypy/dist/", From arigo at codespeak.net Mon Jan 14 16:02:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 16:02:23 +0100 (CET) Subject: [pypy-svn] r50598 - pypy/dist/pypy/doc Message-ID: <20080114150223.2B6DF1684D9@codespeak.net> Author: arigo Date: Mon Jan 14 16:02:21 2008 New Revision: 50598 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Small updates of getting-started. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Mon Jan 14 16:02:21 2008 @@ -571,9 +571,9 @@ python translate.py --run targetpypystandalone.py By default the translation process will try to use the -`Boehm-Demers-Weiser garbage collector`_ for the translated interpreter (Use -``--gc=framework`` to use our own exact mark-n-sweep implementation which -at the moment is slower but doesn't have external dependencies). Otherwise, be +`Boehm-Demers-Weiser garbage collector`_ for the translated interpreter. Use +``--gc=generation`` to use our own exact generational implementation which +is now faster and doesn't have external dependencies. Otherwise, be sure io install Boehm before starting the translation (e.g. by running ``apt-get install libgc-dev`` on Debian or Ubuntu). @@ -621,10 +621,9 @@ * ``--stackless``: this produces a pypy-c that includes features inspired by `Stackless Python `__. - * ``--gc=boehm|ref|framework|stacklessgc``: choose between using + * ``--gc=boehm|ref|marknsweep|semispace|generation``: choose between using the `Boehm-Demers-Weiser garbage collector`_, our reference - counting implementation or our own implementation of a mark and - sweep collector, with two different approaches for finding roots + counting implementation or three of own collector implementations (as we have seen Boehm's collector is the default). Find a more detailed description of the various options in our `configuration From fijal at codespeak.net Mon Jan 14 16:03:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 14 Jan 2008 16:03:50 +0100 (CET) Subject: [pypy-svn] r50599 - pypy/dist/pypy/doc Message-ID: <20080114150350.C4B1F1684D9@codespeak.net> Author: fijal Date: Mon Jan 14 16:03:50 2008 New Revision: 50599 Modified: pypy/dist/pypy/doc/confrest.py Log: Move blog next to news and really remove downloads. Modified: pypy/dist/pypy/doc/confrest.py ============================================================================== --- pypy/dist/pypy/doc/confrest.py (original) +++ pypy/dist/pypy/doc/confrest.py Mon Jan 14 16:03:50 2008 @@ -7,14 +7,12 @@ html.a("news", href="http://codespeak.net/pypy/dist/pypy/doc/news.html", class_="menu"), " ", + html.a("blog", href="http://morepypy.blogspot.com", class_="menu"), html.a("getting-started", href=self.get_doclink("getting-started.html"), class_="menu"), " ", html.a("documentation", href=self.get_doclink("index.html"), class_="menu"), " ", - html.a("blog", href="http://morepypy.blogspot.com", class_="menu"), - html.a("downloads", href=self.get_doclink("download.html"), - class_="menu"), " ", html.a("svn", href="https://codespeak.net/viewvc/pypy/dist/", class_="menu"), " ", html.a("issues", From hpk at codespeak.net Mon Jan 14 16:19:59 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 14 Jan 2008 16:19:59 +0100 (CET) Subject: [pypy-svn] r50600 - pypy/dist/pypy/doc Message-ID: <20080114151959.CC0CB3180C6@codespeak.net> Author: hpk Date: Mon Jan 14 16:19:57 2008 New Revision: 50600 Added: pypy/dist/pypy/doc/home.txt Log: new suggestion for the main page for when you get to http://codespeak.net/pypy. With this i think we could turn news/blog into just "blog" and also forget about "contact". Added: pypy/dist/pypy/doc/home.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/home.txt Mon Jan 14 16:19:57 2008 @@ -0,0 +1,45 @@ + +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 +nonsense, isn't it? `more...`_ + +Getting into PyPy ... +============================================= + +* `PyPy blog`_ for news and status blog about PyPy developments + +* `development mailing list`_ for conceptual and coding discussions + +* `subversion commit mailing list`_ for all updates to code and + documentation. + +.. _`sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint +.. _`subversion commit mailing list`: http://codespeak.net/mailman/listinfo/pypy-svn +.. _`development mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev + +* `development bug/feature tracker`_ for filing bugs and feature requests. + +* `sprint mailing list`_ for people (interested in) attending upcoming sprints. + +* **IRC channel #pypy on freenode**: Many of the core developers are hanging out + at #pypy on irc.freenode.net. You are welcome to join and ask questions even more + so if you are interested in participating in some parts of the PyPy project. You + can find the logs of the channel here_. + + +Meeting PyPy developers +======================= + +The PyPy developers are organising sprints and presenting results at +conferences all year round. They will be happy to meet in person with +anyone interested in the project. Watch out for sprint announcements. + +.. _Python: http://www.python.org/doc/current/ref/ref.html +.. _`more...`: architecture.html#mission-statement +.. _`PyPy blog`: http://morepypy.blogspot.com/ +.. _`development bug/feature tracker`: https://codespeak.net/issue/pypy-dev/ +.. _here: http://tismerysoft.de/pypy/irc-logs/pypy + + From hpk at codespeak.net Mon Jan 14 16:20:54 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 14 Jan 2008 16:20:54 +0100 (CET) Subject: [pypy-svn] r50601 - pypy/dist/pypy/doc Message-ID: <20080114152054.D70C93180C8@codespeak.net> Author: hpk Date: Mon Jan 14 16:20:54 2008 New Revision: 50601 Modified: pypy/dist/pypy/doc/home.txt Log: re-order links Modified: pypy/dist/pypy/doc/home.txt ============================================================================== --- pypy/dist/pypy/doc/home.txt (original) +++ pypy/dist/pypy/doc/home.txt Mon Jan 14 16:20:54 2008 @@ -15,10 +15,6 @@ * `subversion commit mailing list`_ for all updates to code and documentation. -.. _`sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint -.. _`subversion commit mailing list`: http://codespeak.net/mailman/listinfo/pypy-svn -.. _`development mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev - * `development bug/feature tracker`_ for filing bugs and feature requests. * `sprint mailing list`_ for people (interested in) attending upcoming sprints. @@ -41,5 +37,9 @@ .. _`PyPy blog`: http://morepypy.blogspot.com/ .. _`development bug/feature tracker`: https://codespeak.net/issue/pypy-dev/ .. _here: http://tismerysoft.de/pypy/irc-logs/pypy +.. _`sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint +.. _`subversion commit mailing list`: http://codespeak.net/mailman/listinfo/pypy-svn +.. _`development mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev + From hpk at codespeak.net Mon Jan 14 16:26:21 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 14 Jan 2008 16:26:21 +0100 (CET) Subject: [pypy-svn] r50602 - pypy/dist/pypy/doc Message-ID: <20080114152621.15CF039B58F@codespeak.net> Author: hpk Date: Mon Jan 14 16:26:20 2008 New Revision: 50602 Modified: pypy/dist/pypy/doc/home.txt Log: some streamlining, pointing people to FAQ in context of IRC Modified: pypy/dist/pypy/doc/home.txt ============================================================================== --- pypy/dist/pypy/doc/home.txt (original) +++ pypy/dist/pypy/doc/home.txt Mon Jan 14 16:26:20 2008 @@ -8,21 +8,20 @@ Getting into PyPy ... ============================================= -* `PyPy blog`_ for news and status blog about PyPy developments +* `PyPy blog`_: news and status info about PyPy -* `development mailing list`_ for conceptual and coding discussions +* `development mailing list`_: development mailing list. -* `subversion commit mailing list`_ for all updates to code and +* `subversion commit mailing list`_: updates to code and documentation. -* `development bug/feature tracker`_ for filing bugs and feature requests. +* `development bug/feature tracker`_: filing bugs and feature requests. -* `sprint mailing list`_ for people (interested in) attending upcoming sprints. +* `sprint mailing list`_: mailing list for organising upcoming sprints * **IRC channel #pypy on freenode**: Many of the core developers are hanging out - at #pypy on irc.freenode.net. You are welcome to join and ask questions even more - so if you are interested in participating in some parts of the PyPy project. You - can find the logs of the channel here_. + at #pypy on irc.freenode.net. You are welcome to join and ask questions. + Please first checkout the FAQ_. You can find the logs of the channel here_. Meeting PyPy developers @@ -40,6 +39,7 @@ .. _`sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint .. _`subversion commit mailing list`: http://codespeak.net/mailman/listinfo/pypy-svn .. _`development mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev +.. _`FAQ`: faq.html From atobe at codespeak.net Mon Jan 14 16:34:30 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Mon, 14 Jan 2008 16:34:30 +0100 (CET) Subject: [pypy-svn] r50603 - pypy/branch/fixed-list-ootype/pypy/translator/oosupport Message-ID: <20080114153430.B92003180CA@codespeak.net> Author: atobe Date: Mon Jan 14 16:34:30 2008 New Revision: 50603 Modified: pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py pypy/branch/fixed-list-ootype/pypy/translator/oosupport/genoo.py Log: (cfbolz, atobe): In progress. Trying to get support for prebuilt arrays. Modified: pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py Mon Jan 14 16:34:30 2008 @@ -203,6 +203,8 @@ return genoo.ClassConst(self.db, value, uniq) elif isinstance(value, ootype._list): return genoo.ListConst(self.db, value, uniq) + elif isinstance(value, ootype._array): + return genoo.ArrayConst(self.db, value, uniq) elif isinstance(value, ootype._static_meth): return genoo.StaticMethodConst(self.db, value, uniq) elif isinstance(value, ootype._custom_dict): @@ -395,7 +397,7 @@ and any classes that are used are loaded. Called when the constant object is created. """ - raise NotImplementedException + raise NotImplementedError def create_pointer(self, gen): """ @@ -413,7 +415,7 @@ the pointer from the stack in the process; otherwise, a pop is automatically inserted afterwards. """ - raise NotImplementedException + raise NotImplementedError # ____________________________________________________________ # Internal helpers @@ -604,10 +606,6 @@ The default is not to initialize if the list is a list of Void. """ return self.value._TYPE.ITEM is ootype.Void - try: - return self.value._list == [0] * len(self.value._list) - except: - return False def initialize_data(self, constgen, gen): assert not self.is_null() @@ -628,6 +626,56 @@ gen.call_method(SELFTYPE, 'll_setitem_fast') # ______________________________________________________________________ +# Array constants + +class ArrayConst(AbstractConst): + def __init__(self, db, list, count): + AbstractConst.__init__(self, db, list, count) + self.name = 'ARRAY__%d' % count + + def record_dependencies(self): + if not self.value: + return + for item in self.value._array: + self._record_const_if_complex(self.value._TYPE.ITEM, item) + + def create_pointer(self, gen): + from pypy.objspace.flow.model import Constant + assert not self.is_null() + SELFTYPE = self.value._TYPE + + # Create the array + length = Constant(len(self.value._array), ootype.Signed) + gen.oonewarray(SELFTYPE, length) + + def _do_not_initialize(self): + """ Returns True if the array should not be initialized; this + can be overloaded by the backend if your conditions are wider. + The default is not to initialize if the array is a array of + Void. """ + return self.value._TYPE.ITEM is ootype.Void + + def initialize_data(self, constgen, gen): + assert not self.is_null() + SELFTYPE = self.value._TYPE + ITEM = self.value._TYPE.ITEM + + # check for special cases and avoid initialization + if self._do_not_initialize(): + return + + # set each item in the list using the OOTYPE methods + for idx, item in enumerate(self.value._array): + constgen._consider_split_current_function(gen) + gen.dup(SELFTYPE) + push_constant(self.db, ootype.Signed, idx, gen) + push_constant(self.db, ITEM, item, gen) + gen.prepare_generic_argument(ITEM) + gen.call_method(SELFTYPE, 'll_setitem_fast') + print idx, item + + +# ______________________________________________________________________ # Dictionary constants class DictConst(AbstractConst): Modified: pypy/branch/fixed-list-ootype/pypy/translator/oosupport/genoo.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/oosupport/genoo.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/oosupport/genoo.py Mon Jan 14 16:34:30 2008 @@ -22,6 +22,7 @@ RecordConst = ooconst.RecordConst ClassConst = ooconst.ClassConst ListConst = ooconst.ListConst + ArrayConst = ooconst.ArrayConst StaticMethodConst = ooconst.StaticMethodConst CustomDictConst = ooconst.CustomDictConst DictConst = ooconst.DictConst From hpk at codespeak.net Mon Jan 14 16:46:18 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 14 Jan 2008 16:46:18 +0100 (CET) Subject: [pypy-svn] r50604 - pypy/dist/pypy/doc Message-ID: <20080114154618.A5D5416855E@codespeak.net> Author: hpk Date: Mon Jan 14 16:46:17 2008 New Revision: 50604 Modified: pypy/dist/pypy/doc/home.txt Log: adding obligatory documentation and getting-started link. Modified: pypy/dist/pypy/doc/home.txt ============================================================================== --- pypy/dist/pypy/doc/home.txt (original) +++ pypy/dist/pypy/doc/home.txt Mon Jan 14 16:46:17 2008 @@ -8,21 +8,27 @@ Getting into PyPy ... ============================================= -* `PyPy blog`_: news and status info about PyPy +* `PyPy Blog`_: news and status info about PyPy -* `development mailing list`_: development mailing list. +* `Documentation`_: extensive documentation about PyPy. -* `subversion commit mailing list`_: updates to code and +* `Getting Started`_: Getting started and playing with PyPy. + +* `Development mailing list`_: development and conceptual + discussions. + +* `Subversion commit mailing list`_: updates to code and documentation. -* `development bug/feature tracker`_: filing bugs and feature requests. +* `Development bug/feature tracker`_: filing bugs and feature requests. -* `sprint mailing list`_: mailing list for organising upcoming sprints +* `Sprint mailing list`_: mailing list for organising upcoming sprints. * **IRC channel #pypy on freenode**: Many of the core developers are hanging out at #pypy on irc.freenode.net. You are welcome to join and ask questions. - Please first checkout the FAQ_. You can find the logs of the channel here_. + Please first checkout the FAQ_. You can find logs of the channel here_. +.. XXX play1? Meeting PyPy developers ======================= @@ -40,6 +46,5 @@ .. _`subversion commit mailing list`: http://codespeak.net/mailman/listinfo/pypy-svn .. _`development mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev .. _`FAQ`: faq.html - - - +.. _`Documentation`: index.html +.. _`Getting Started`: getting-started.html From atobe at codespeak.net Mon Jan 14 17:25:31 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Mon, 14 Jan 2008 17:25:31 +0100 (CET) Subject: [pypy-svn] r50605 - in pypy/branch/fixed-list-ootype/pypy/translator: jvm oosupport Message-ID: <20080114162531.1B1771684D3@codespeak.net> Author: atobe Date: Mon Jan 14 17:25:29 2008 New Revision: 50605 Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py Log: (cbolz, atobe, antocuni): Fixed problem with arrays in JVM backend. Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py Mon Jan 14 17:25:29 2008 @@ -156,7 +156,7 @@ elif desc == '[B': s = "newarray byte" else: - s = "anewarray" + s = "anewarray " + arraytype.element_type.descriptor self.cache[arraytype] = obj = Opcode(s) return obj Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py Mon Jan 14 17:25:29 2008 @@ -69,8 +69,11 @@ def int_class_name(self): """ Converts a descriptor like Ljava/lang/Object; to internal class name java/lang/Object """ - assert self[0] == 'L' and self[-1] == ';' - return self[1:-1] + if self[0] == 'L' and self[-1] == ';': + return self[1:-1] + else: + assert self.startswith('[') + return self def type_width(self): """ Returns number of JVM words this type takes up. JVM words are a theoretically abstract quantity that basically Modified: pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/oosupport/constant.py Mon Jan 14 17:25:29 2008 @@ -670,7 +670,6 @@ gen.dup(SELFTYPE) push_constant(self.db, ootype.Signed, idx, gen) push_constant(self.db, ITEM, item, gen) - gen.prepare_generic_argument(ITEM) gen.call_method(SELFTYPE, 'll_setitem_fast') print idx, item From xoraxax at codespeak.net Mon Jan 14 18:11:46 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Mon, 14 Jan 2008 18:11:46 +0100 (CET) Subject: [pypy-svn] r50608 - pypy/dist/pypy/rlib Message-ID: <20080114171146.978E0168564@codespeak.net> Author: xoraxax Date: Mon Jan 14 18:11:46 2008 New Revision: 50608 Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py Log: Remove WinSock2.h include here because it also appears in the preinclude lines. Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py ============================================================================== --- pypy/dist/pypy/rlib/_rsocket_rffi.py (original) +++ pypy/dist/pypy/rlib/_rsocket_rffi.py Mon Jan 14 18:11:46 2008 @@ -36,7 +36,7 @@ COND_HEADER = ''.join(['#ifdef %s\n#include <%s>\n#endif\n' % cond_include for cond_include in cond_includes]) if _MS_WINDOWS: - includes = ('WinSock2.h', 'WS2tcpip.h') + includes = () libraries = ('ws2_32',) calling_conv = 'win' HEADER = '\n'.join([ From cfbolz at codespeak.net Mon Jan 14 18:16:20 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 18:16:20 +0100 (CET) Subject: [pypy-svn] r50609 - pypy/branch/fixed-list-ootype/pypy/translator/jvm Message-ID: <20080114171620.EB2A2168566@codespeak.net> Author: cfbolz Date: Mon Jan 14 18:16:19 2008 New Revision: 50609 Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py Log: implement void arrays as just integers (the only information they have is there length) Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/database.py Mon Jan 14 18:16:19 2008 @@ -542,6 +542,7 @@ ootype.Bool : jvmtype.jByteArray, ootype.UniChar : jvmtype.jCharArray, ootype.String : jvmtype.jStringArray, + ootype.Void : jvmtype.jVoidArray, } def _array_type(self, ITEM): Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py Mon Jan 14 18:16:19 2008 @@ -19,7 +19,8 @@ jObject, jByteArray, jPyPyExcWrap, jIntegerClass, jLongClass, \ jDoubleClass, jCharClass, jStringBuilder, JvmScalarType, jArrayList, \ jObjectArray, jPyPyInterlink, jPyPyCustomDict, jPyPyEquals, \ - jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os, jPyPyInterlink + jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os, jPyPyInterlink, \ + jVoidArray # ___________________________________________________________________________ @@ -139,7 +140,10 @@ class NewArrayOpcodeFamily(object): def __init__(self): - self.cache = {} + # a void array is just an int, therefore oonewarray does not need to + # do anything, because it the new can just use the int argument that is + # already on the stack + self.cache = {jVoidArray: None} def for_type(self, arraytype): try: @@ -475,7 +479,32 @@ gen._instr(ARRSTORE.for_type(self.arraytype.element_type)) else: assert 0, "unknown array method" - + +class VoidArrayMethod(ArrayMethod): + def _argtypes(self): + if self.ootype_methodname == "ll_length": + return [] + elif self.ootype_methodname == "ll_getitem_fast": + return [jInt] + elif self.ootype_methodname == "ll_setitem_fast": + return [jInt] + else: + assert 0, "unknown array method" + + def _rettype(self): + if self.ootype_methodname == "ll_length": + return jInt + return jVoid + + def invoke(self, gen): + if self.ootype_methodname == "ll_length": + pass + elif self.ootype_methodname == "ll_getitem_fast": + gen.emit(POP); gen.emit(POP) + elif self.ootype_methodname == "ll_setitem_fast": + gen.emit(POP); gen.emit(POP) + else: + assert 0, "unknown array method" # ___________________________________________________________________________ # Fields @@ -997,6 +1026,9 @@ it is the name of a method to invoke, or an Opcode/Method object (defined above).""" + if instr is None: + return + if isinstance(instr, str): return getattr(self, instr)(*args) Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/typesystem.py Mon Jan 14 18:16:19 2008 @@ -239,6 +239,16 @@ # Arrays don't have methods in Java, but they do in the ootype system from pypy.translator.jvm.generator import ArrayMethod return ArrayMethod(self, methodnm) + +class JvmVoidArrayType(JvmArrayType): + def __init__(self): + JvmType.__init__(self, JvmTypeDescriptor("I")) + self.element_type = jVoid + def lookup_method(self, methodnm): + # Arrays don't have methods in Java, but they do in the ootype system + from pypy.translator.jvm.generator import VoidArrayMethod + return VoidArrayMethod(self, methodnm) + jByteArray = JvmArrayType(jByte) jObjectArray = JvmArrayType(jObject) @@ -246,6 +256,7 @@ jDoubleArray = JvmArrayType(jDouble) jCharArray = JvmArrayType(jChar) jIntArray = JvmArrayType(jInt) +jVoidArray = JvmVoidArrayType() class Generifier(object): From arigo at codespeak.net Mon Jan 14 18:16:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 18:16:30 +0100 (CET) Subject: [pypy-svn] r50610 - in pypy/branch/applevel-ctypes2/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080114171630.AD3F4168571@codespeak.net> Author: arigo Date: Mon Jan 14 18:16:29 2008 New Revision: 50610 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dll.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Log: General hacking and refactoring until more tests pass. It remains to be seen for how long the _CData_input() and _CData_output() abstractions will survive ctypes' complete ad-hoc-ness... Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Mon Jan 14 18:16:29 2008 @@ -1,23 +1,19 @@ -import _ffi +import _rawffi -from _ctypes.basics import _CData, cdata_from_address, _CDataMeta +from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof class ArrayMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) res._ffiletter = 'P' if '_type_' in typedict: - ffiarray = _ffi.Array(typedict['_type_']._ffiletter) + ffiarray = _rawffi.Array(typedict['_type_']._ffiletter) res._ffiarray = ffiarray if typedict['_type_']._type_ == 'c': def getvalue(self): - res = [] - i = 0 - while i < self._length_ and self[i] != '\x00': - res.append(self[i]) - i += 1 - return "".join(res) + return _rawffi.charp2string(self._array.buffer, + self._length_) def setvalue(self, val): # we don't want to have buffers here import ctypes @@ -40,6 +36,9 @@ res._ffiarray = None return res + def _CData_input(self, value): + return self.from_param(value)._array.byptr() + from_address = cdata_from_address class Array(_CData): @@ -50,45 +49,51 @@ for i, arg in enumerate(args): self[i] = arg - def _fix_item(self, item): - if item >= self._length_: + def _fix_index(self, index): + if index < 0: + index += self._length_ + if 0 <= index < self._length_: + return index + else: raise IndexError - if item < 0: - return self._length_ + item - return item - def _get_slice_params(self, item): - if item.step is not None: + def _get_slice_params(self, index): + if index.step is not None: raise TypeError("3 arg slices not supported (for no reason)") - start = item.start or 0 - stop = item.stop or self._length_ + start = index.start or 0 + stop = index.stop or self._length_ return start, stop - def _slice_setitem(self, item, value): - start, stop = self._get_slice_params(item) + def _slice_setitem(self, index, value): + start, stop = self._get_slice_params(index) for i in range(start, stop): self[i] = value[i - start] - def _slice_getitem(self, item): - start, stop = self._get_slice_params(item) + def _slice_getitem(self, index): + start, stop = self._get_slice_params(index) return "".join([self[i] for i in range(start, stop)]) - - def __setitem__(self, item, value): + + def _subarray(self, index): + """Return an _array of length 1 whose address is the same as + the index'th item of self.""" + address = self._array.buffer + address += index * sizeof(self._type_) + return self._ffiarray.fromaddress(address, 1) + + def __setitem__(self, index, value): from ctypes import _SimpleCData - if isinstance(item, slice): - self._slice_setitem(item, value) + if isinstance(index, slice): + self._slice_setitem(index, value) return - value = self._type_.from_param(value).value - item = self._fix_item(item) - if self._type_._ffiletter == 'c' and len(value) > 1: - raise TypeError("Expected strings of length 1") - self._array[item] = value - - def __getitem__(self, item): - if isinstance(item, slice): - return self._slice_getitem(item) - item = self._fix_item(item) - return self._array[item] + value = self._type_._CData_input(value) + index = self._fix_index(index) + self._array[index] = value[0] + + def __getitem__(self, index): + if isinstance(index, slice): + return self._slice_getitem(index) + index = self._fix_index(index) + return self._type_._CData_output(self._subarray(index)) def __len__(self): return self._length_ Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Mon Jan 14 18:16:29 2008 @@ -1,11 +1,34 @@ -import _ffi +import _rawffi class _CDataMeta(type): def from_param(self, value): if isinstance(value, self): return value - raise TypeError("Wrong type") + try: + as_parameter = value._as_parameter_ + except AttributeError: + raise TypeError("expected %s instance instead of %s" % ( + self.__name__, type(value).__name__)) + else: + return self.from_param(as_parameter) + + def _CData_input(self, value): + """Used when data enters into ctypes from user code. 'value' is + some user-specified Python object, which is converted into an + _array of length 1 containing the same value according to the + type 'self'. + """ + return self.from_param(value)._array + + def _CData_output(self, resarray): + """Used when data exits ctypes and goes into user code. + 'resarray' is an _array of length 1 containing the value, + and this returns a general Python object that corresponds. + """ + res = self.__new__(self) + res._array = resarray + return res.__ctypes_from_outparam__() class _CData(object): """ The most basic object for all ctypes types @@ -32,16 +55,14 @@ def sizeof(tp): ffitp = tp._type_ - return _ffi.sizeof(TP_TO_FFITP.get(ffitp, ffitp)) + return _rawffi.sizeof(TP_TO_FFITP.get(ffitp, ffitp)) def alignment(tp): ffitp = tp._type_ - return _ffi.alignment(TP_TO_FFITP.get(ffitp, ffitp)) + return _rawffi.alignment(TP_TO_FFITP.get(ffitp, ffitp)) def byref(cdata): - from ctypes import pointer, _SimpleCData - if not isinstance(cdata, _SimpleCData): - raise TypeError("expected CData instance") + from ctypes import pointer return pointer(cdata) def cdata_from_address(self, address): Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dll.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dll.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/dll.py Mon Jan 14 18:16:29 2008 @@ -1,7 +1,7 @@ -import _ffi +import _rawffi def dlopen(name, mode): # XXX mode is ignored if name is None: return None # XXX seems to mean the cpython lib - return _ffi.CDLL(name) + return _rawffi.CDLL(name) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Mon Jan 14 18:16:29 2008 @@ -1,4 +1,3 @@ -import _ffi from _ctypes.basics import _CData, _CDataMeta @@ -38,9 +37,9 @@ argtypes = self._guess_argtypes(args) restype = self._restype_ funcptr = self._getfuncptr(argtypes, restype) - res = funcptr(*self._wrap_args(argtypes, args)) + resarray = funcptr(*self._wrap_args(argtypes, args)) if restype is not None: - return restype(res).__ctypes_from_outparam__() + return restype._CData_output(resarray) def _getfuncptr(self, argtypes, restype): argletters = [arg._ffiletter for arg in argtypes] @@ -55,5 +54,5 @@ return res def _wrap_args(self, argtypes, args): - return [argtype.from_param(arg)._array[0] for argtype, arg in + return [argtype._CData_input(arg) for argtype, arg in zip(argtypes, args)] Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Mon Jan 14 18:16:29 2008 @@ -1,14 +1,16 @@ -import _ffi +import _rawffi from _ctypes.basics import _CData, _CDataMeta, cdata_from_address +from _ctypes.basics import sizeof, byref +from _ctypes.array import Array DEFAULT_VALUE = object() class PointerType(_CDataMeta): def __new__(self, name, cls, typedict): d = dict( - size = _ffi.sizeof('P'), - align = _ffi.alignment('P'), + size = _rawffi.sizeof('P'), + align = _rawffi.alignment('P'), length = 1, _ffiletter = 'P' ) @@ -18,7 +20,7 @@ for k, v in d.iteritems(): setattr(obj, k, v) if '_type_' in typedict: - ffiarray = _ffi.Array('P') + ffiarray = _rawffi.Array('P') def __init__(self, value=0): self._array = ffiarray(1) self.contents = value @@ -29,6 +31,19 @@ obj.__init__ = __init__ return obj + def from_param(self, value): + if value is None: + return 0 + # If we expect POINTER(), but receive a instance, accept + # it by calling byref(). + if isinstance(value, self._type_): + return byref(value) + # Array instances are also pointers when the item types are the same. + if isinstance(value, Array): + if issubclass(type(value)._type_, self._type_): + return value + return _CDataMeta.from_param(self, value) + from_address = cdata_from_address class _Pointer(_CData): @@ -48,13 +63,19 @@ else: self._array[0] = value._array - def __getitem__(self, item): - assert item == 0 - return self._type_.from_address(self._array[0]).__ctypes_from_outparam__() + def _subarray(self, index=0): + """Return an _array of length 1 whose address is the same as + the index'th item to which self is pointing.""" + address = self._array[0] + address += index * sizeof(self._type_) + return self._type_._ffiarray.fromaddress(address, 1) + + def __getitem__(self, index): + return self._type_._CData_output(self._subarray(index)) - def __setitem__(self, item, value): - if item != 0: + def __setitem__(self, index, value): + if index != 0: raise IndexError - self._type_.from_address(self._array[item]).value = value + self._subarray(index)[0] = self._type_._CData_input(value)[0] contents = property(getcontents, setcontents) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Mon Jan 14 18:16:29 2008 @@ -1,4 +1,4 @@ -import _ffi +import _rawffi SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" @@ -40,10 +40,41 @@ raise ValueError('%s is not a type character' % (tp)) default = TP_TO_DEFAULT[tp] ffitp = TP_TO_FFITP.get(tp, tp) - ffiarray = _ffi.Array(ffitp) + ffiarray = _rawffi.Array(ffitp) result = type.__new__(self, name, bases, dct) result._ffiletter = tp result._ffiarray = ffiarray + if tp == 'z': + # c_char_p special cases + from _ctypes import Array, _Pointer + + def __init__(self, value=DEFAULT_VALUE): + if isinstance(value, str): + array = _rawffi.Array('c')(len(value)+1, value) + value = array.buffer + # XXX free 'array' later + _SimpleCData.__init__(self, value) + result.__init__ = __init__ + + def _getvalue(self): + return _rawffi.charp2string(self._array[0]) + def _setvalue(self, value): + xxx + result.value = property(_getvalue, _setvalue) + + def from_param(self, value): + if value is None: + return None + if isinstance(value, basestring): + return self(value) + if isinstance(value, self): + return value + if isinstance(value, (Array, _Pointer)): + if type(value)._type_ == 'c': + return value + return _SimpleCData.from_param(self, value) + result.from_param = classmethod(from_param) + return result from_address = cdata_from_address @@ -52,9 +83,12 @@ return create_array_type(self, other) def from_param(self, value): - if not isinstance(value, _CData): + if isinstance(value, self): + return value + try: return self(value) - return super(SimpleType, self).from_param(value) + except (TypeError, ValueError): + return super(SimpleType, self).from_param(value) class _SimpleCData(_CData): __metaclass__ = SimpleType @@ -69,15 +103,12 @@ return self._array[0] def _setvalue(self, value): - # XXX - if isinstance(value, _SimpleCData): - self._array[0] = value.value - else: - self._array[0] = value + xxx value = property(_getvalue, _setvalue) + del _getvalue, _setvalue def __ctypes_from_outparam__(self): - return self._array[0] + return self.value def __repr__(self): return "%s(%s)" % (type(self).__name__, self.value) Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_numbers.py Mon Jan 14 18:16:29 2008 @@ -76,11 +76,13 @@ def test_from_param(self): # the from_param class method attribute always # returns PyCArgObject instances + py.test.skip("bogus test") for t in signed_types + unsigned_types + float_types: assert ArgType == type(t.from_param(0)) def test_byref(self): # calling byref returns also a PyCArgObject instance + py.test.skip("bogus test") for t in signed_types + unsigned_types + float_types: parm = byref(t()) assert ArgType == type(parm) Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Mon Jan 14 18:16:29 2008 @@ -124,6 +124,7 @@ ## print p.from_address(addr)[0][0] def test_other(self): + py.test.skip("in-progress") class Table(Structure): _fields_ = [("a", c_int), ("b", c_int), @@ -155,10 +156,62 @@ argv = (c_char_p * 2)() argc = c_int( 2 ) argv[0] = 'hello' + assert argv[0] == 'hello' argv[1] = 'world' result = func( byref(argc), argv ) assert result == 'world', result + def test_charpp2(self): + """Test that a character pointer-to-pointer is correctly passed""" + dll = CDLL(_ctypes_test) + func = dll._testfunc_c_p_p + func.restype = c_char_p + argv = (c_char_p * 2)() + argc = c_int( 2 ) + argv[0] = 'hello' + argv[1] = 'world' + result = func( byref(argc), byref(argv) ) + assert result == 'world', result + + def test_charpp3(self): + """Test that a character pointer-to-pointer is correctly passed""" + dll = CDLL(_ctypes_test) + func = dll._testfunc_c_p_p + func.argtypes = (POINTER(c_int), c_char_p * 2) + func.restype = c_char_p + argv = (c_char_p * 2)() + argc = c_int( 2 ) + argv[0] = 'hello' + argv[1] = 'world' + result = func( byref(argc), argv ) + assert result == 'world', result + + def test_charpp4(self): + """Test that a character pointer-to-pointer is correctly passed""" + dll = CDLL(_ctypes_test) + func = dll._testfunc_c_p_p + func.argtypes = (POINTER(c_int), POINTER(c_char_p * 2)) + func.restype = c_char_p + argv = (c_char_p * 2)() + argc = c_int( 2 ) + argv[0] = 'hello' + argv[1] = 'world' + result = func( byref(argc), argv ) + assert result == 'world', result + + def test_charpp5(self): + """Test that a character pointer-to-pointer is correctly passed""" + dll = CDLL(_ctypes_test) + func = dll._testfunc_c_p_p + func.argtypes = (POINTER(c_int), POINTER(c_char_p * 2)) + func.restype = c_char_p + argv = (c_char_p * 2)() + argc = c_int( 2 ) + argv[0] = 'hello' + argv[1] = 'world' + result = func( byref(argc), byref(argv) ) + assert result == 'world', result + def test_bug_1467852(self): # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 x = c_int(5) From arigo at codespeak.net Mon Jan 14 18:26:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 18:26:38 +0100 (CET) Subject: [pypy-svn] r50611 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080114172638.8D840168565@codespeak.net> Author: arigo Date: Mon Jan 14 18:26:37 2008 New Revision: 50611 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: * support for sizeof() on non-primitives (incomplete). * implement _setvalue for primitives. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Mon Jan 14 18:26:37 2008 @@ -48,18 +48,14 @@ # return "" % (self.ffiletter, self._array[0]) -TP_TO_FFITP = { # XXX this should die; interp_ffi should just accept them - 'O': 'P', - 'z': 's', -} - def sizeof(tp): - ffitp = tp._type_ - return _rawffi.sizeof(TP_TO_FFITP.get(ffitp, ffitp)) + if not isinstance(tp, _CDataMeta): + raise TypeError("ctypes type expected, got %r" % (type(tp).__name__,)) + return tp._sizeofinstances() def alignment(tp): ffitp = tp._type_ - return _rawffi.alignment(TP_TO_FFITP.get(ffitp, ffitp)) + return _rawffi.alignment(ffitp) def byref(cdata): from ctypes import pointer Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Mon Jan 14 18:26:37 2008 @@ -44,6 +44,9 @@ return value return _CDataMeta.from_param(self, value) + def _sizeofinstances(self): + return _rawffi.sizeof('P') + from_address = cdata_from_address class _Pointer(_CData): Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Mon Jan 14 18:26:37 2008 @@ -2,7 +2,7 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" -from _ctypes.basics import _CData, _CDataMeta, cdata_from_address, TP_TO_FFITP +from _ctypes.basics import _CData, _CDataMeta, cdata_from_address from _ctypes.array import create_array_type class NULL(object): @@ -39,8 +39,7 @@ tp not in SIMPLE_TYPE_CHARS): raise ValueError('%s is not a type character' % (tp)) default = TP_TO_DEFAULT[tp] - ffitp = TP_TO_FFITP.get(tp, tp) - ffiarray = _rawffi.Array(ffitp) + ffiarray = _rawffi.Array(tp) result = type.__new__(self, name, bases, dct) result._ffiletter = tp result._ffiarray = ffiarray @@ -48,18 +47,14 @@ # c_char_p special cases from _ctypes import Array, _Pointer - def __init__(self, value=DEFAULT_VALUE): + def _getvalue(self): + return _rawffi.charp2string(self._array[0]) + def _setvalue(self, value): if isinstance(value, str): array = _rawffi.Array('c')(len(value)+1, value) value = array.buffer # XXX free 'array' later - _SimpleCData.__init__(self, value) - result.__init__ = __init__ - - def _getvalue(self): - return _rawffi.charp2string(self._array[0]) - def _setvalue(self, value): - xxx + self._array[0] = value result.value = property(_getvalue, _setvalue) def from_param(self, value): @@ -90,6 +85,9 @@ except (TypeError, ValueError): return super(SimpleType, self).from_param(value) + def _sizeofinstances(self): + return _rawffi.sizeof(self._type_) + class _SimpleCData(_CData): __metaclass__ = SimpleType _type_ = 'i' @@ -97,13 +95,13 @@ def __init__(self, value=DEFAULT_VALUE): self._array = self._ffiarray(1) if value is not DEFAULT_VALUE: - self._array[0] = value + self.value = value def _getvalue(self): return self._array[0] def _setvalue(self, value): - xxx + self._array[0] = value value = property(_getvalue, _setvalue) del _getvalue, _setvalue From arigo at codespeak.net Mon Jan 14 20:07:25 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 14 Jan 2008 20:07:25 +0100 (CET) Subject: [pypy-svn] r50614 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080114190725.967FC168566@codespeak.net> Author: arigo Date: Mon Jan 14 20:07:19 2008 New Revision: 50614 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Log: Tiny clean-ups. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Mon Jan 14 20:07:19 2008 @@ -16,9 +16,8 @@ self._length_) def setvalue(self, val): # we don't want to have buffers here - import ctypes if len(val) > self._length_: - raise ValueError("%s too long" % (val,)) + raise ValueError("%r too long" % (val,)) for i in range(len(val)): self[i] = val[i] if len(val) < self._length_: @@ -81,7 +80,6 @@ return self._ffiarray.fromaddress(address, 1) def __setitem__(self, index, value): - from ctypes import _SimpleCData if isinstance(index, slice): self._slice_setitem(index, value) return From cfbolz at codespeak.net Mon Jan 14 23:03:28 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 23:03:28 +0100 (CET) Subject: [pypy-svn] r50615 - pypy/branch/fixed-list-ootype/pypy/translator/jvm Message-ID: <20080114220328.57E70168572@codespeak.net> Author: cfbolz Date: Mon Jan 14 23:03:26 2008 New Revision: 50615 Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py Log: (antocuni): make even more array tests pass Modified: pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py (original) +++ pypy/branch/fixed-list-ootype/pypy/translator/jvm/generator.py Mon Jan 14 23:03:26 2008 @@ -160,7 +160,7 @@ elif desc == '[B': s = "newarray byte" else: - s = "anewarray " + arraytype.element_type.descriptor + s = "anewarray " + arraytype.element_type.descriptor.int_class_name() self.cache[arraytype] = obj = Opcode(s) return obj From cfbolz at codespeak.net Mon Jan 14 23:04:42 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 14 Jan 2008 23:04:42 +0100 (CET) Subject: [pypy-svn] r50616 - pypy/dist/pypy/doc Message-ID: <20080114220442.186F9168572@codespeak.net> Author: cfbolz Date: Mon Jan 14 23:04:41 2008 New Revision: 50616 Modified: pypy/dist/pypy/doc/getting-started.txt Log: typo Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Mon Jan 14 23:04:41 2008 @@ -574,7 +574,7 @@ `Boehm-Demers-Weiser garbage collector`_ for the translated interpreter. Use ``--gc=generation`` to use our own exact generational implementation which is now faster and doesn't have external dependencies. Otherwise, be -sure io install Boehm before starting the translation (e.g. by running +sure to install Boehm before starting the translation (e.g. by running ``apt-get install libgc-dev`` on Debian or Ubuntu). This whole process will take some time and quite a lot of memory (although it From cfbolz at codespeak.net Tue Jan 15 10:39:05 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 15 Jan 2008 10:39:05 +0100 (CET) Subject: [pypy-svn] r50618 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080115093905.152FA16855C@codespeak.net> Author: cfbolz Date: Tue Jan 15 10:39:04 2008 New Revision: 50618 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: (all): planning for today Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Tue Jan 15 10:39:04 2008 @@ -2,17 +2,17 @@ Task ideas ========== - - try getting debug information in the Java class files (Carl Friedrich, - Paul) DONE + - try getting debug information in the Java class files DONE - - benchmark the size of the young nursery for generational GC (Olivier, - most of Armin) IN-PROGRESS, the result is that picking half the L2 cache + - benchmark the size of the young nursery for generational GC + DONE, the result still is that picking half the L2 cache size for the nursery sounds good - - look at the RPython microbenchmarks for Java (Toby, Armin around) + - look at the RPython microbenchmarks for Java DONE, fixed sized-lists are slow - - work on CTypes (Maciek, Armin) general non-progress + - work on CTypes (Carl Friedrich, Armin) + more general non-progress - think about summarizing test outcomes @@ -23,6 +23,6 @@ working correctly (Anto, Paul) - implement fixed-size lists as arrays in the ootypesystem (Carl Friedrich, - Toby) IN PROGRESS, backend support missing + Toby) IN PROGRESS, jvm backend supported, minor problems From arigo at codespeak.net Tue Jan 15 11:37:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 11:37:58 +0100 (CET) Subject: [pypy-svn] r50619 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115103758.B48A516855A@codespeak.net> Author: arigo Date: Tue Jan 15 11:37:57 2008 New Revision: 50619 Added: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py (contents, props changed) Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Log: (cfbolz, arigo) Fix size and alignment of structures, and expose this information to app-level. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Tue Jan 15 11:37:57 2008 @@ -29,37 +29,49 @@ fields.append((name, code)) return fields -def size_and_pos(fields): - size = intmask(TYPEMAP[fields[0][1]].c_size) - pos = [0] - for i in range(1, len(fields)): +def round_up(size, alignment): + return (size + alignment - 1) & -alignment + +def size_alignment_pos(fields): + size = 0 + alignment = 1 + pos = [] + for i in range(len(fields)): field_desc = TYPEMAP[fields[i][1]] - missing = size % intmask(field_desc.c_alignment) - if missing: - size += intmask(field_desc.c_alignment) - missing + size = round_up(size, intmask(field_desc.c_alignment)) + alignment = max(alignment, intmask(field_desc.c_alignment)) pos.append(size) size += intmask(field_desc.c_size) - return size, pos + size = round_up(size, alignment) + return size, alignment, pos class W_Structure(Wrappable): def __init__(self, space, w_fields): fields = unpack_fields(space, w_fields) - name_to_offset = {} + name_to_index = {} for i in range(len(fields)): name, letter = fields[i] if letter not in TYPEMAP: raise OperationError(space.w_ValueError, space.wrap( "Unkown type letter %s" % (letter,))) - if name in name_to_offset: + if name in name_to_index: raise OperationError(space.w_ValueError, space.wrap( "duplicate field name %s" % (name, ))) - name_to_offset[name] = i - size, pos = size_and_pos(fields) + name_to_index[name] = i + size, alignment, pos = size_alignment_pos(fields) self.size = size + self.alignment = alignment self.ll_positions = pos self.fields = fields - self.name_to_offset = name_to_offset + self.name_to_index = name_to_index + + def getindex(self, space, attr): + try: + return self.name_to_index[attr] + except KeyError: + raise OperationError(space.w_AttributeError, space.wrap( + "C Structure has no attribute %s" % attr)) def descr_call(self, space, __args__): args_w, kwargs_w = __args__.unpack() @@ -68,20 +80,28 @@ space.w_TypeError, space.wrap("Structure accepts only keyword arguments as field initializers")) return space.wrap(W_StructureInstance(space, self, 0, kwargs_w)) + descr_call.unwrap_spec = ['self', ObjSpace, Arguments] def fromaddress(self, space, address): return space.wrap(W_StructureInstance(space, self, address, None)) fromaddress.unwrap_spec = ['self', ObjSpace, int] + def descr_getfieldoffset(self, space, attr): + index = self.getindex(space, attr) + return space.wrap(self.ll_positions[index]) + descr_getfieldoffset.unwrap_spec = ['self', ObjSpace, str] + def descr_new_structure(space, w_type, w_fields): return space.wrap(W_Structure(space, w_fields)) W_Structure.typedef = TypeDef( 'Structure', __new__ = interp2app(descr_new_structure), - __call__ = interp2app(W_Structure.descr_call, - unwrap_spec=['self', ObjSpace, Arguments]), - fromaddress = interp2app(W_Structure.fromaddress) + __call__ = interp2app(W_Structure.descr_call), + fromaddress = interp2app(W_Structure.fromaddress), + size = interp_attrproperty('size', W_Structure), + alignment = interp_attrproperty('alignment', W_Structure), + getfieldoffset = interp2app(W_Structure.descr_getfieldoffset), ) W_Structure.typedef.acceptable_as_base_class = False @@ -106,18 +126,10 @@ for field, w_value in fieldinits_w.iteritems(): self.setattr(space, field, w_value) - - def getindex(self, space, attr): - try: - return self.shape.name_to_offset[attr] - except KeyError: - raise OperationError(space.w_AttributeError, space.wrap( - "C Structure has no attribute %s" % attr)) - def getattr(self, space, attr): if not self.ll_buffer: raise segfault_exception(space, "accessing NULL pointer") - i = self.getindex(space, attr) + i = self.shape.getindex(space, attr) _, c = self.shape.fields[i] return wrap_value(space, cast_pos, self, i, c) getattr.unwrap_spec = ['self', ObjSpace, str] @@ -125,7 +137,7 @@ def setattr(self, space, attr, w_value): if not self.ll_buffer: raise segfault_exception(space, "accessing NULL pointer") - i = self.getindex(space, attr) + i = self.shape.getindex(space, attr) _, c = self.shape.fields[i] unwrap_value(space, push_field, self, i, c, w_value) setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] Added: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py ============================================================================== --- (empty file) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Tue Jan 15 11:37:57 2008 @@ -0,0 +1,25 @@ +from pypy.conftest import gettestobjspace +import os, sys, py + +def setup_module(mod): + if sys.platform != 'linux2': + py.test.skip("Linux only tests by now") + +class AppTestNested: + def setup_class(cls): + space = gettestobjspace(usemodules=('_rawffi','struct')) + cls.space = space + + def test_inspect_structure(self): + import _rawffi, struct + align = max(struct.calcsize("i"), struct.calcsize("P")) + assert align & (align-1) == 0, "not a power of 2??" + def round_up(x): + return (x+align-1) & -align + + S = _rawffi.Structure([('a', 'i'), ('b', 'P'), ('c', 'c')]) + assert S.size == round_up(struct.calcsize("iPc")) + assert S.alignment == align + assert S.getfieldoffset('a') == 0 + assert S.getfieldoffset('b') == align + assert S.getfieldoffset('c') == round_up(struct.calcsize("iP")) Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Tue Jan 15 11:37:57 2008 @@ -1,7 +1,7 @@ -from pypy.module._rawffi.structure import size_and_pos +from pypy.module._rawffi.structure import size_alignment_pos, TYPEMAP -sizeof = lambda x : size_and_pos(x)[0] +sizeof = lambda x : size_alignment_pos(x)[0] def unpack(desc): return [('x', i) for i in desc] @@ -10,8 +10,14 @@ s_c = sizeof(unpack('c')) s_l = sizeof(unpack('l')) s_q = sizeof(unpack('q')) + alignment_of_q = TYPEMAP['q'].c_alignment + assert alignment_of_q >= 4 assert sizeof(unpack('cl')) == 2*s_l - assert sizeof(unpack('cq')) == s_q + s_l - assert sizeof(unpack('ccq')) == s_q + s_l - assert sizeof(unpack('ccccq')) == 4 * s_c + s_q - + assert sizeof(unpack('cq')) == alignment_of_q + s_q + assert sizeof(unpack('ccq')) == alignment_of_q + s_q + assert sizeof(unpack('cccq')) == alignment_of_q + s_q + assert sizeof(unpack('ccccq')) == alignment_of_q + s_q + assert sizeof(unpack('qc')) == s_q + alignment_of_q + assert sizeof(unpack('qcc')) == s_q + alignment_of_q + assert sizeof(unpack('qccc')) == s_q + alignment_of_q + assert sizeof(unpack('qcccc')) == s_q + alignment_of_q From pdg at codespeak.net Tue Jan 15 12:07:55 2008 From: pdg at codespeak.net (pdg at codespeak.net) Date: Tue, 15 Jan 2008 12:07:55 +0100 (CET) Subject: [pypy-svn] r50620 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080115110755.47A7A168553@codespeak.net> Author: pdg Date: Tue Jan 15 12:07:54 2008 New Revision: 50620 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_interp_clr.py Log: (antocuni, pdg) Fixed lazy import tests Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Tue Jan 15 12:07:54 2008 @@ -14,7 +14,7 @@ receive a second argument, which is None for a top-level module, or package.__path__ for submodules or subpackages - It should return a loader object if the module was found, or None if it wasn't. + It should return a loader object if the module was found, or None if it wasn\'t. If find_module() raises an exception, the caller will abort the import. When importer.find_module("spam.eggs.ham") is called, "spam.eggs" has already been imported and added to sys.modules. @@ -50,7 +50,7 @@ C The __name__ attribute must be set. If one uses imp.new_module() then the attribute is set automatically. - D If it's a package, the __path__ variable must be set. This must + D If it\'s a package, the __path__ variable must be set. This must be a list, but may be empty if __path__ has no further significance to the importer (more on this later). Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Tue Jan 15 12:07:54 2008 @@ -194,16 +194,21 @@ Return: List of Valid .NET namespaces """ - listOfNamespaces = [] + namespaces = {} currentDomain = System.AppDomain.get_CurrentDomain() assems = currentDomain.GetAssemblies() for loadedAssembly in assems: typesInAssembly = loadedAssembly.GetTypes() for type in typesInAssembly: namespace = type.get_Namespace() - if namespace != None and namespace not in listOfNamespaces: - listOfNamespaces.append(namespace) - w_listOfNamespaces = wrap_list_of_strings(space, listOfNamespaces) + if namespace != None: + chunks = namespace.split(".") + temp_name = chunks[0] + namespaces[temp_name] = None + for chunk in chunks[1:]: + temp_name += "."+chunk + namespaces[temp_name] = None + w_listOfNamespaces = wrap_list_of_strings(space, namespaces.keys()) return w_listOfNamespaces def list_of_generic_classes(space): Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Tue Jan 15 12:07:54 2008 @@ -5,6 +5,15 @@ space = gettestobjspace(usemodules=('clr', )) cls.space = space + def test_list_of_valid_namespaces(self): + import clr + ns = clr.list_of_valid_namespaces() + + assert 'System' in ns + assert 'System.Collections' in ns + assert 'System.Runtime' in ns + assert 'System.Runtime.InteropServices' in ns + def test_import_hook_simple(self): import clr import System.Math @@ -41,4 +50,4 @@ def test_lazy_import(self): import System - System.Xml.Schema # does not raise attribute error + System.Runtime.InteropServices # does not raise attribute error Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_interp_clr.py Tue Jan 15 12:07:54 2008 @@ -7,3 +7,4 @@ assert split('System.Foo.Bar') == ('System.Foo', 'Bar') assert split('System.Foo.A+B') == ('System.Foo', 'A+B') assert split('System.') == ('System', '') + From pdg at codespeak.net Tue Jan 15 12:13:02 2008 From: pdg at codespeak.net (pdg at codespeak.net) Date: Tue, 15 Jan 2008 12:13:02 +0100 (CET) Subject: [pypy-svn] r50621 - pypy/branch/clr-module-improvements/pypy/translator/cli Message-ID: <20080115111302.59911168550@codespeak.net> Author: pdg Date: Tue Jan 15 12:13:01 2008 New Revision: 50621 Modified: pypy/branch/clr-module-improvements/pypy/translator/cli/support.py Log: (antocuni, pdg) changed pythonnet1 CLR to pythonnet2 clr for the import Modified: pypy/branch/clr-module-improvements/pypy/translator/cli/support.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/translator/cli/support.py (original) +++ pypy/branch/clr-module-improvements/pypy/translator/cli/support.py Tue Jan 15 12:13:01 2008 @@ -7,7 +7,7 @@ py.log.setconsumer("cli", ansi_log) try: - import CLR as PythonNet + import clr as PythonNet PythonNet.System.Reflection.Assembly.LoadFile(Support.get()) except ImportError: class _PythonNet: From arigo at codespeak.net Tue Jan 15 12:41:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 12:41:50 +0100 (CET) Subject: [pypy-svn] r50622 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115114150.7C70E1683EA@codespeak.net> Author: arigo Date: Tue Jan 15 12:41:48 2008 New Revision: 50622 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Log: (cfbolz, fijal, arigo) Support nested structures inside other structures. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py Tue Jan 15 12:41:48 2008 @@ -16,7 +16,6 @@ 'StructureInstance' : 'structure.W_StructureInstance', 'Array' : 'array.W_Array', 'ArrayInstance' : 'array.W_ArrayInstance', - '_get_type' : 'interp_rawffi._w_get_type', 'sizeof' : 'interp_rawffi.sizeof', 'alignment' : 'interp_rawffi.alignment', 'charp2string' : 'interp_rawffi.charp2string', Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Tue Jan 15 12:41:48 2008 @@ -11,8 +11,8 @@ from pypy.interpreter.error import OperationError, wrap_oserror from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataInstance -from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value, _get_type,\ - TYPEMAP +from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value +from pypy.module._rawffi.interp_rawffi import unpack_typecode, letter2tp from pypy.rlib.rarithmetic import intmask def push_elem(ll_array, pos, value): @@ -27,10 +27,10 @@ get_elem._annspecialcase_ = 'specialize:arg(2)' class W_Array(Wrappable): - def __init__(self, space, of): + def __init__(self, space, itemtp): + assert isinstance(itemtp, tuple) self.space = space - self.of = of - self.itemsize = intmask(TYPEMAP[of].c_size) + self.itemtp = itemtp def allocate(self, space, length): return W_ArrayInstance(space, self, length) @@ -46,8 +46,8 @@ " array length")) for num in range(iterlength): w_item = items_w[num] - unwrap_value(space, push_elem, result.ll_buffer, num, self.of, - w_item) + unwrap_value(space, push_elem, result.ll_buffer, num, + self.itemtp, w_item) return space.wrap(result) def fromaddress(self, space, address, length): @@ -58,27 +58,28 @@ def __init__(self, space): self.space = space self.cache = {} - self.array_of_ptr = self.get_array_type('P') + self.array_of_ptr = self.get_array_type(letter2tp(space, 'P')) - def get_array_type(self, of): + def get_array_type(self, itemtp): try: - return self.cache[of] + return self.cache[itemtp] except KeyError: - _get_type(self.space, of) - result = W_Array(self.space, of) - self.cache[of] = result + result = W_Array(self.space, itemtp) + self.cache[itemtp] = result return result def get_array_cache(space): return space.fromcache(ArrayCache) -def descr_new_array(space, w_type, of): - array_type = get_array_cache(space).get_array_type(of) +def descr_new_array(space, w_type, w_itemtp): + itemtp = unpack_typecode(space, w_itemtp) + array_type = get_array_cache(space).get_array_type(itemtp) return space.wrap(array_type) W_Array.typedef = TypeDef( 'Array', - __new__ = interp2app(descr_new_array, unwrap_spec=[ObjSpace, W_Root, str]), + __new__ = interp2app(descr_new_array, + unwrap_spec=[ObjSpace, W_Root, W_Root]), __call__ = interp2app(W_Array.descr_call, unwrap_spec=['self', ObjSpace, int, W_Root]), fromaddress = interp2app(W_Array.fromaddress), @@ -89,7 +90,8 @@ class W_ArrayInstance(W_DataInstance): def __init__(self, space, shape, length, address=0): - W_DataInstance.__init__(self, space, shape.itemsize * length, address) + _, itemsize, _ = shape.itemtp + W_DataInstance.__init__(self, space, itemsize * length, address) self.length = length self.shape = shape @@ -98,14 +100,15 @@ def setitem(self, space, num, w_value): if num >= self.length or num < 0: raise OperationError(space.w_IndexError, space.w_None) - unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.of, + unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.itemtp, w_value) setitem.unwrap_spec = ['self', ObjSpace, int, W_Root] def getitem(self, space, num): if num >= self.length or num < 0: raise OperationError(space.w_IndexError, space.w_None) - return wrap_value(space, get_elem, self.ll_buffer, num, self.shape.of) + return wrap_value(space, get_elem, self.ll_buffer, num, + self.shape.itemtp) getitem.unwrap_spec = ['self', ObjSpace, int] W_ArrayInstance.typedef = TypeDef( Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Tue Jan 15 12:41:48 2008 @@ -12,6 +12,7 @@ from pypy.module.struct.standardfmttable import min_max_acc_method from pypy.module.struct.nativefmttable import native_fmttable from pypy.tool.sourcetools import func_with_new_name +from pypy.rlib.rarithmetic import intmask class FfiValueError(Exception): def __init__(self, msg): @@ -54,6 +55,11 @@ } TYPEMAP_PTR_LETTERS = "POsz" +UNPACKED_TYPECODES = dict([(code, (code, + intmask(field_desc.c_size), + intmask(field_desc.c_alignment))) + for code, field_desc in TYPEMAP.items()]) + LL_TYPEMAP = { 'c' : rffi.CHAR, 'b' : rffi.SIGNEDCHAR, @@ -75,18 +81,19 @@ 'v' : lltype.Void, } -def _get_type(space, key): +def letter2tp(space, key): try: - return TYPEMAP[key] + return UNPACKED_TYPECODES[key] except KeyError: raise OperationError(space.w_ValueError, space.wrap( "Unknown type letter %s" % (key,))) - return lltype.nullptr(FFI_TYPE_P.TO) -def _w_get_type(space, key): - _get_type(space, key) - return space.w_None -_w_get_type.unwrap_spec = [ObjSpace, str] +def _get_type_(space, key): + try: + return TYPEMAP[key] + except KeyError: + raise OperationError(space.w_ValueError, space.wrap( + "Unknown type letter %s" % (key,))) class W_CDLL(Wrappable): def __init__(self, space, name): @@ -97,7 +104,7 @@ def get_type(self, key): space = self.space - return _get_type(space, key) + return _get_type_(space, key) def ptr(self, space, name, w_argtypes, w_restype): """ Get a pointer for function name with provided argtypes @@ -188,6 +195,14 @@ w_exception = space.getattr(w_mod, space.wrap("SegfaultException")) return OperationError(w_exception, space.wrap(reason)) +def unpack_typecode(space, w_typecode): + if space.is_true(space.isinstance(w_typecode, space.w_str)): + letter = space.str_w(w_typecode) + return letter2tp(space, letter) + else: + w_size, w_align = space.unpacktuple(w_typecode, expected_length=2) + return ('?', space.int_w(w_size), space.int_w(w_align)) + class W_DataInstance(Wrappable): def __init__(self, space, size, address=0): @@ -217,20 +232,21 @@ def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg): + letter, _, _ = tp w = space.wrap - if tp == "d": + if letter == "d": push_func(add_arg, argdesc, space.float_w(w_arg)) - elif tp == "f": + elif letter == "f": push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT, space.float_w(w_arg))) - elif tp in TYPEMAP_PTR_LETTERS: + elif letter in TYPEMAP_PTR_LETTERS: # check for NULL ptr if space.is_true(space.isinstance(w_arg, space.w_int)): push_func(add_arg, argdesc, rffi.cast(rffi.VOIDP, space.int_w(w_arg))) else: datainstance = space.interp_w(W_DataInstance, w_arg) push_func(add_arg, argdesc, datainstance.ll_buffer) - elif tp == "c": + elif letter == "c": s = space.str_w(w_arg) if len(s) != 1: raise OperationError(space.w_TypeError, w( @@ -239,7 +255,7 @@ push_func(add_arg, argdesc, val) else: for c, checker in unroll_size_checkers: - if tp == c: + if letter == c: if c == "q": val = space.r_longlong_w(w_arg) elif c == "Q": @@ -254,14 +270,18 @@ raise OperationError(space.w_ValueError, w(e.msg)) TP = LL_TYPEMAP[c] push_func(add_arg, argdesc, rffi.cast(TP, val)) - + return + else: + raise OperationError(space.w_TypeError, + space.wrap("cannot directly write value")) unwrap_value._annspecialcase_ = 'specialize:arg(1)' ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items()) def wrap_value(space, func, add_arg, argdesc, tp): + letter, _, _ = tp for c, ll_type in ll_typemap_iter: - if tp == c: + if letter == c: if c in TYPEMAP_PTR_LETTERS: res = func(add_arg, argdesc, rffi.VOIDP) return space.wrap(rffi.cast(lltype.Signed, res)) @@ -277,7 +297,8 @@ ll_type))) else: return space.wrap(intmask(func(add_arg, argdesc, ll_type))) - return space.w_None + raise OperationError(space.w_TypeError, + space.wrap("cannot directly read value")) wrap_value._annspecialcase_ = 'specialize:arg(1)' class W_FuncPtr(Wrappable): @@ -286,7 +307,7 @@ self.ptr = ptr if restype != 'v': cache = get_array_cache(space) - self.resarray = cache.get_array_type(restype) + self.resarray = cache.get_array_type(letter2tp(space, restype)) else: self.resarray = None self.argtypes = argtypes @@ -307,9 +328,9 @@ msg = ("Argument %d should be an array of length 1, " "got length %d" % (i+1, arg.length)) raise OperationError(space.w_TypeError, space.wrap(msg)) - if arg.shape.of != argtype: + if arg.shape.itemtp[0] != argtype: msg = "Argument %d should be typecode %s, got %s" % ( - i+1, argtype, arg.shape.of) + i+1, argtype, arg.shape.itemtp[0]) raise OperationError(space.w_TypeError, space.wrap(msg)) args_ll.append(arg.ll_buffer) # XXX we could avoid the intermediate list args_ll Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Tue Jan 15 12:41:48 2008 @@ -12,8 +12,8 @@ from pypy.interpreter.error import OperationError, wrap_oserror from pypy.module._rawffi.interp_rawffi import segfault_exception from pypy.module._rawffi.interp_rawffi import W_DataInstance -from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value, _get_type,\ - TYPEMAP +from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value +from pypy.module._rawffi.interp_rawffi import unpack_typecode from pypy.rlib.rarithmetic import intmask def unpack_fields(space, w_fields): @@ -24,9 +24,9 @@ if not len(l_w) == 2: raise OperationError(space.w_ValueError, space.wrap( "Expected list of 2-size tuples")) - name, code = space.str_w(l_w[0]), space.str_w(l_w[1]) - _get_type(space, code) # be paranoid about types - fields.append((name, code)) + name = space.str_w(l_w[0]) + tp = unpack_typecode(space, l_w[1]) + fields.append((name, tp)) return fields def round_up(size, alignment): @@ -36,12 +36,11 @@ size = 0 alignment = 1 pos = [] - for i in range(len(fields)): - field_desc = TYPEMAP[fields[i][1]] - size = round_up(size, intmask(field_desc.c_alignment)) - alignment = max(alignment, intmask(field_desc.c_alignment)) + for fieldname, (letter, fieldsize, fieldalignment) in fields: + size = round_up(size, fieldalignment) + alignment = max(alignment, fieldalignment) pos.append(size) - size += intmask(field_desc.c_size) + size += intmask(fieldsize) size = round_up(size, alignment) return size, alignment, pos @@ -51,10 +50,7 @@ fields = unpack_fields(space, w_fields) name_to_index = {} for i in range(len(fields)): - name, letter = fields[i] - if letter not in TYPEMAP: - raise OperationError(space.w_ValueError, space.wrap( - "Unkown type letter %s" % (letter,))) + name, tp = fields[i] if name in name_to_index: raise OperationError(space.w_ValueError, space.wrap( "duplicate field name %s" % (name, ))) @@ -91,6 +87,11 @@ return space.wrap(self.ll_positions[index]) descr_getfieldoffset.unwrap_spec = ['self', ObjSpace, str] + def descr_gettypecode(self, space): + return space.newtuple([space.wrap(self.size), + space.wrap(self.alignment)]) + descr_gettypecode.unwrap_spec = ['self', ObjSpace] + def descr_new_structure(space, w_type, w_fields): return space.wrap(W_Structure(space, w_fields)) @@ -102,6 +103,7 @@ size = interp_attrproperty('size', W_Structure), alignment = interp_attrproperty('alignment', W_Structure), getfieldoffset = interp2app(W_Structure.descr_getfieldoffset), + gettypecode = interp2app(W_Structure.descr_gettypecode), ) W_Structure.typedef.acceptable_as_base_class = False @@ -130,18 +132,24 @@ if not self.ll_buffer: raise segfault_exception(space, "accessing NULL pointer") i = self.shape.getindex(space, attr) - _, c = self.shape.fields[i] - return wrap_value(space, cast_pos, self, i, c) + _, tp = self.shape.fields[i] + return wrap_value(space, cast_pos, self, i, tp) getattr.unwrap_spec = ['self', ObjSpace, str] def setattr(self, space, attr, w_value): if not self.ll_buffer: raise segfault_exception(space, "accessing NULL pointer") i = self.shape.getindex(space, attr) - _, c = self.shape.fields[i] - unwrap_value(space, push_field, self, i, c, w_value) + _, tp = self.shape.fields[i] + unwrap_value(space, push_field, self, i, tp, w_value) setattr.unwrap_spec = ['self', ObjSpace, str, W_Root] + def descr_fieldaddress(self, space, attr): + i = self.shape.getindex(space, attr) + ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i]) + return space.wrap(rffi.cast(lltype.Signed, ptr)) + descr_fieldaddress.unwrap_spec = ['self', ObjSpace, str] + W_StructureInstance.typedef = TypeDef( 'StructureInstance', @@ -151,6 +159,7 @@ free = interp2app(W_StructureInstance.free), shape = interp_attrproperty('shape', W_StructureInstance), byptr = interp2app(W_StructureInstance.byptr), + fieldaddress= interp2app(W_StructureInstance.descr_fieldaddress), ) W_StructureInstance.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Tue Jan 15 12:41:48 2008 @@ -23,3 +23,23 @@ assert S.getfieldoffset('a') == 0 assert S.getfieldoffset('b') == align assert S.getfieldoffset('c') == round_up(struct.calcsize("iP")) + assert S.gettypecode() == (S.size, S.alignment) + + def test_nested_structures(self): + import _rawffi + S1 = _rawffi.Structure([('a', 'i'), ('b', 'P'), ('c', 'c')]) + S = _rawffi.Structure([('x', 'c'), ('s1', S1.gettypecode())]) + assert S.size == S1.alignment + S1.size + assert S.alignment == S1.alignment + assert S.getfieldoffset('x') == 0 + assert S.getfieldoffset('s1') == S1.alignment + s = S() + s.x = 'G' + raises(TypeError, 's.s1') + assert s.fieldaddress('s1') == s.buffer + S.getfieldoffset('s1') + s1 = S1.fromaddress(s.fieldaddress('s1')) + s1.c = 'H' + rawbuf = _rawffi.Array('c').fromaddress(s.buffer, S.size) + assert rawbuf[0] == 'G' + assert rawbuf[S1.alignment + S1.getfieldoffset('c')] == 'H' + s.free() Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Tue Jan 15 12:41:48 2008 @@ -1,10 +1,11 @@ -from pypy.module._rawffi.structure import size_alignment_pos, TYPEMAP +from pypy.module._rawffi.structure import size_alignment_pos +from pypy.module._rawffi.interp_rawffi import TYPEMAP, letter2tp sizeof = lambda x : size_alignment_pos(x)[0] def unpack(desc): - return [('x', i) for i in desc] + return [('x', letter2tp('space', i)) for i in desc] def test_sizeof(): s_c = sizeof(unpack('c')) From arigo at codespeak.net Tue Jan 15 12:51:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 12:51:58 +0100 (CET) Subject: [pypy-svn] r50623 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115115158.C4BC816854D@codespeak.net> Author: arigo Date: Tue Jan 15 12:51:57 2008 New Revision: 50623 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Log: (fijal, cfbolz, arigo) Arrays of structures. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Tue Jan 15 12:51:57 2008 @@ -111,13 +111,25 @@ self.shape.itemtp) getitem.unwrap_spec = ['self', ObjSpace, int] + def getlength(self, space): + return space.wrap(self.length) + getlength.unwrap_spec = ['self', ObjSpace] + + def descr_itemaddress(self, space, num): + _, itemsize, _ = self.shape.itemtp + ptr = rffi.ptradd(self.ll_buffer, itemsize * num) + return space.wrap(rffi.cast(lltype.Signed, ptr)) + descr_itemaddress.unwrap_spec = ['self', ObjSpace, int] + W_ArrayInstance.typedef = TypeDef( 'ArrayInstance', __setitem__ = interp2app(W_ArrayInstance.setitem), __getitem__ = interp2app(W_ArrayInstance.getitem), + __len__ = interp2app(W_ArrayInstance.getlength), buffer = GetSetProperty(W_ArrayInstance.getbuffer), shape = interp_attrproperty('shape', W_ArrayInstance), free = interp2app(W_ArrayInstance.free), byptr = interp2app(W_ArrayInstance.byptr), + itemaddress = interp2app(W_ArrayInstance.descr_itemaddress), ) W_ArrayInstance.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Tue Jan 15 12:51:57 2008 @@ -82,10 +82,10 @@ return space.wrap(W_StructureInstance(space, self, address, None)) fromaddress.unwrap_spec = ['self', ObjSpace, int] - def descr_getfieldoffset(self, space, attr): + def descr_fieldoffset(self, space, attr): index = self.getindex(space, attr) return space.wrap(self.ll_positions[index]) - descr_getfieldoffset.unwrap_spec = ['self', ObjSpace, str] + descr_fieldoffset.unwrap_spec = ['self', ObjSpace, str] def descr_gettypecode(self, space): return space.newtuple([space.wrap(self.size), @@ -98,11 +98,11 @@ W_Structure.typedef = TypeDef( 'Structure', __new__ = interp2app(descr_new_structure), - __call__ = interp2app(W_Structure.descr_call), + __call__ = interp2app(W_Structure.descr_call), fromaddress = interp2app(W_Structure.fromaddress), size = interp_attrproperty('size', W_Structure), alignment = interp_attrproperty('alignment', W_Structure), - getfieldoffset = interp2app(W_Structure.descr_getfieldoffset), + fieldoffset = interp2app(W_Structure.descr_fieldoffset), gettypecode = interp2app(W_Structure.descr_gettypecode), ) W_Structure.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Tue Jan 15 12:51:57 2008 @@ -20,9 +20,9 @@ S = _rawffi.Structure([('a', 'i'), ('b', 'P'), ('c', 'c')]) assert S.size == round_up(struct.calcsize("iPc")) assert S.alignment == align - assert S.getfieldoffset('a') == 0 - assert S.getfieldoffset('b') == align - assert S.getfieldoffset('c') == round_up(struct.calcsize("iP")) + assert S.fieldoffset('a') == 0 + assert S.fieldoffset('b') == align + assert S.fieldoffset('c') == round_up(struct.calcsize("iP")) assert S.gettypecode() == (S.size, S.alignment) def test_nested_structures(self): @@ -31,15 +31,35 @@ S = _rawffi.Structure([('x', 'c'), ('s1', S1.gettypecode())]) assert S.size == S1.alignment + S1.size assert S.alignment == S1.alignment - assert S.getfieldoffset('x') == 0 - assert S.getfieldoffset('s1') == S1.alignment + assert S.fieldoffset('x') == 0 + assert S.fieldoffset('s1') == S1.alignment s = S() s.x = 'G' raises(TypeError, 's.s1') - assert s.fieldaddress('s1') == s.buffer + S.getfieldoffset('s1') + assert s.fieldaddress('s1') == s.buffer + S.fieldoffset('s1') s1 = S1.fromaddress(s.fieldaddress('s1')) s1.c = 'H' rawbuf = _rawffi.Array('c').fromaddress(s.buffer, S.size) assert rawbuf[0] == 'G' - assert rawbuf[S1.alignment + S1.getfieldoffset('c')] == 'H' + assert rawbuf[S1.alignment + S1.fieldoffset('c')] == 'H' s.free() + + def test_array_of_structures(self): + import _rawffi + S = _rawffi.Structure([('a', 'i'), ('b', 'P'), ('c', 'c')]) + A = _rawffi.Array(S.gettypecode()) + a = A(3) + raises(TypeError, "a[0]") + s0 = S.fromaddress(a.buffer) + s0.c = 'B' + assert a.itemaddress(1) == a.buffer + S.size + s1 = S.fromaddress(a.itemaddress(1)) + s1.c = 'A' + s2 = S.fromaddress(a.itemaddress(2)) + s2.c = 'Z' + rawbuf = _rawffi.Array('c').fromaddress(a.buffer, S.size * len(a)) + ofs = S.fieldoffset('c') + assert rawbuf[0*S.size+ofs] == 'B' + assert rawbuf[1*S.size+ofs] == 'A' + assert rawbuf[2*S.size+ofs] == 'Z' + a.free() From arigo at codespeak.net Tue Jan 15 13:00:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 13:00:10 +0100 (CET) Subject: [pypy-svn] r50624 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115120010.3CCFC1684DB@codespeak.net> Author: arigo Date: Tue Jan 15 13:00:09 2008 New Revision: 50624 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Log: (fijal, arigo) Array of arrays. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Tue Jan 15 13:00:09 2008 @@ -54,6 +54,12 @@ return space.wrap(W_ArrayInstance(space, self, length, address)) fromaddress.unwrap_spec = ['self', ObjSpace, int, int] + def descr_gettypecode(self, space, length): + _, itemsize, alignment = self.itemtp + return space.newtuple([space.wrap(itemsize * length), + space.wrap(alignment)]) + descr_gettypecode.unwrap_spec = ['self', ObjSpace, int] + class ArrayCache: def __init__(self, space): self.space = space @@ -83,7 +89,7 @@ __call__ = interp2app(W_Array.descr_call, unwrap_spec=['self', ObjSpace, int, W_Root]), fromaddress = interp2app(W_Array.fromaddress), - of = interp_attrproperty('of', W_Array), + gettypecode = interp2app(W_Array.descr_gettypecode), ) W_Array.typedef.acceptable_as_base_class = False Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Tue Jan 15 13:00:09 2008 @@ -63,3 +63,23 @@ assert rawbuf[1*S.size+ofs] == 'A' assert rawbuf[2*S.size+ofs] == 'Z' a.free() + + def test_array_of_array(self): + import _rawffi, struct + B = _rawffi.Array('i') + sizeofint = struct.calcsize("i") + assert B.gettypecode(100) == (sizeofint * 100, sizeofint) + A = _rawffi.Array(B.gettypecode(4)) + a = A(2) + b0 = B.fromaddress(a.itemaddress(0), 4) + b0[0] = 3 + b0[3] = 7 + b1 = B.fromaddress(a.itemaddress(1), 4) + b1[0] = 13 + b1[3] = 17 + rawbuf = _rawffi.Array('i').fromaddress(a.buffer, 2 * 4) + assert rawbuf[0] == 3 + assert rawbuf[3] == 7 + assert rawbuf[4] == 13 + assert rawbuf[7] == 17 + a.free() From arigo at codespeak.net Tue Jan 15 13:14:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 13:14:55 +0100 (CET) Subject: [pypy-svn] r50625 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115121455.41F241684F0@codespeak.net> Author: arigo Date: Tue Jan 15 13:14:52 2008 New Revision: 50625 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: (fijal, arigo) Some nice __repr__'s. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Tue Jan 15 13:14:52 2008 @@ -50,6 +50,10 @@ self.itemtp, w_item) return space.wrap(result) + def descr_repr(self, space): + return space.wrap("<_rawffi.Array '%s' (%d, %d)>" % self.itemtp) + descr_repr.unwrap_spec = ['self', ObjSpace] + def fromaddress(self, space, address, length): return space.wrap(W_ArrayInstance(space, self, length, address)) fromaddress.unwrap_spec = ['self', ObjSpace, int, int] @@ -88,6 +92,7 @@ unwrap_spec=[ObjSpace, W_Root, W_Root]), __call__ = interp2app(W_Array.descr_call, unwrap_spec=['self', ObjSpace, int, W_Root]), + __repr__ = interp2app(W_Array.descr_repr), fromaddress = interp2app(W_Array.fromaddress), gettypecode = interp2app(W_Array.descr_gettypecode), ) @@ -101,6 +106,12 @@ self.length = length self.shape = shape + def descr_repr(self, space): + addr = rffi.cast(lltype.Signed, self.ll_buffer) + return space.wrap("<_rawffi array %d of length %d>" % (addr, + self.length)) + descr_repr.unwrap_spec = ['self', ObjSpace] + # XXX don't allow negative indexes, nor slices def setitem(self, space, num, w_value): @@ -129,6 +140,7 @@ W_ArrayInstance.typedef = TypeDef( 'ArrayInstance', + __repr__ = interp2app(W_ArrayInstance.descr_repr), __setitem__ = interp2app(W_ArrayInstance.setitem), __getitem__ = interp2app(W_ArrayInstance.getitem), __len__ = interp2app(W_ArrayInstance.getlength), Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Tue Jan 15 13:14:52 2008 @@ -78,6 +78,13 @@ return space.wrap(W_StructureInstance(space, self, 0, kwargs_w)) descr_call.unwrap_spec = ['self', ObjSpace, Arguments] + def descr_repr(self, space): + fieldnames = ' '.join(["'%s'" % name for name, _ in self.fields]) + return space.wrap("<_rawffi.Structure %s (%d, %d)>" % (fieldnames, + self.size, + self.alignment)) + descr_repr.unwrap_spec = ['self', ObjSpace] + def fromaddress(self, space, address): return space.wrap(W_StructureInstance(space, self, address, None)) fromaddress.unwrap_spec = ['self', ObjSpace, int] @@ -99,6 +106,7 @@ 'Structure', __new__ = interp2app(descr_new_structure), __call__ = interp2app(W_Structure.descr_call), + __repr__ = interp2app(W_Structure.descr_repr), fromaddress = interp2app(W_Structure.fromaddress), size = interp_attrproperty('size', W_Structure), alignment = interp_attrproperty('alignment', W_Structure), @@ -128,6 +136,11 @@ for field, w_value in fieldinits_w.iteritems(): self.setattr(space, field, w_value) + def descr_repr(self, space): + addr = rffi.cast(lltype.Signed, self.ll_buffer) + return space.wrap("<_rawffi struct %d>" % (addr,)) + descr_repr.unwrap_spec = ['self', ObjSpace] + def getattr(self, space, attr): if not self.ll_buffer: raise segfault_exception(space, "accessing NULL pointer") @@ -153,6 +166,7 @@ W_StructureInstance.typedef = TypeDef( 'StructureInstance', + __repr__ = interp2app(W_StructureInstance.descr_repr), __getattr__ = interp2app(W_StructureInstance.getattr), __setattr__ = interp2app(W_StructureInstance.setattr), buffer = GetSetProperty(W_StructureInstance.getbuffer), Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Tue Jan 15 13:14:52 2008 @@ -438,3 +438,20 @@ arg1.free() arg2.free() a.free() + + def test_repr(self): + import _rawffi, struct + s = struct.calcsize("i") + assert (repr(_rawffi.Array('i')) == + "<_rawffi.Array 'i' (%d, %d)>" % (s, s)) + assert repr(_rawffi.Array((18, 2))) == "<_rawffi.Array '?' (18, 2)>" + assert (repr(_rawffi.Structure([('x', 'i'), ('yz', 'i')])) == + "<_rawffi.Structure 'x' 'yz' (%d, %d)>" % (2*s, s)) + + s = _rawffi.Structure([('x', 'i'), ('yz', 'i')])() + assert repr(s) == "<_rawffi struct %d>" % (s.buffer,) + s.free() + a = _rawffi.Array('i')(5) + assert repr(a) == "<_rawffi array %d of length %d>" % (a.buffer, + len(a)) + a.free() From pdg at codespeak.net Tue Jan 15 13:26:59 2008 From: pdg at codespeak.net (pdg at codespeak.net) Date: Tue, 15 Jan 2008 13:26:59 +0100 (CET) Subject: [pypy-svn] r50626 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080115122659.10C071684F0@codespeak.net> Author: pdg Date: Tue Jan 15 13:26:58 2008 New Revision: 50626 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Log: (antocuni, pdg) fixed importing of generic classes. Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Tue Jan 15 13:26:58 2008 @@ -14,8 +14,8 @@ '_CliObject_internal': 'interp_clr.W_CliObject', 'call_staticmethod': 'interp_clr.call_staticmethod', 'load_cli_class': 'interp_clr.load_cli_class', - 'list_of_valid_namespaces': 'interp_clr.list_of_valid_namespaces', - 'list_of_generic_classes': 'interp_clr.list_of_generic_classes', + 'get_extra_type_info': 'interp_clr.get_extra_type_info', + #'list_of_generic_classes': 'interp_clr.list_of_generic_classes', 'isDotNetType': 'interp_clr.isDotNetType', 'load_assembly': 'interp_clr.load_assembly', 'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies', Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Tue Jan 15 13:26:58 2008 @@ -22,12 +22,14 @@ def __init__(self): import clr # this might not be the correct place to load the valid NameSpaces - self.valid_name_spaces = set(clr.list_of_valid_namespaces()) + valid_namespaces, generic_mappings = clr.get_extra_type_info() + self.valid_namespaces = set(valid_namespaces) + self.generic_mappings = dict(generic_mappings) def find_module(self, fullname, path=None): # check for true NAMESPACE or .NET TYPE import clr - if fullname in self.valid_name_spaces or clr.isDotNetType(fullname): + if fullname in self.valid_namespaces or fullname in self.generic_mappings or clr.isDotNetType(fullname): # fullname is a .Net Module return self else: @@ -59,16 +61,16 @@ ''' # If it is a call for a Class then return with the Class reference import clr - if clr.isDotNetType(fullname): + if clr.isDotNetType(fullname) or fullname in self.generic_mappings: ''' Task is to breakup System.Collections.ArrayList and call clr.load_cli_class('System.Collections','ArrayList') ''' + fullname = self.generic_mappings.get(fullname, fullname) rindex = fullname.rfind('.') if rindex != -1: leftStr = fullname[:rindex] rightStr = fullname[rindex+1:] sys.modules[fullname] = clr.load_cli_class(leftStr, rightStr) - else: # if not a call for actual class (say for namespaces) assign an empty module if fullname not in sys.modules: mod = CLRModule(fullname) @@ -86,10 +88,10 @@ # treating System.Collections.Generic specially here. # this treatment is done after the empty module insertion - if fullname == "System.Collections.Generic": - genericClassList = clr.list_of_generic_classes() - for genericClass in genericClassList: - sys.modules[genericClass[: genericClass.find('`')]] = clr.load_cli_class("System.Collections.Generic", genericClass) + #if fullname == "System.Collections.Generic": + # genericClassList = clr.list_of_generic_classes() + # for genericClass in genericClassList: + # sys.modules[genericClass[: genericClass.find('`')]] = clr.load_cli_class("System.Collections.Generic", genericClass) return sys.modules[fullname] Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Tue Jan 15 13:26:58 2008 @@ -127,6 +127,13 @@ list_w.append(space.newtuple(items_w)) return space.newlist(list_w) +def wrap_list_of_pairs(space, lst): + list_w = [] + for (a,b) in lst: + items_w = [space.wrap(a), space.wrap(b)] + list_w.append(space.newtuple(items_w)) + return space.newlist(list_w) + def wrap_list_of_strings(space, lst): list_w = [space.wrap(s) for s in lst] return space.newlist(list_w) @@ -185,7 +192,7 @@ return self.cache.get(fullname, None) CliClassCache = _CliClassCache() -def list_of_valid_namespaces(space): +def get_extra_type_info(space): """ We use this function to play with reflection and then return useful data to the app_importer module @@ -195,6 +202,7 @@ Return: List of Valid .NET namespaces """ namespaces = {} + generics = [] currentDomain = System.AppDomain.get_CurrentDomain() assems = currentDomain.GetAssemblies() for loadedAssembly in assems: @@ -208,38 +216,44 @@ for chunk in chunks[1:]: temp_name += "."+chunk namespaces[temp_name] = None + if type.get_IsGenericType(): + fullname = type.get_FullName() + index = fullname.rfind("`") + assert index != -1 + generics.append((fullname[0:index], fullname)) w_listOfNamespaces = wrap_list_of_strings(space, namespaces.keys()) - return w_listOfNamespaces + w_generic_mappings = wrap_list_of_pairs(space, generics) + return space.newtuple([w_listOfNamespaces, w_generic_mappings]) -def list_of_generic_classes(space): - """ - use reflection to get a list of generic classes - - Return: List of generic classes - e.g. [Dictionary`2 , List`1 , IEnumerator`1 , IEnumerable`1] - """ - listOfGenericTypes = [] - currentDomain = System.AppDomain.get_CurrentDomain() - assems = currentDomain.GetAssemblies() - for loadedAssembly in assems: - typesInAssembly = loadedAssembly.GetTypes() - for type in typesInAssembly: - namespace = type.get_Namespace() - type_str = type.ToString() - if namespace == "System.Collections.Generic": - rightDot = type_str.rfind('.') - rightTilde = type_str.rfind('`') - firstSqBracket = type_str.find('[') - firstPlus = type_str.find('+') - if rightDot != -1 and rightTilde != -1: - if firstPlus == -1: - nameToPush = type_str[rightDot+1 : firstSqBracket] - else: - nameToPush = type_str[rightDot+1 : firstPlus] - if nameToPush not in listOfGenericTypes: - listOfGenericTypes.append(nameToPush) - w_listOfGenericTypes = wrap_list_of_strings(space, listOfGenericTypes) - return w_listOfGenericTypes +#def list_of_generic_classes(space): +# """ +# use reflection to get a list of generic classes +# +# Return: List of generic classes +# e.g. [Dictionary`2 , List`1 , IEnumerator`1 , IEnumerable`1] +# """ +# listOfGenericTypes = [] +# currentDomain = System.AppDomain.get_CurrentDomain() +# assems = currentDomain.GetAssemblies() +# for loadedAssembly in assems: +# typesInAssembly = loadedAssembly.GetTypes() +# for type in typesInAssembly: +# namespace = type.get_Namespace() +# type_str = type.ToString() +# if namespace == "System.Collections.Generic": +# rightDot = type_str.rfind('.') +# rightTilde = type_str.rfind('`') +# firstSqBracket = type_str.find('[') +# firstPlus = type_str.find('+') +# if rightDot != -1 and rightTilde != -1: +# if firstPlus == -1: +# nameToPush = type_str[rightDot+1 : firstSqBracket] +# else: +# nameToPush = type_str[rightDot+1 : firstPlus] +# if nameToPush not in listOfGenericTypes: +# listOfGenericTypes.append(nameToPush) +# w_listOfGenericTypes = wrap_list_of_strings(space, listOfGenericTypes) +# return w_listOfGenericTypes def isDotNetType(space, nameFromImporter): """ Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Tue Jan 15 13:26:58 2008 @@ -7,7 +7,7 @@ def test_list_of_valid_namespaces(self): import clr - ns = clr.list_of_valid_namespaces() + ns, gen = clr.get_extra_type_info() assert 'System' in ns assert 'System.Collections' in ns @@ -51,3 +51,7 @@ def test_lazy_import(self): import System System.Runtime.InteropServices # does not raise attribute error + + def test_generic_class_import(self): + import System.Collections.Generic.List + From arigo at codespeak.net Tue Jan 15 15:05:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 15:05:36 +0100 (CET) Subject: [pypy-svn] r50627 - in pypy/branch/applevel-ctypes2/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080115140536.4726216856D@codespeak.net> Author: arigo Date: Tue Jan 15 15:05:34 2008 New Revision: 50627 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_extra.py pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Log: (fijal, arigo) * update test_extra. * add an array test in test_extra. * implement the basics of Structure. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Tue Jan 15 15:05:34 2008 @@ -75,8 +75,7 @@ def _subarray(self, index): """Return an _array of length 1 whose address is the same as the index'th item of self.""" - address = self._array.buffer - address += index * sizeof(self._type_) + address = self._array.itemaddress(index) return self._ffiarray.fromaddress(address, 1) def __setitem__(self, index, value): Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Tue Jan 15 15:05:34 2008 @@ -34,7 +34,10 @@ """ The most basic object for all ctypes types """ __metaclass__ = _CDataMeta - + + def __init__(self, *args, **kwds): + raise TypeError("%s has no type" % (type(self),)) + def __ctypes_from_outparam__(self): return self Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Tue Jan 15 15:05:34 2008 @@ -25,10 +25,7 @@ self._array = ffiarray(1) self.contents = value obj._ffiarray = ffiarray - else: - def __init__(self, value=0): - raise TypeError("%s has no type" % obj) - obj.__init__ = __init__ + obj.__init__ = __init__ return obj def from_param(self, value): Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Tue Jan 15 15:05:34 2008 @@ -1,9 +1,58 @@ +import _rawffi from _ctypes.basics import _CData, _CDataMeta class StructureMeta(_CDataMeta): def __new__(self, name, cls, typedict): - return type.__new__(self, name, cls, typedict) + res = type.__new__(self, name, cls, typedict) + if '_fields_' in typedict: + names = [name for name, ctype in typedict['_fields_']] + res._fieldtypes = dict(typedict['_fields_']) + rawfields = [(name, ctype._ffiletter) + for name, ctype in typedict['_fields_']] + ffistruct = _rawffi.Structure(rawfields) + res._ffistruct = ffistruct + + def __init__(self, *args, **kwds): + self.__dict__['_struct'] = ffistruct() + if len(args) > len(names): + raise TypeError("too many arguments") + for name, arg in zip(names, args): + if name in kwds: + raise TypeError("duplicate value for argument %r" % ( + name,)) + self.__setattr__(name, arg) + for name, arg in kwds.items(): + self.__setattr__(name, arg) + res.__init__ = __init__ + + return res + + def _CData_input(self, value): + return self.from_param(value)._struct.byptr() + class Structure(_CData): __metaclass__ = StructureMeta + + def _subarray(self, fieldtype, name): + """Return an _array of length 1 whose address is the same as + the address of the field 'name' of self.""" + address = self._struct.fieldaddress(name) + A = _rawffi.Array(fieldtype._ffiletter) + return A.fromaddress(address, 1) + + def __setattr__(self, name, value): + try: + fieldtype = self._fieldtypes[name] + except KeyError: + raise AttributeError(name) + value = fieldtype._CData_input(value) + self._struct.__setattr__(name, value[0]) + + def __getattr__(self, name): + try: + fieldtype = self._fieldtypes[name] + except KeyError: + raise AttributeError(name) + return fieldtype._CData_output(self._subarray(fieldtype, name)) Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_extra.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_extra.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_extra.py Tue Jan 15 15:05:34 2008 @@ -90,6 +90,21 @@ assert s.x == 17 assert s.p.contents.value == -33 +def test_ptr_array(): + a = (POINTER(c_ushort) * 5)() + x = c_ushort(52) + y = c_ushort(1000) + + a[2] = pointer(x) + assert a[2].contents.value == 52 + a[2].contents.value += 1 + assert x.value == 53 + + a[3].contents = y + assert a[3].contents.value == 1000 + a[3].contents.value += 1 + assert y.value == 1001 + def test_void_p(): x = c_int(12) p1 = cast(pointer(x), c_void_p) @@ -165,35 +180,6 @@ assert not c_void_p() -def test_py_object(): - class TAG: - pass - x = py_object(TAG) - assert x.value is TAG - x.value = 42 - assert x.value == 42 - -def test_pythonapi(): - PyInt_AsLong = pythonapi.PyInt_AsLong - PyInt_AsLong.argtypes = [py_object] - PyInt_AsLong.restype = c_long - assert PyInt_AsLong(py_object(17L)) == 17 - py.test.raises(TypeError, "PyInt_AsLong(py_object('hello'))") - -def test_py_object_subclass(): - PyInt_FromLong = pythonapi.PyInt_FromLong - # automatic unwrapping of the py_object result - PyInt_FromLong.argtypes = [c_long] - PyInt_FromLong.restype = py_object - assert isinstance(PyInt_FromLong(17), int) - - # but not if we subclass it... - class W_Object(py_object): - pass - PyInt_FromLong.argtypes = [c_long] - PyInt_FromLong.restype = W_Object - assert isinstance(PyInt_FromLong(17), W_Object) - def test_sizeof(): x = create_string_buffer(117) assert sizeof(x) == 117 # assumes that chars are one byte each @@ -201,23 +187,26 @@ assert sizeof(x) == 42 * sizeof(c_int) def test_convert_pointers(): - PyString_FromString = pythonapi.PyString_FromString - PyString_FromString.restype = py_object + import conftest + _ctypes_test = str(conftest.sofile) + dll = CDLL(_ctypes_test) + func = dll._testfunc_p_p + func.restype = c_char_p # automatic conversions to c_char_p - PyString_FromString.argtypes = [c_char_p] - assert PyString_FromString("hello") == "hello" - assert PyString_FromString(c_char_p("hello")) == "hello" - assert PyString_FromString((c_char * 6)(*"hello")) == "hello" - assert PyString_FromString(create_string_buffer("hello")) == "hello" + func.argtypes = [c_char_p] + assert func("hello") == "hello" + assert func(c_char_p("hello")) == "hello" + assert func((c_char * 6)(*"hello")) == "hello" + assert func(create_string_buffer("hello")) == "hello" # automatic conversions to c_void_p - PyString_FromString.argtypes = [c_void_p] - assert PyString_FromString("hello") == "hello" - assert PyString_FromString(c_char_p("hello")) == "hello" - assert PyString_FromString((c_char * 6)(*"hello")) == "hello" - assert PyString_FromString((c_byte * 6)(104,101,108,108,111)) =="hello" - assert PyString_FromString(create_string_buffer("hello")) == "hello" + func.argtypes = [c_void_p] + assert func("hello") == "hello" + assert func(c_char_p("hello")) == "hello" + assert func((c_char * 6)(*"hello")) == "hello" + assert func((c_byte * 6)(104,101,108,108,111)) =="hello" + assert func(create_string_buffer("hello")) == "hello" def test_varsize_cast(): import struct Modified: pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/app_test/ctypes/test_pointers.py Tue Jan 15 15:05:34 2008 @@ -124,7 +124,6 @@ ## print p.from_address(addr)[0][0] def test_other(self): - py.test.skip("in-progress") class Table(Structure): _fields_ = [("a", c_int), ("b", c_int), From arigo at codespeak.net Tue Jan 15 15:12:16 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 15:12:16 +0100 (CET) Subject: [pypy-svn] r50628 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080115141216.84B73168422@codespeak.net> Author: arigo Date: Tue Jan 15 15:12:15 2008 New Revision: 50628 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Log: Revert this. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Tue Jan 15 15:12:15 2008 @@ -25,7 +25,10 @@ self._array = ffiarray(1) self.contents = value obj._ffiarray = ffiarray - obj.__init__ = __init__ + else: + def __init__(self, value=0): + raise TypeError("%s has no type" % obj) + obj.__init__ = __init__ return obj def from_param(self, value): From hpk at codespeak.net Tue Jan 15 15:19:26 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 15 Jan 2008 15:19:26 +0100 (CET) Subject: [pypy-svn] r50629 - pypy/dist/pypy/doc Message-ID: <20080115141926.BD018168422@codespeak.net> Author: hpk Date: Tue Jan 15 15:19:23 2008 New Revision: 50629 Added: pypy/dist/pypy/doc/contact.html pypy/dist/pypy/doc/news.html pypy/dist/pypy/doc/old_news.txt - copied unchanged from r50603, pypy/dist/pypy/doc/news.txt Removed: pypy/dist/pypy/doc/contact.txt pypy/dist/pypy/doc/news.txt Modified: pypy/dist/pypy/doc/confrest.py pypy/dist/pypy/doc/faq.txt pypy/dist/pypy/doc/getting-started.txt pypy/dist/pypy/doc/project-ideas.txt Log: major update to codespeak'S PyPy site structure * home.txt/html new entry point with main links * no contact.txt (subsumed and streamline into home.txt) * no news.txt (instead there is the external "blog" now) * news.html and contact.html redirect to home.html * various fixes of links, removal of cruft information Modified: pypy/dist/pypy/doc/confrest.py ============================================================================== --- pypy/dist/pypy/doc/confrest.py (original) +++ pypy/dist/pypy/doc/confrest.py Tue Jan 15 15:19:23 2008 @@ -4,22 +4,25 @@ class PyPyPage(Page): def fill_menubar(self): self.menubar = html.div( - html.a("news", - href="http://codespeak.net/pypy/dist/pypy/doc/news.html", - class_="menu"), " ", + html.a("home", + href=self.get_doclink("home.html"), + class_="menu"), + " ", html.a("blog", href="http://morepypy.blogspot.com", class_="menu"), + " ", html.a("getting-started", href=self.get_doclink("getting-started.html"), - class_="menu"), " ", + class_="menu"), + " ", html.a("documentation", href=self.get_doclink("index.html"), - class_="menu"), " ", + class_="menu"), + " ", html.a("svn", href="https://codespeak.net/viewvc/pypy/dist/", - class_="menu"), " ", + class_="menu"), + " ", html.a("issues", href="https://codespeak.net/issue/pypy-dev/", class_="menu"), - html.a("contact", href=self.get_doclink("contact.html"), - class_="menu"), " ", " ", id="menubar") def get_doclink(self, target): Added: pypy/dist/pypy/doc/contact.html ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/contact.html Tue Jan 15 15:19:23 2008 @@ -0,0 +1,17 @@ + + + + + + + + +

+ you should be automatically redirected to + + http://codespeak.net/pypy/dist/pypy/doc/home.html +

+ + + Modified: pypy/dist/pypy/doc/faq.txt ============================================================================== --- pypy/dist/pypy/doc/faq.txt (original) +++ pypy/dist/pypy/doc/faq.txt Tue Jan 15 15:19:23 2008 @@ -197,8 +197,8 @@ discussions. .. _`project suggestions`: project-ideas.html -.. _`contact us`: contact.html -.. _`mailing list`: contact.html +.. _`contact us`: home.html +.. _`mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev ---------------------------------------------------------------------- I am getting strange errors while playing with PyPy, what should I do? Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Tue Jan 15 15:19:23 2008 @@ -844,7 +844,7 @@ .. _events: http://codespeak.net/pypy/dist/pypy/doc/news.html .. _`pypy-dev mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev -.. _`contact possibilities`: contact.html +.. _`contact possibilities`: home.html .. _`py library`: http://codespeak.net/py .. _`PyPy/LLVM backend`: translation.html#llvm @@ -878,7 +878,7 @@ .. _trace: ../../pypy/objspace/trace.py .. _flow: ../../pypy/objspace/flow/ .. _translator.py: ../../pypy/translator/translator.py -.. _mailing lists: contact.html +.. _mailing lists: home.html .. _documentation: index.html .. _unit tests: coding-guide.html#test-design .. _bug reports: https://codespeak.net/issue/pypy-dev/ Added: pypy/dist/pypy/doc/news.html ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/news.html Tue Jan 15 15:19:23 2008 @@ -0,0 +1,17 @@ + + + + + + + + +

+ you should be automatically redirected to + + http://codespeak.net/pypy/dist/pypy/doc/home.html +

+ + + Modified: pypy/dist/pypy/doc/project-ideas.txt ============================================================================== --- pypy/dist/pypy/doc/project-ideas.txt (original) +++ pypy/dist/pypy/doc/project-ideas.txt Tue Jan 15 15:19:23 2008 @@ -9,7 +9,7 @@ with. Feel free to suggest new ideas and discuss them in #pypy on the freenode IRC -network or the pypy-dev mailing list (see the contact_ page). +network or the pypy-dev mailing list (see the home_ page). ----------- @@ -194,7 +194,7 @@ .. _`code templating solution`: http://codespeak.net/svn/pypy/extradoc/soc-2006/code-templating.txt .. _documentation: index.html -.. _contact: contact.html +.. _home: home.html .. _`pypy-dev mailing list`: http://codespeak.net/mailman/listinfo/pypy-dev .. _`Summer of PyPy`: summer-of-pypy.html .. _`ZODB's Persistent class`: http://www.zope.org/Documentation/Books/ZDG/current/Persistence.stx From hpk at codespeak.net Tue Jan 15 15:24:26 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 15 Jan 2008 15:24:26 +0100 (CET) Subject: [pypy-svn] r50630 - pypy/dist/pypy/doc/weekly Message-ID: <20080115142426.27056168422@codespeak.net> Author: hpk Date: Tue Jan 15 15:24:24 2008 New Revision: 50630 Removed: pypy/dist/pypy/doc/weekly/ Log: remove 2005/2006 weekly news, does not really make sense to keep it - please revive it (maybe to some extradoc/ place) if you disagree. From arigo at codespeak.net Tue Jan 15 15:30:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 15:30:04 +0100 (CET) Subject: [pypy-svn] r50631 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080115143004.3352B16856F@codespeak.net> Author: arigo Date: Tue Jan 15 15:29:59 2008 New Revision: 50631 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Log: (fijal, arigo) Some general progress. More tests pass. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Tue Jan 15 15:29:59 2008 @@ -12,7 +12,7 @@ res._ffiarray = ffiarray if typedict['_type_']._type_ == 'c': def getvalue(self): - return _rawffi.charp2string(self._array.buffer, + return _rawffi.charp2string(self._buffer.buffer, self._length_) def setvalue(self, val): # we don't want to have buffers here @@ -36,7 +36,7 @@ return res def _CData_input(self, value): - return self.from_param(value)._array.byptr() + return self.from_param(value)._buffer.byptr() from_address = cdata_from_address @@ -44,7 +44,7 @@ __metaclass__ = ArrayMeta def __init__(self, *args): - self._array = self._ffiarray(self._length_) + self._buffer = self._ffiarray(self._length_) for i, arg in enumerate(args): self[i] = arg @@ -73,9 +73,9 @@ return "".join([self[i] for i in range(start, stop)]) def _subarray(self, index): - """Return an _array of length 1 whose address is the same as + """Return a _rawffi array of length 1 whose address is the same as the index'th item of self.""" - address = self._array.itemaddress(index) + address = self._buffer.itemaddress(index) return self._ffiarray.fromaddress(address, 1) def __setitem__(self, index, value): @@ -84,7 +84,7 @@ return value = self._type_._CData_input(value) index = self._fix_index(index) - self._array[index] = value[0] + self._buffer[index] = value[0] def __getitem__(self, index): if isinstance(index, slice): Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Tue Jan 15 15:29:59 2008 @@ -15,21 +15,25 @@ def _CData_input(self, value): """Used when data enters into ctypes from user code. 'value' is - some user-specified Python object, which is converted into an - _array of length 1 containing the same value according to the + some user-specified Python object, which is converted into a _rawffi + array of length 1 containing the same value according to the type 'self'. """ - return self.from_param(value)._array + return self.from_param(value)._buffer def _CData_output(self, resarray): """Used when data exits ctypes and goes into user code. - 'resarray' is an _array of length 1 containing the value, + 'resarray' is a _rawffi array of length 1 containing the value, and this returns a general Python object that corresponds. """ res = self.__new__(self) - res._array = resarray + res._buffer = resarray return res.__ctypes_from_outparam__() + def __mul__(self, other): + from _ctypes.array import create_array_type + return create_array_type(self, other) + class _CData(object): """ The most basic object for all ctypes types """ @@ -53,7 +57,11 @@ def sizeof(tp): if not isinstance(tp, _CDataMeta): - raise TypeError("ctypes type expected, got %r" % (type(tp).__name__,)) + if isinstance(tp, _CData): + tp = type(tp) + else: + raise TypeError("ctypes type or instance expected, got %r" % ( + type(tp).__name__,)) return tp._sizeofinstances() def alignment(tp): @@ -67,9 +75,8 @@ def cdata_from_address(self, address): instance = self.__new__(self) lgt = getattr(self, '_length_', 1) - instance._array = self._ffiarray.fromaddress(address, lgt) + instance._buffer = self._ffiarray.fromaddress(address, lgt) return instance def addressof(tp): - # XXX we should have a method on each.. - return tp._array.buffer + return tp._buffer.buffer Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Tue Jan 15 15:29:59 2008 @@ -22,7 +22,7 @@ if '_type_' in typedict: ffiarray = _rawffi.Array('P') def __init__(self, value=0): - self._array = ffiarray(1) + self._buffer = ffiarray(1) self.contents = value obj._ffiarray = ffiarray else: @@ -52,24 +52,19 @@ class _Pointer(_CData): __metaclass__ = PointerType - def getvalue(self): - return self._array - - value = property(getvalue) - def getcontents(self): - return self._type_.from_address(self._array[0]) + return self._type_.from_address(self._buffer[0]) def setcontents(self, value): - if isinstance(value, int): - self._array[0] = value - else: - self._array[0] = value._array + if not isinstance(value, self._type_): + raise TypeError("expected %s instead of %s" % ( + self._type_.__name__, type(value).__name__)) + self._buffer[0] = value._buffer def _subarray(self, index=0): - """Return an _array of length 1 whose address is the same as + """Return a _rawffi array of length 1 whose address is the same as the index'th item to which self is pointing.""" - address = self._array[0] + address = self._buffer[0] address += index * sizeof(self._type_) return self._type_._ffiarray.fromaddress(address, 1) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Tue Jan 15 15:29:59 2008 @@ -3,7 +3,6 @@ SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" from _ctypes.basics import _CData, _CDataMeta, cdata_from_address -from _ctypes.array import create_array_type class NULL(object): pass @@ -48,13 +47,13 @@ from _ctypes import Array, _Pointer def _getvalue(self): - return _rawffi.charp2string(self._array[0]) + return _rawffi.charp2string(self._buffer[0]) def _setvalue(self, value): if isinstance(value, str): array = _rawffi.Array('c')(len(value)+1, value) value = array.buffer # XXX free 'array' later - self._array[0] = value + self._buffer[0] = value result.value = property(_getvalue, _setvalue) def from_param(self, value): @@ -74,9 +73,6 @@ from_address = cdata_from_address - def __mul__(self, other): - return create_array_type(self, other) - def from_param(self, value): if isinstance(value, self): return value @@ -93,15 +89,15 @@ _type_ = 'i' def __init__(self, value=DEFAULT_VALUE): - self._array = self._ffiarray(1) + self._buffer = self._ffiarray(1) if value is not DEFAULT_VALUE: self.value = value def _getvalue(self): - return self._array[0] + return self._buffer[0] def _setvalue(self, value): - self._array[0] = value + self._buffer[0] = value value = property(_getvalue, _setvalue) del _getvalue, _setvalue Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Tue Jan 15 15:29:59 2008 @@ -14,7 +14,7 @@ res._ffistruct = ffistruct def __init__(self, *args, **kwds): - self.__dict__['_struct'] = ffistruct() + self.__dict__['_buffer'] = ffistruct() if len(args) > len(names): raise TypeError("too many arguments") for name, arg in zip(names, args): @@ -29,16 +29,21 @@ return res def _CData_input(self, value): - return self.from_param(value)._struct.byptr() + return self.from_param(value)._buffer.byptr() + + def from_address(self, address): + instance = self.__new__(self) + instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) + return instance class Structure(_CData): __metaclass__ = StructureMeta def _subarray(self, fieldtype, name): - """Return an _array of length 1 whose address is the same as + """Return a _rawffi array of length 1 whose address is the same as the address of the field 'name' of self.""" - address = self._struct.fieldaddress(name) + address = self._buffer.fieldaddress(name) A = _rawffi.Array(fieldtype._ffiletter) return A.fromaddress(address, 1) @@ -48,7 +53,7 @@ except KeyError: raise AttributeError(name) value = fieldtype._CData_input(value) - self._struct.__setattr__(name, value[0]) + self._buffer.__setattr__(name, value[0]) def __getattr__(self, name): try: From xoraxax at codespeak.net Tue Jan 15 16:39:51 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Tue, 15 Jan 2008 16:39:51 +0100 (CET) Subject: [pypy-svn] r50632 - pypy/dist/pypy/translator/c/src Message-ID: <20080115153951.146E3168564@codespeak.net> Author: xoraxax Date: Tue Jan 15 16:39:51 2008 New Revision: 50632 Modified: pypy/dist/pypy/translator/c/src/stack.h Log: Move an include line to try to mitigate the header mess. Modified: pypy/dist/pypy/translator/c/src/stack.h ============================================================================== --- pypy/dist/pypy/translator/c/src/stack.h (original) +++ pypy/dist/pypy/translator/c/src/stack.h Tue Jan 15 16:39:51 2008 @@ -6,6 +6,10 @@ # define MAX_STACK_SIZE (1 << 19) #endif +/* This include must be done in any case to initialise + * the header dependencies early (thread -> winsock2, before windows.h) */ +#include "thread.h" + void LL_stack_unwind(void); int LL_stack_too_big_slowpath(void); @@ -28,9 +32,9 @@ && LL_stack_too_big_slowpath()); } + #ifndef PYPY_NOT_MAIN_FILE #include -#include "thread.h" #ifndef PYPY_NOINLINE # if defined __GNUC__ From arigo at codespeak.net Tue Jan 15 16:41:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 16:41:30 +0100 (CET) Subject: [pypy-svn] r50633 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080115154130.AACB2168564@codespeak.net> Author: arigo Date: Tue Jan 15 16:41:30 2008 New Revision: 50633 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Log: (fijal, arigo) As usual - rewrite some core logic once again, and more tests pass. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Tue Jan 15 16:41:30 2008 @@ -2,11 +2,10 @@ from _ctypes.dummy import ArgumentError from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr -from _ctypes.dummy import _cast_addr from _ctypes.basics import _CData, sizeof, alignment, byref, addressof from _ctypes.primitive import _SimpleCData -from _ctypes.pointer import _Pointer +from _ctypes.pointer import _Pointer, _cast_addr from _ctypes.function import CFuncPtr from _ctypes.dll import dlopen from _ctypes.structure import Structure Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Tue Jan 15 16:41:30 2008 @@ -35,9 +35,6 @@ res._ffiarray = None return res - def _CData_input(self, value): - return self.from_param(value)._buffer.byptr() - from_address = cdata_from_address class Array(_CData): @@ -95,6 +92,9 @@ def __len__(self): return self._length_ + def _get_buffer_for_param(self): + return self._buffer.byptr() + ARRAY_CACHE = {} def create_array_type(base, length): Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/basics.py Tue Jan 15 16:41:30 2008 @@ -19,7 +19,8 @@ array of length 1 containing the same value according to the type 'self'. """ - return self.from_param(value)._buffer + cobj = self.from_param(value) + return cobj._get_buffer_for_param() def _CData_output(self, resarray): """Used when data exits ctypes and goes into user code. @@ -34,6 +35,9 @@ from _ctypes.array import create_array_type return create_array_type(self, other) + def _is_pointer_like(self): + return False + class _CData(object): """ The most basic object for all ctypes types """ @@ -45,6 +49,9 @@ def __ctypes_from_outparam__(self): return self + def _get_buffer_for_param(self): + return self._buffer + #class CArgObject(object): # def __init__(self, letter, raw_value, _type): # self.ffiletter = letter Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Tue Jan 15 16:41:30 2008 @@ -1,4 +1,5 @@ +import types from _ctypes.basics import _CData, _CDataMeta class CFuncPtrType(_CDataMeta): @@ -27,10 +28,15 @@ if isinstance(address_or_name_and_dll, tuple): self.name, self.dll = address_or_name_and_dll else: + self.address = address_or_name_and_dll self.name = None def __call__(self, *args): if self.name is None: + if isinstance(self.address, types.FunctionType): + # special hack to support to way a few functions like + # ctypes.cast() are implemented in ctypes/__init__.py + return self.address(*args) raise NotImplementedError("Creation of function pointer to pure addresses is not implemented") argtypes = self._argtypes_ if argtypes is None: Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Tue Jan 15 16:41:30 2008 @@ -21,12 +21,12 @@ setattr(obj, k, v) if '_type_' in typedict: ffiarray = _rawffi.Array('P') - def __init__(self, value=0): + def __init__(self, value=None): self._buffer = ffiarray(1) self.contents = value obj._ffiarray = ffiarray else: - def __init__(self, value=0): + def __init__(self, value=None): raise TypeError("%s has no type" % obj) obj.__init__ = __init__ return obj @@ -47,19 +47,30 @@ def _sizeofinstances(self): return _rawffi.sizeof('P') + def _is_pointer_like(self): + return True + from_address = cdata_from_address class _Pointer(_CData): __metaclass__ = PointerType def getcontents(self): - return self._type_.from_address(self._buffer[0]) + addr = self._buffer[0] + if addr == 0: + return None + else: + return self._type_.from_address(addr) def setcontents(self, value): - if not isinstance(value, self._type_): - raise TypeError("expected %s instead of %s" % ( - self._type_.__name__, type(value).__name__)) - self._buffer[0] = value._buffer + if value is not None: + if not isinstance(value, self._type_): + raise TypeError("expected %s instead of %s" % ( + self._type_.__name__, type(value).__name__)) + value = value._buffer + else: + value = 0 + self._buffer[0] = value def _subarray(self, index=0): """Return a _rawffi array of length 1 whose address is the same as @@ -77,3 +88,15 @@ self._subarray(index)[0] = self._type_._CData_input(value)[0] contents = property(getcontents, setcontents) + + +def _cast_addr(obj, _, tp): + if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): + raise TypeError("cast() argument 1 must be a pointer, not %s" + % (type(obj),)) + if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()): + raise TypeError("cast() argument 2 must be a pointer type, not %s" + % (tp,)) + result = tp() + result._buffer[0] = obj._buffer[0] + return result Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Tue Jan 15 16:41:30 2008 @@ -64,9 +64,10 @@ if isinstance(value, self): return value if isinstance(value, (Array, _Pointer)): - if type(value)._type_ == 'c': + from ctypes import c_char + if type(value)._type_ == c_char: return value - return _SimpleCData.from_param(self, value) + return SimpleType.from_param(self, value) result.from_param = classmethod(from_param) return result @@ -84,6 +85,9 @@ def _sizeofinstances(self): return _rawffi.sizeof(self._type_) + def _is_pointer_like(self): + return self._type_ in "sPzUZXO" + class _SimpleCData(_CData): __metaclass__ = SimpleType _type_ = 'i' Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/structure.py Tue Jan 15 16:41:30 2008 @@ -28,9 +28,6 @@ return res - def _CData_input(self, value): - return self.from_param(value)._buffer.byptr() - def from_address(self, address): instance = self.__new__(self) instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) @@ -61,3 +58,6 @@ except KeyError: raise AttributeError(name) return fieldtype._CData_output(self._subarray(fieldtype, name)) + + def _get_buffer_for_param(self): + return self._buffer.byptr() From antocuni at codespeak.net Tue Jan 15 16:48:30 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 15 Jan 2008 16:48:30 +0100 (CET) Subject: [pypy-svn] r50634 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080115154830.8AFDD168564@codespeak.net> Author: antocuni Date: Tue Jan 15 16:48:29 2008 New Revision: 50634 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/boxing_rules.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py Log: (antocuni, pdg) make generic clasess really work. Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Tue Jan 15 16:48:29 2008 @@ -15,7 +15,6 @@ 'call_staticmethod': 'interp_clr.call_staticmethod', 'load_cli_class': 'interp_clr.load_cli_class', 'get_extra_type_info': 'interp_clr.get_extra_type_info', - #'list_of_generic_classes': 'interp_clr.list_of_generic_classes', 'isDotNetType': 'interp_clr.isDotNetType', 'load_assembly': 'interp_clr.load_assembly', 'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies', Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py Tue Jan 15 16:48:29 2008 @@ -78,7 +78,24 @@ def __get__(self, obj, type_): return self.fget() +def _qualify(t): + return '%s, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' % t + class MetaGenericCliClassWrapper(type): + _cli_types = { + int: _qualify('System.Int32'), + str: _qualify('System.String'), + bool: _qualify('System.Boolean'), + float: _qualify('System.Double'), + } + _System_Object = _qualify('System.Object') + + def _cli_name(cls, ttype): + if isinstance(ttype, MetaCliClassWrapper): + return '[%s]' % ttype.__fullyqualifiedname__ + else: + return '[%s]' % cls._cli_types.get(ttype, cls._System_Object) + def __setattr__(cls, name, value): obj = cls.__dict__.get(name, None) if isinstance(obj, StaticProperty): @@ -86,37 +103,19 @@ else: type.__setattr__(cls, name, value) - def __getitem__(cls,*args): - #cls.__cliclass__ ='System.Collections.Generic.Dictionary`2' - rightDot = cls.__cliclass__.rfind('.') - rightTilde = cls.__cliclass__.rfind('`') - load_cli_class_leftArg = cls.__cliclass__[:rightDot] - genClassName = cls.__cliclass__[rightDot+1: rightTilde] - genClassNumArgs = int(cls.__cliclass__[rightTilde +1 :]) + def __getitem__(cls, type_or_tuple): import clr + if isinstance(type_or_tuple, tuple): + types = type_or_tuple + else: + types = (type_or_tuple,) + namespace, generic_class = cls.__cliclass__.rsplit('.', 1) + generic_params = [cls._cli_name(t) for t in types] + instance_class = '%s[%s]' % (generic_class, ','.join(generic_params)) try: - ln = len(args[0]) - # put a check for the number of arguments passed for the Generic class - if ln != genClassNumArgs: - raise "InvalidArgumentList" - else: - lindex = str(args[0][0]).find('\'') - rindex = str(args[0][0]).rfind('\'') - load_cli_class_rightArg = genClassName - load_cli_class_rightArg += "`%s[%s"%(ln,str(args[0][0])[lindex+1:rindex]) - for i in range(1,ln): - lindex = str(args[0][i]).find('\'') - rindex = str(args[0][i]).rfind('\'') - load_cli_class_rightArg += ",%s"%str(args[0][i])[lindex+1:rindex] - load_cli_class_rightArg += "]" - return clr.load_cli_class(load_cli_class_leftArg,load_cli_class_rightArg) - except: - # it's a single arg passed - lindex = str(args[0]).find('\'') - rindex = str(args[0]).rfind('\'') - load_cli_class_rightArg = genClassName - load_cli_class_rightArg += "`1[%s]"%(str(args[0])[lindex+1:rindex]) - return clr.load_cli_class(load_cli_class_leftArg,load_cli_class_rightArg) + return clr.load_cli_class(namespace, instance_class) + except ImportError: + raise TypeError, "Cannot load type %s.%s" % (namespace, instance_class) class MetaCliClassWrapper(type): def __setattr__(cls, name, value): @@ -155,9 +154,12 @@ obj.__cliobj__ = cliobj return obj -def build_wrapper(namespace, classname, staticmethods, methods, properties, indexers, hasIEnumerable, isClassGeneric): +def build_wrapper(namespace, classname, assembly_qualified_name, + staticmethods, methods, properties, indexers, + hasIEnumerable, isClassGeneric): fullname = '%s.%s' % (namespace, classname) d = {'__cliclass__': fullname, + '__fullyqualifiedname__': assembly_qualified_name, '__module__': namespace} for name in staticmethods: d[name] = StaticMethodWrapper(fullname, name) Modified: pypy/branch/clr-module-improvements/pypy/module/clr/boxing_rules.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/boxing_rules.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/boxing_rules.py Tue Jan 15 16:48:29 2008 @@ -1,3 +1,4 @@ +from pypy.tool.pairtype import extendabletype from pypy.interpreter.baseobjspace import W_Root from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.floatobject import W_FloatObject @@ -6,33 +7,47 @@ from pypy.objspace.std.stringobject import W_StringObject from pypy.translator.cli.dotnet import box -def tocli(self): - return box(self) -W_Root.tocli = tocli - -def tocli(self): - return box(self.intval) -W_IntObject.tocli = tocli - -def tocli(self): - return box(self.floatval) -W_FloatObject.tocli = tocli - -def tocli(self): - return None -W_NoneObject.tocli = tocli - -def tocli(self): - return box(self.boolval) -W_BoolObject.tocli = tocli - -def tocli(self): - return box(self._value) -W_StringObject.tocli = tocli +class __extend__(W_Root): + __metaclass__ = extendabletype + + def tocli(self): + return box(self) + +class __extend__(W_IntObject): + __metaclass__ = extendabletype + + def tocli(self): + return box(self.intval) + +class __extend__(W_FloatObject): + __metaclass__ = extendabletype + + def tocli(self): + return box(self.floatval) + +class __extend__(W_NoneObject): + __metaclass__ = extendabletype + + def tocli(self): + return None + +class __extend__(W_BoolObject): + __metaclass__ = extendabletype + + def tocli(self): + return box(self.boolval) + +class __extend__(W_StringObject): + __metaclass__ = extendabletype + + def tocli(self): + return box(self._value) from pypy.objspace.fake.objspace import W_Object as W_Object_Fake from pypy.rlib.nonconst import NonConstant -def tocli(self): - return NonConstant(None) -W_Object_Fake.tocli = tocli +class __extend__(W_Object_Fake): + __metaclass__ = extendabletype + + def tocli(self): + return NonConstant(None) Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Tue Jan 15 16:48:29 2008 @@ -218,42 +218,15 @@ namespaces[temp_name] = None if type.get_IsGenericType(): fullname = type.get_FullName() - index = fullname.rfind("`") - assert index != -1 - generics.append((fullname[0:index], fullname)) + if '+' not in fullname: + # else it's a nested type, ignore it + index = fullname.rfind("`") + assert index != -1 + generics.append((fullname[0:index], fullname)) w_listOfNamespaces = wrap_list_of_strings(space, namespaces.keys()) w_generic_mappings = wrap_list_of_pairs(space, generics) return space.newtuple([w_listOfNamespaces, w_generic_mappings]) - -#def list_of_generic_classes(space): -# """ -# use reflection to get a list of generic classes -# -# Return: List of generic classes -# e.g. [Dictionary`2 , List`1 , IEnumerator`1 , IEnumerable`1] -# """ -# listOfGenericTypes = [] -# currentDomain = System.AppDomain.get_CurrentDomain() -# assems = currentDomain.GetAssemblies() -# for loadedAssembly in assems: -# typesInAssembly = loadedAssembly.GetTypes() -# for type in typesInAssembly: -# namespace = type.get_Namespace() -# type_str = type.ToString() -# if namespace == "System.Collections.Generic": -# rightDot = type_str.rfind('.') -# rightTilde = type_str.rfind('`') -# firstSqBracket = type_str.find('[') -# firstPlus = type_str.find('+') -# if rightDot != -1 and rightTilde != -1: -# if firstPlus == -1: -# nameToPush = type_str[rightDot+1 : firstSqBracket] -# else: -# nameToPush = type_str[rightDot+1 : firstPlus] -# if nameToPush not in listOfGenericTypes: -# listOfGenericTypes.append(nameToPush) -# w_listOfGenericTypes = wrap_list_of_strings(space, listOfGenericTypes) -# return w_listOfGenericTypes +get_extra_type_info.unwrap_spec = [ObjSpace] def isDotNetType(space, nameFromImporter): """ @@ -351,11 +324,13 @@ if b_type.IsGenericType: isClassGeneric = True + assembly_qualified_name = b_type.get_AssemblyQualifiedName() w_staticmethods, w_methods = get_methods(space, b_type) w_properties, w_indexers = get_properties(space, b_type) return build_wrapper(space, space.wrap(namespace), space.wrap(classname), + space.wrap(assembly_qualified_name), w_staticmethods, w_methods, w_properties, Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py Tue Jan 15 16:48:29 2008 @@ -215,18 +215,46 @@ raises(TypeError, x.__setitem__, 4, 4.453) raises(TypeError, x.__setitem__, "test", 3) - def test_generic_class_with_single_import(self): + def test_generic_metaclass_list(self): import clr - import System.Collections.Generic - import List + from System.Collections.Generic import List import System.Int32 - l2 = List[System.Int32]() - l2.Add(3) - raises(TypeError, l2.Add, "test") + lst = List[System.Int32]() + lst.Add(42) + assert lst[0] == 42 + raises(TypeError, lst.Add, "test") - import Dictionary + lst = List[int]() + lst.Add(42) + assert lst[0] == 42 + raises(TypeError, lst.Add, "test") + + def test_generic_metaclass_dict(self): + import clr + from System.Collections.Generic import Dictionary + import System.Int32 import System.String - d1 = Dictionary[System.Int32,System.String]() - d1[1]="test" - raises(TypeError, d1.__setitem__, 3, 3) + d1 = Dictionary[System.Int32, System.String]() + d1[42]="test" + assert d1[42] == "test" + raises(TypeError, d1.__setitem__, 42, 42) + + d1 = Dictionary[int, str]() + d1[42]="test" + assert d1[42] == "test" + raises(TypeError, d1.__setitem__, 42, 42) + def test_generic_metaclass_object(self): + import clr + from System.Collections.Generic import List + class Foo(object): + pass + lst = List[Foo]() + f = Foo() + lst.Add(f) + assert lst[0] is f + + def test_generic_metaclass_typeerror(self): + import clr + from System.Collections.Generic import List + raises(TypeError, "List[int, int]") From arigo at codespeak.net Tue Jan 15 16:49:01 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 16:49:01 +0100 (CET) Subject: [pypy-svn] r50635 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080115154901.28BE5168564@codespeak.net> Author: arigo Date: Tue Jan 15 16:49:00 2008 New Revision: 50635 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Log: (fijal, arigo) __nonzero__. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Tue Jan 15 16:49:00 2008 @@ -23,7 +23,8 @@ ffiarray = _rawffi.Array('P') def __init__(self, value=None): self._buffer = ffiarray(1) - self.contents = value + if value is not None: + self.contents = value obj._ffiarray = ffiarray else: def __init__(self, value=None): @@ -58,18 +59,14 @@ def getcontents(self): addr = self._buffer[0] if addr == 0: - return None - else: - return self._type_.from_address(addr) + raise ValueError("NULL pointer access") + return self._type_.from_address(addr) def setcontents(self, value): - if value is not None: - if not isinstance(value, self._type_): - raise TypeError("expected %s instead of %s" % ( - self._type_.__name__, type(value).__name__)) - value = value._buffer - else: - value = 0 + if not isinstance(value, self._type_): + raise TypeError("expected %s instead of %s" % ( + self._type_.__name__, type(value).__name__)) + value = value._buffer self._buffer[0] = value def _subarray(self, index=0): @@ -87,6 +84,9 @@ raise IndexError self._subarray(index)[0] = self._type_._CData_input(value)[0] + def __nonzero__(self): + return self._buffer[0] != 0 + contents = property(getcontents, setcontents) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Tue Jan 15 16:49:00 2008 @@ -47,12 +47,18 @@ from _ctypes import Array, _Pointer def _getvalue(self): - return _rawffi.charp2string(self._buffer[0]) + addr = self._buffer[0] + if addr == 0: + return None + else: + return _rawffi.charp2string(addr) def _setvalue(self, value): if isinstance(value, str): array = _rawffi.Array('c')(len(value)+1, value) value = array.buffer # XXX free 'array' later + elif value is None: + value = 0 self._buffer[0] = value result.value = property(_getvalue, _setvalue) @@ -110,3 +116,6 @@ def __repr__(self): return "%s(%s)" % (type(self).__name__, self.value) + + def __nonzero__(self): + return self._buffer[0] not in (0, '\x00') From atobe at codespeak.net Tue Jan 15 16:52:30 2008 From: atobe at codespeak.net (atobe at codespeak.net) Date: Tue, 15 Jan 2008 16:52:30 +0100 (CET) Subject: [pypy-svn] r50636 - in pypy/branch/fixed-list-ootype/pypy/rpython: ootypesystem test Message-ID: <20080115155230.0FC41168564@codespeak.net> Author: atobe Date: Tue Jan 15 16:52:29 2008 New Revision: 50636 Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rtuple.py pypy/branch/fixed-list-ootype/pypy/rpython/test/test_rlist.py Log: (cfbolz, atobe): Fixed various places in rtyper to work with new Arrays. Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/ootype.py Tue Jan 15 16:52:29 2008 @@ -353,7 +353,7 @@ "ll_upper": Meth([], self.SELFTYPE_T), "ll_lower": Meth([], self.SELFTYPE_T), "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count) - "ll_split_chr": Meth([self.CHAR], List(self.SELFTYPE_T)), + "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)), "ll_contains": Meth([self.CHAR], Bool), "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T), }) @@ -529,6 +529,12 @@ self.ITEM = ITEMTYPE self._init_methods() + def ll_convert_from_array(self, array): + length = array.ll_length() + result = self.ll_newlist(length) + for n in range(length): + result.ll_setitem_fast(n, array.ll_getitem_fast(n)) + return result class Array(BuiltinADTType): # placeholders for types @@ -607,6 +613,8 @@ from pypy.rpython.ootypesystem import rlist return rlist.ll_newarray(self, length) + def ll_convert_from_array(self, array): + return array class Dict(BuiltinADTType): # placeholders for types @@ -1244,8 +1252,9 @@ def ll_split_chr(self, ch): # NOT_RPYTHON - res = _list(List(self._TYPE)) - res._list = [self.make_string(s) for s in self._str.split(ch)] + l = [self.make_string(s) for s in self._str.split(ch)] + res = _array(Array(self._TYPE), len(l)) + res._array[:] = l return res def ll_contains(self, ch): Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rdict.py Tue Jan 15 16:52:29 2008 @@ -323,7 +323,7 @@ def ll_dict_kvi(d, LIST, func): length = d.ll_length() - result = ll_newlist(LIST, length) + result = LIST.ll_newlist(length) it = d.ll_get_items_iterator() i = 0 while it.ll_go_next(): Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rstr.py Tue Jan 15 16:52:29 2008 @@ -209,8 +209,8 @@ def ll_stringslice_minusone(s): return s.ll_substring(0, s.ll_strlen()-1) - def ll_split_chr(LIST, s, c): - return s.ll_split_chr(c) + def ll_split_chr(RESULT, s, c): + return RESULT.ll_convert_from_array(s.ll_split_chr(c)) def ll_int(s, base): if not 2 <= base <= 36: Modified: pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/ootypesystem/rtuple.py Tue Jan 15 16:52:29 2008 @@ -36,13 +36,19 @@ def rtype_bltn_list(self, hop): from pypy.rpython.ootypesystem import rlist v_tup = hop.inputarg(self, 0) - LIST = hop.r_result.lowleveltype - c_list = inputconst(ootype.Void, LIST) - v_list = hop.genop('new', [c_list], resulttype=LIST) - c_resize = inputconst(ootype.Void, '_ll_resize') - c_setitem = inputconst(ootype.Void, 'll_setitem_fast') + RESULT = hop.r_result.lowleveltype + c_resulttype = inputconst(ootype.Void, RESULT) c_length = inputconst(ootype.Signed, len(self.items_r)) - hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void) + if isinstance(RESULT, ootype.Array): + v_list = hop.genop('oonewarray', [c_resulttype, c_length], resulttype=RESULT) + else: + assert isinstance(RESULT, ootype.List) + v_list = hop.genop('new', [c_resulttype], resulttype=RESULT) + c_resize = inputconst(ootype.Void, '_ll_resize') + hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void) + + c_setitem = inputconst(ootype.Void, 'll_setitem_fast') + for index in range(len(self.items_r)): name = self.fieldnames[index] r_item = self.items_r[index] @@ -51,6 +57,7 @@ v_item = hop.llops.convertvar(v_item, r_item, hop.r_result.item_repr) c_index = inputconst(ootype.Signed, index) hop.genop('oosend', [c_setitem, v_list, c_index, v_item], resulttype=ootype.Void) + return v_list Modified: pypy/branch/fixed-list-ootype/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/fixed-list-ootype/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/fixed-list-ootype/pypy/rpython/test/test_rlist.py Tue Jan 15 16:52:29 2008 @@ -498,7 +498,6 @@ assert self.class_name(res) == 'A' #''.join(res.super.typeptr.name) == 'A\00' - def test_reverse(self): def dummyfn(): l = [5, 3, 2] @@ -517,15 +516,15 @@ assert res == 235 def test_prebuilt_list(self): - klist = ['a', 'd', 'z', 'k'] + klist = [6, 7, 8, 9] def dummyfn(n): return klist[n] res = self.interpret(dummyfn, [0]) - assert res == 'a' + assert res == 6 res = self.interpret(dummyfn, [3]) - assert res == 'k' + assert res == 9 res = self.interpret(dummyfn, [-2]) - assert res == 'z' + assert res == 8 klist = ['a', 'd', 'z'] def mkdummyfn(): From arigo at codespeak.net Tue Jan 15 16:52:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 16:52:32 +0100 (CET) Subject: [pypy-svn] r50637 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080115155232.A365C16856D@codespeak.net> Author: arigo Date: Tue Jan 15 16:52:31 2008 New Revision: 50637 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Log: (fijal, arigo) _sizeofinstances() on arrays. Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/array.py Tue Jan 15 16:52:31 2008 @@ -37,6 +37,10 @@ from_address = cdata_from_address + def _sizeofinstances(self): + size, alignment = self._ffiarray.gettypecode(self._length_) + return size + class Array(_CData): __metaclass__ = ArrayMeta From arigo at codespeak.net Tue Jan 15 16:53:41 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 16:53:41 +0100 (CET) Subject: [pypy-svn] r50638 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes Message-ID: <20080115155341.1890B168564@codespeak.net> Author: arigo Date: Tue Jan 15 16:53:40 2008 New Revision: 50638 Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Log: (fijal, arigo) Pass one more test with more obscure lack of logic. (NB. This check-in message is vastly longer than the change.) Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original) +++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Tue Jan 15 16:53:40 2008 @@ -24,7 +24,7 @@ self._restype_ = restype restype = property(_getrestype, _setrestype) - def __init__(self, address_or_name_and_dll): + def __init__(self, address_or_name_and_dll=0): if isinstance(address_or_name_and_dll, tuple): self.name, self.dll = address_or_name_and_dll else: From arigo at codespeak.net Tue Jan 15 17:03:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 17:03:12 +0100 (CET) Subject: [pypy-svn] r50639 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115160312.1E1EE168564@codespeak.net> Author: arigo Date: Tue Jan 15 17:03:11 2008 New Revision: 50639 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: (fijal, arigo) Accept any pointer letter as argument to functions taking pointers. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Tue Jan 15 17:03:11 2008 @@ -328,10 +328,13 @@ msg = ("Argument %d should be an array of length 1, " "got length %d" % (i+1, arg.length)) raise OperationError(space.w_TypeError, space.wrap(msg)) - if arg.shape.itemtp[0] != argtype: - msg = "Argument %d should be typecode %s, got %s" % ( - i+1, argtype, arg.shape.itemtp[0]) - raise OperationError(space.w_TypeError, space.wrap(msg)) + letter = arg.shape.itemtp[0] + if letter != argtype: + if not (argtype in TYPEMAP_PTR_LETTERS and + letter in TYPEMAP_PTR_LETTERS): + msg = "Argument %d should be typecode %s, got %s" % ( + i+1, argtype, letter) + raise OperationError(space.w_TypeError, space.wrap(msg)) args_ll.append(arg.ll_buffer) # XXX we could avoid the intermediate list args_ll if self.resarray is not None: Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Tue Jan 15 17:03:11 2008 @@ -201,7 +201,7 @@ def test_time(self): import _rawffi libc = _rawffi.CDLL('libc.so.6') - time = libc.ptr('time', ['P'], 'l') + time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test arg = _rawffi.Array('P')(1) arg[0] = 0 res = time(arg) From antocuni at codespeak.net Tue Jan 15 17:15:42 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 15 Jan 2008 17:15:42 +0100 (CET) Subject: [pypy-svn] r50640 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080115161542.1C8C6168564@codespeak.net> Author: antocuni Date: Tue Jan 15 17:15:40 2008 New Revision: 50640 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Log: (antocuni, pdg) whack untile checkmodule clr passes Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Tue Jan 15 17:15:40 2008 @@ -16,8 +16,8 @@ 'load_cli_class': 'interp_clr.load_cli_class', 'get_extra_type_info': 'interp_clr.get_extra_type_info', 'isDotNetType': 'interp_clr.isDotNetType', - 'load_assembly': 'interp_clr.load_assembly', - 'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies', + #'load_assembly': 'interp_clr.load_assembly', + #'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies', } def setup_after_space_initialization(self): Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Tue Jan 15 17:15:40 2008 @@ -13,6 +13,7 @@ System.Double # force the type to be loaded, else the annotator could think that System has no Double attribute System.Boolean # the same +System.AppDomain def get_method(space, b_type, name, b_paramtypes): try: @@ -116,7 +117,7 @@ def split_fullname(name): lastdot = name.rfind('.') - if lastdot == -1: + if lastdot < 0: return '', name return name[:lastdot], name[lastdot+1:] @@ -205,23 +206,25 @@ generics = [] currentDomain = System.AppDomain.get_CurrentDomain() assems = currentDomain.GetAssemblies() - for loadedAssembly in assems: + for i in range(len(assems)): + loadedAssembly = assems[i] typesInAssembly = loadedAssembly.GetTypes() - for type in typesInAssembly: - namespace = type.get_Namespace() - if namespace != None: + for i in range(len(typesInAssembly)): + ttype = typesInAssembly[i] + namespace = ttype.get_Namespace() + if namespace is not None: chunks = namespace.split(".") temp_name = chunks[0] namespaces[temp_name] = None for chunk in chunks[1:]: temp_name += "."+chunk namespaces[temp_name] = None - if type.get_IsGenericType(): - fullname = type.get_FullName() + if ttype.get_IsGenericType(): + fullname = ttype.get_FullName() if '+' not in fullname: # else it's a nested type, ignore it index = fullname.rfind("`") - assert index != -1 + assert index >= 0 generics.append((fullname[0:index], fullname)) w_listOfNamespaces = wrap_list_of_strings(space, namespaces.keys()) w_generic_mappings = wrap_list_of_pairs(space, generics) @@ -238,56 +241,57 @@ return space.wrap(System.Type.GetType(nameFromImporter) is not None) isDotNetType.unwrap_spec = [ObjSpace, str] -def list_of_loadedAssemblies(space): - """ - return a List of currently loaded .NET assembliesy - - return: - list eg: ['System.Xml','System.Data','mscorlib'] - """ - loadedAssemblies = [] - currentDomain = System.AppDomain.get_CurrentDomain() - currentLoadedAssemblies = currentDomain.GetAssemblies() - - for lAssembly in currentLoadedAssemblies: - strName = lAssembly.get_FullName() - rindexComma = strName.find(',') - if rindexComma != -1: - loadedAssemblies.append(strName[:rindexComma]) - return space.wrap(loadedAssemblies) -list_of_loadedAssemblies.unwrap_spec = [ObjSpace] - -def load_assembly(space, assemblyPath): - """ - Load the given .NET assembly into the PyPy interpreter - - Parameters: - - - assemblyPath: the full path of the assembly - (e.g., /usr/lib/mono/2.0/System.Data.dll). - """ - assemblyToLoad = "" - loadedAssemblies = space.unwrap(list_of_loadedAssemblies(space)) - - # split the name to pull out "System.Data.dll" - # then check if it has already been loaded. - rindexSlash = assemblyPath.rfind('/') - if rindexSlash != -1: - strAfterSlash = assemblyPath[rindexSlash +1 : ] - rindexDot = strAfterSlash.rfind('.') - if rindexDot != -1: - assemblyToLoad = strAfterSlash[: rindexDot] - - if assemblyToLoad in loadedAssemblies: - print " won't reload loaded assembly " - pass - else: - try: - System.Reflection.Assembly.LoadFile(assemblyPath) - print "Loaded %s"%assemblyPath - except: - print " can not load the assembly " -load_assembly.unwrap_spec = [ObjSpace, str] +##def list_of_loadedAssemblies(space): +## """ +## return a List of currently loaded .NET assembliesy + +## return: +## list eg: ['System.Xml','System.Data','mscorlib'] +## """ +## loadedAssemblies = [] +## currentDomain = System.AppDomain.get_CurrentDomain() +## currentLoadedAssemblies = currentDomain.GetAssemblies() + +## for i in range(len(currentLoadedAssemblies)): +## lAssembly = currentLoadedAssemblies[i] +## strName = lAssembly.get_FullName() +## rindexComma = strName.find(',') +## if rindexComma != -1: +## loadedAssemblies.append(strName[:rindexComma]) +## return space.wrap(loadedAssemblies) +##list_of_loadedAssemblies.unwrap_spec = [ObjSpace] + +##def load_assembly(space, assemblyPath): +## """ +## Load the given .NET assembly into the PyPy interpreter + +## Parameters: + +## - assemblyPath: the full path of the assembly +## (e.g., /usr/lib/mono/2.0/System.Data.dll). +## """ +## assemblyToLoad = "" +## loadedAssemblies = space.unwrap(list_of_loadedAssemblies(space)) + +## # split the name to pull out "System.Data.dll" +## # then check if it has already been loaded. +## rindexSlash = assemblyPath.rfind('/') +## if rindexSlash != -1: +## strAfterSlash = assemblyPath[rindexSlash +1 : ] +## rindexDot = strAfterSlash.rfind('.') +## if rindexDot != -1: +## assemblyToLoad = strAfterSlash[: rindexDot] + +## if assemblyToLoad in loadedAssemblies: +## print " won't reload loaded assembly " +## pass +## else: +## try: +## System.Reflection.Assembly.LoadFile(assemblyPath) +## print "Loaded %s"%assemblyPath +## except: +## print " can not load the assembly " +##load_assembly.unwrap_spec = [ObjSpace, str] def load_cli_class(space, namespace, classname): """ @@ -321,7 +325,7 @@ # this is where we test if the class is Generic # set the flag isClassGeneric isClassGeneric = False - if b_type.IsGenericType: + if b_type.get_IsGenericType(): isClassGeneric = True assembly_qualified_name = b_type.get_AssemblyQualifiedName() From arigo at codespeak.net Tue Jan 15 17:26:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 17:26:28 +0100 (CET) Subject: [pypy-svn] r50641 - in pypy/branch/applevel-ctypes2/pypy/rlib: . test Message-ID: <20080115162628.2C40C16855A@codespeak.net> Author: arigo Date: Tue Jan 15 17:26:26 2008 New Revision: 50641 Modified: pypy/branch/applevel-ctypes2/pypy/rlib/rarithmetic.py pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rarithmetic.py Log: (fijal, arigo) Fix intmask() to work on r_somesmallintegerclass() too. This should include r_int on 64-bit architectures. Modified: pypy/branch/applevel-ctypes2/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/rarithmetic.py Tue Jan 15 17:26:26 2008 @@ -60,10 +60,9 @@ def intmask(n): if isinstance(n, int): return int(n) # possibly bool->int - if isinstance(n, unsigned_int): - n = long(n) - elif isinstance(n, objectmodel.Symbolic): + if isinstance(n, objectmodel.Symbolic): return n # assume Symbolics don't overflow + n = long(n) n &= LONG_MASK if n >= LONG_TEST: n -= 2*LONG_TEST Modified: pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rarithmetic.py Tue Jan 15 17:26:26 2008 @@ -184,6 +184,19 @@ assert intmask(r_uint(-1)) == -1 assert intmask(r_ulonglong(-1)) == -1 +def test_intmask_small(): + from pypy.rpython.lltypesystem import rffi + for tp in [rffi.r_signedchar, rffi.r_short, rffi.r_int, + rffi.r_long, rffi.r_longlong]: + x = intmask(tp(5)) + assert (type(x), x) == (int, 5) + x = intmask(tp(-5)) + assert (type(x), x) == (int, -5) + for tp in [rffi.r_uchar, rffi.r_ushort, rffi.r_uint, + rffi.r_ulong, rffi.r_ulonglong]: + x = intmask(tp(5)) + assert (type(x), x) == (int, 5) + def test_ovfcheck(): one = 1 x = sys.maxint From cfbolz at codespeak.net Tue Jan 15 17:38:16 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 15 Jan 2008 17:38:16 +0100 (CET) Subject: [pypy-svn] r50642 - pypy/dist/pypy/translator/c/src Message-ID: <20080115163816.D6C9516855A@codespeak.net> Author: cfbolz Date: Tue Jan 15 17:38:16 2008 New Revision: 50642 Modified: pypy/dist/pypy/translator/c/src/ll_strtod.h Log: according to alexander, this is not needed now Modified: pypy/dist/pypy/translator/c/src/ll_strtod.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_strtod.h (original) +++ pypy/dist/pypy/translator/c/src/ll_strtod.h Tue Jan 15 17:38:16 2008 @@ -1,10 +1,6 @@ #ifndef LL_STRTOD_H #define LL_STRTOD_H -#ifdef MS_WINDOWS -#include -#endif - #include #include #include From arigo at codespeak.net Tue Jan 15 17:45:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 17:45:14 +0100 (CET) Subject: [pypy-svn] r50643 - in pypy/branch/applevel-ctypes2/pypy/rlib: . test Message-ID: <20080115164514.746D716856C@codespeak.net> Author: arigo Date: Tue Jan 15 17:45:14 2008 New Revision: 50643 Modified: pypy/branch/applevel-ctypes2/pypy/rlib/rbigint.py pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rbigint.py Log: (fijal, arigo) Add a method ulonglongmask() on rbigints, to truncate the value down to a r_ulonglong. Modified: pypy/branch/applevel-ctypes2/pypy/rlib/rbigint.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/rbigint.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/rbigint.py Tue Jan 15 17:45:14 2008 @@ -200,6 +200,10 @@ raise ValueError("cannot convert negative integer to unsigned int") return _AsULonglong_ignore_sign(self) + def ulonglongmask(self): + """Return r_ulonglong(self), truncating.""" + return _AsULonglong_mask(self) + def tofloat(self): return _AsDouble(self) @@ -1584,6 +1588,17 @@ i -= 1 return x +def _AsULonglong_mask(v): + x = r_ulonglong(0) + i = len(v.digits) - 1 + while i >= 0: + prev = x + x = (x << SHIFT) + v.digits[i] + i -= 1 + if v.sign < 0: + x = -x + return x + def _hash(v): # This is designed so that Python ints and longs with the # same value hash to the same value, otherwise comparisons Modified: pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rbigint.py (original) +++ pypy/branch/applevel-ctypes2/pypy/rlib/test/test_rbigint.py Tue Jan 15 17:45:14 2008 @@ -3,7 +3,7 @@ from random import random, randint from pypy.rlib.rbigint import rbigint, SHIFT, MASK from pypy.rlib import rbigint as lobj -from pypy.rlib.rarithmetic import r_uint, r_longlong +from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong import operator, sys class TestRLong(object): @@ -419,6 +419,16 @@ py.test.raises(OverflowError, f3.tolonglong) py.test.raises(OverflowError, f4.tolonglong) + def test_ulonglongmask(self): + assert rbigint.fromlong(-1).ulonglongmask() == r_ulonglong(-1) + assert rbigint.fromlong(0).ulonglongmask() == r_ulonglong(0) + assert (rbigint.fromlong(sys.maxint).ulonglongmask() == + r_ulonglong(sys.maxint)) + assert (rbigint.fromlong(9**50).ulonglongmask() == + r_ulonglong(9**50)) + assert (rbigint.fromlong(-9**50).ulonglongmask() == + r_ulonglong(-9**50)) + class TestTranslatable(object): From arigo at codespeak.net Tue Jan 15 17:48:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 17:48:20 +0100 (CET) Subject: [pypy-svn] r50644 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115164820.9BE0416856C@codespeak.net> Author: arigo Date: Tue Jan 15 17:48:20 2008 New Revision: 50644 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: (fijal, arigo) Kill all the nice work on the size checkers. Instead, _rawffi now truncates whatever int or long Python object it receives, just like ctypes. :-/ Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Tue Jan 15 17:48:20 2008 @@ -161,34 +161,7 @@ buffer.""" ) -def make_size_checker(format, size, signed): - min, max, _ = min_max_acc_method(size, signed) - - def checker(value): - if value < min: - raise FfiValueError("%d too small for format %s" % (value, format)) - elif value > max: - raise FfiValueError("%d too large for format %s" % (value, format)) - return checker - -_SIZE_CHECKERS = { - 'b' : True, - 'B' : False, - 'h' : True, - 'H' : False, - 'i' : True, - 'I' : False, - 'l' : True, - 'L' : False, - 'q' : True, - 'Q' : False, -} - -# XXX check for single float as well -SIZE_CHECKERS = {} -for c, signed in _SIZE_CHECKERS.items(): - SIZE_CHECKERS[c] = make_size_checker(c, native_fmttable[c]['size'], signed) -unroll_size_checkers = unrolling_iterable(SIZE_CHECKERS.items()) +unroll_letters_for_numbers = unrolling_iterable("bBhHiIlLqQ") def segfault_exception(space, reason): w_mod = space.getbuiltinmodule("_rawffi") @@ -254,22 +227,14 @@ val = s[0] push_func(add_arg, argdesc, val) else: - for c, checker in unroll_size_checkers: + for c in unroll_letters_for_numbers: if letter == c: - if c == "q": - val = space.r_longlong_w(w_arg) - elif c == "Q": - val = space.r_ulonglong_w(w_arg) - elif c == "I" or c == "L" or c =="B": - val = space.uint_w(w_arg) - else: - val = space.int_w(w_arg) - try: - checker(val) - except FfiValueError, e: - raise OperationError(space.w_ValueError, w(e.msg)) TP = LL_TYPEMAP[c] - push_func(add_arg, argdesc, rffi.cast(TP, val)) + if space.is_true(space.isinstance(w_arg, space.w_int)): + val = rffi.cast(TP, space.int_w(w_arg)) + else: + val = rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask()) + push_func(add_arg, argdesc, val) return else: raise OperationError(space.w_TypeError, @@ -292,9 +257,6 @@ return space.wrap(func(add_arg, argdesc, ll_type)) elif c == 'f' or c == 'd': return space.wrap(float(func(add_arg, argdesc, ll_type))) - elif c == 'h' or c == 'H': - return space.wrap(rffi.cast(lltype.Signed, func(add_arg, argdesc, - ll_type))) else: return space.wrap(intmask(func(add_arg, argdesc, ll_type))) raise OperationError(space.w_TypeError, Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Tue Jan 15 17:48:20 2008 @@ -350,9 +350,6 @@ res = some_huge_uvalue() assert res[0] == 1<<42 res.free() - arg1 = _rawffi.Array('Q')(1) - raises(ValueError, "arg1[0] = -1") - arg1.free() pass_ll = lib.ptr('pass_ll', ['q'], 'q') arg1 = _rawffi.Array('q')(1) arg1[0] = 1<<42 @@ -455,3 +452,55 @@ assert repr(a) == "<_rawffi array %d of length %d>" % (a.buffer, len(a)) a.free() + + def test_truncate(self): + import _rawffi + a = _rawffi.Array('b')(1) + a[0] = -5 + assert a[0] == -5 + a[0] = 123L + assert a[0] == 123 + a[0] = 0x97817182ab128111111111111171817d042 + assert a[0] == 0x42 + a[0] = 255 + assert a[0] == -1 + a[0] = -2 + assert a[0] == -2 + a[0] = -255 + assert a[0] == 1 + a.free() + + a = _rawffi.Array('B')(1) + a[0] = 123L + assert a[0] == 123 + a[0] = 0x18329b1718b97d89b7198db817d042 + assert a[0] == 0x42 + a[0] = 255 + assert a[0] == 255 + a[0] = -2 + assert a[0] == 254 + a[0] = -255 + assert a[0] == 1 + a.free() + + a = _rawffi.Array('h')(1) + a[0] = 123L + assert a[0] == 123 + a[0] = 0x9112cbc91bd91db19aaaaaaaaaaaaaa8170d42 + assert a[0] == 0x0d42 + a[0] = 65535 + assert a[0] == -1 + a[0] = -2 + assert a[0] == -2 + a[0] = -65535 + assert a[0] == 1 + a.free() + + a = _rawffi.Array('H')(1) + a[0] = 123L + assert a[0] == 123 + a[0] = 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeee817d042 + assert a[0] == 0xd042 + a[0] = -2 + assert a[0] == 65534 + a.free() From antocuni at codespeak.net Tue Jan 15 19:11:39 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 15 Jan 2008 19:11:39 +0100 (CET) Subject: [pypy-svn] r50646 - in pypy/branch/clr-module-improvements/pypy/translator/cli: . test Message-ID: <20080115181139.EC2F21684E3@codespeak.net> Author: antocuni Date: Tue Jan 15 19:11:39 2008 New Revision: 50646 Modified: pypy/branch/clr-module-improvements/pypy/translator/cli/dotnet.py pypy/branch/clr-module-improvements/pypy/translator/cli/test/test_dotnet.py Log: fix annotations of strings. Thanks cfbolz Modified: pypy/branch/clr-module-improvements/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/translator/cli/dotnet.py (original) +++ pypy/branch/clr-module-improvements/pypy/translator/cli/dotnet.py Tue Jan 15 19:11:39 2008 @@ -157,7 +157,7 @@ elif TYPE is ootype.Char: return SomeChar() elif TYPE is ootype.String: - return SomeString() + return SomeString(can_be_None=True) else: return lltype_to_annotation(TYPE) lltype_to_annotation = classmethod(lltype_to_annotation) Modified: pypy/branch/clr-module-improvements/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/branch/clr-module-improvements/pypy/translator/cli/test/test_dotnet.py Tue Jan 15 19:11:39 2008 @@ -12,6 +12,7 @@ System = CLR.System Math = CLR.System.Math ArrayList = CLR.System.Collections.ArrayList +Type = CLR.System.Type class TestDotnetAnnotation(object): @@ -169,6 +170,15 @@ assert isinstance(s, annmodel.SomeInstance) assert s.classdef.name.endswith('Foo') + def test_can_be_None(self): + def fn(): + ttype = Type.GetType('foo') + return ttype.get_Namespace() + a = RPythonAnnotator() + s = a.build_types(fn, []) + assert isinstance(s, annmodel.SomeString) + assert s.can_be_None + class TestDotnetRtyping(CliTest): def _skip_pythonnet(self, msg): @@ -389,9 +399,27 @@ res = self.interpret(fn, []) assert res is True + def test_compare_string_None(self): + from pypy.rlib.nonconst import NonConstant + def null(): + if NonConstant(True): + return None + else: + return "" + + def fn(): + ttype = Type.GetType('Consts, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089') + namespace = ttype.get_Namespace() + if namespace is not None: + return False + else: + return True + res = self.interpret(fn, [], backendopt=False) + assert res is True + class TestPythonnet(TestDotnetRtyping): # don't interpreter functions but execute them directly through pythonnet - def interpret(self, f, args): + def interpret(self, f, args, backendopt='ignored'): return f(*args) def _skip_pythonnet(self, msg): From antocuni at codespeak.net Tue Jan 15 19:15:00 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 15 Jan 2008 19:15:00 +0100 (CET) Subject: [pypy-svn] r50647 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080115181500.173871684E3@codespeak.net> Author: antocuni Date: Tue Jan 15 19:14:59 2008 New Revision: 50647 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Log: load extra info just the first time they are needed, else they break translation (thanks cfbolz again) Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Tue Jan 15 19:14:59 2008 @@ -20,15 +20,17 @@ been imported and added to sys.modules. ''' def __init__(self): - import clr - # this might not be the correct place to load the valid NameSpaces - valid_namespaces, generic_mappings = clr.get_extra_type_info() - self.valid_namespaces = set(valid_namespaces) - self.generic_mappings = dict(generic_mappings) + self.valid_namespaces = None + self.generic_mappings = None def find_module(self, fullname, path=None): - # check for true NAMESPACE or .NET TYPE import clr + if self.valid_namespaces is None: + # this might not be the correct place to load the valid NameSpaces + valid_namespaces, generic_mappings = clr.get_extra_type_info() + self.valid_namespaces = set(valid_namespaces) + self.generic_mappings = dict(generic_mappings) + if fullname in self.valid_namespaces or fullname in self.generic_mappings or clr.isDotNetType(fullname): # fullname is a .Net Module return self From antocuni at codespeak.net Tue Jan 15 19:31:46 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 15 Jan 2008 19:31:46 +0100 (CET) Subject: [pypy-svn] r50648 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080115183146.B5D5816855A@codespeak.net> Author: antocuni Date: Tue Jan 15 19:31:46 2008 New Revision: 50648 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Log: (arigo) install the import hook only after startup, else the translation breaks Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Tue Jan 15 19:31:46 2008 @@ -20,7 +20,7 @@ #'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies', } - def setup_after_space_initialization(self): + def startup(self, space): self.space.appexec([self], """(clr_module): import sys sys.meta_path.append(clr_module.dotnetimporter()) From arigo at codespeak.net Tue Jan 15 19:31:54 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 19:31:54 +0100 (CET) Subject: [pypy-svn] r50649 - in pypy/branch/applevel-ctypes2/pypy/interpreter: . test Message-ID: <20080115183154.971A516856D@codespeak.net> Author: arigo Date: Tue Jan 15 19:31:53 2008 New Revision: 50649 Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/gateway.py pypy/branch/applevel-ctypes2/pypy/interpreter/test/test_gateway.py Log: (fijal, arigo) Support for r_uint and r_ulonglong in unwrap_spec. Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/gateway.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/interpreter/gateway.py (original) +++ pypy/branch/applevel-ctypes2/pypy/interpreter/gateway.py Tue Jan 15 19:31:53 2008 @@ -20,7 +20,7 @@ from pypy.interpreter.argument import Arguments, AbstractArguments from pypy.tool.sourcetools import NiceCompile, compile2 from pypy.rlib.jit import hint -from pypy.rlib.rarithmetic import r_longlong, r_int +from pypy.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint # internal non-translatable parts: import py @@ -164,9 +164,8 @@ app_sig.varargname = argname[2:] def visit__object(self, typ, app_sig): - if typ not in (int, str, float, unicode, r_longlong): - assert False, "unsupported basic type in unwrap_spec" - self.checked_space_method(typ.__name__, app_sig) + name = int_unwrapping_space_method(typ) + self.checked_space_method(name, app_sig) class UnwrapSpec_EmitRun(UnwrapSpecEmit): @@ -210,12 +209,7 @@ self.run_args.append(self.scopenext()) def visit__object(self, typ): - if typ not in (int, str, float, unicode, r_longlong): - assert False, "unsupported basic type in unwrap_spec" - if typ is r_int is r_longlong: - name = 'r_longlong' - else: - name = typ.__name__ + name = int_unwrapping_space_method(typ) self.run_args.append("space.%s_w(%s)" % (name, self.scopenext())) @@ -327,9 +321,8 @@ raise FastFuncNotSupported def visit__object(self, typ): - if typ not in (int, str, float, unicode, r_longlong): - assert False, "unsupported basic type in unwrap_spec" - self.unwrap.append("space.%s_w(%s)" % (typ.__name__, + name = int_unwrapping_space_method(typ) + self.unwrap.append("space.%s_w(%s)" % (name, self.nextarg())) def visit_index(self, typ): @@ -364,7 +357,16 @@ fastfunc = d['fastfunc_%s_%d' % (func.__name__, narg)] return narg, fastfunc make_fastfunc = staticmethod(make_fastfunc) - + +def int_unwrapping_space_method(typ): + assert typ in (int, str, float, unicode, r_longlong, r_uint, r_ulonglong) + if typ is r_int is r_longlong: + return 'r_longlong' + elif typ is r_uint: + return 'uint' + else: + return typ.__name__ + class BuiltinCode(eval.Code): "The code object implementing a built-in (interpreter-level) hook." _immutable_ = True Modified: pypy/branch/applevel-ctypes2/pypy/interpreter/test/test_gateway.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/interpreter/test/test_gateway.py (original) +++ pypy/branch/applevel-ctypes2/pypy/interpreter/test/test_gateway.py Tue Jan 15 19:31:53 2008 @@ -231,6 +231,44 @@ space.raises_w(space.w_OverflowError, space.call_function, w_app_g3_ll, w_huge) + def test_interp2app_unwrap_spec_r_uint(self): + space = self.space + w = space.wrap + def g3_ll(space, n): + return space.wrap(n * 3) + app_g3_ll = gateway.interp2app_temp(g3_ll, + unwrap_spec=[gateway.ObjSpace, + gateway.r_uint]) + w_app_g3_ll = space.wrap(app_g3_ll) + w_big = w(gateway.r_uint(sys.maxint+100)) + assert space.eq_w( + space.call_function(w_app_g3_ll, w_big), + w(gateway.r_uint((sys.maxint+100)*3))) + space.raises_w(space.w_OverflowError, + space.call_function, w_app_g3_ll, w(10L**100)) + space.raises_w(space.w_ValueError, + space.call_function, w_app_g3_ll, w(-1)) + + def test_interp2app_unwrap_spec_r_ulonglong(self): + space = self.space + w = space.wrap + def g3_ll(space, n): + return space.wrap(n * 3) + app_g3_ll = gateway.interp2app_temp(g3_ll, + unwrap_spec=[gateway.ObjSpace, + gateway.r_ulonglong]) + w_app_g3_ll = space.wrap(app_g3_ll) + w_big = w(gateway.r_ulonglong(-100)) + assert space.eq_w( + space.call_function(w_app_g3_ll, w_big), + w(gateway.r_ulonglong(-300))) + space.raises_w(space.w_OverflowError, + space.call_function, w_app_g3_ll, w(10L**100)) + space.raises_w(space.w_ValueError, + space.call_function, w_app_g3_ll, w(-1)) + space.raises_w(space.w_ValueError, + space.call_function, w_app_g3_ll, w(-10L**99)) + def test_interp2app_unwrap_spec_index(self): space = self.space w = space.wrap From arigo at codespeak.net Tue Jan 15 19:43:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 15 Jan 2008 19:43:20 +0100 (CET) Subject: [pypy-svn] r50650 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test Message-ID: <20080115184320.4132D16855C@codespeak.net> Author: arigo Date: Tue Jan 15 19:43:19 2008 New Revision: 50650 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: Intermediate check-in: use unsigned integers everywhere as addresses, like ctypes does. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Tue Jan 15 19:43:19 2008 @@ -13,7 +13,7 @@ from pypy.module._rawffi.interp_rawffi import W_DataInstance from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value from pypy.module._rawffi.interp_rawffi import unpack_typecode, letter2tp -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint def push_elem(ll_array, pos, value): TP = lltype.typeOf(value) @@ -56,7 +56,7 @@ def fromaddress(self, space, address, length): return space.wrap(W_ArrayInstance(space, self, length, address)) - fromaddress.unwrap_spec = ['self', ObjSpace, int, int] + fromaddress.unwrap_spec = ['self', ObjSpace, r_uint, int] def descr_gettypecode(self, space, length): _, itemsize, alignment = self.itemtp @@ -100,15 +100,15 @@ class W_ArrayInstance(W_DataInstance): - def __init__(self, space, shape, length, address=0): + def __init__(self, space, shape, length, address=r_uint(0)): _, itemsize, _ = shape.itemtp W_DataInstance.__init__(self, space, itemsize * length, address) self.length = length self.shape = shape def descr_repr(self, space): - addr = rffi.cast(lltype.Signed, self.ll_buffer) - return space.wrap("<_rawffi array %d of length %d>" % (addr, + addr = rffi.cast(lltype.Unsigned, self.ll_buffer) + return space.wrap("<_rawffi array %x of length %d>" % (addr, self.length)) descr_repr.unwrap_spec = ['self', ObjSpace] @@ -135,7 +135,7 @@ def descr_itemaddress(self, space, num): _, itemsize, _ = self.shape.itemtp ptr = rffi.ptradd(self.ll_buffer, itemsize * num) - return space.wrap(rffi.cast(lltype.Signed, ptr)) + return space.wrap(rffi.cast(lltype.Unsigned, ptr)) descr_itemaddress.unwrap_spec = ['self', ObjSpace, int] W_ArrayInstance.typedef = TypeDef( Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/callback.py Tue Jan 15 19:43:19 2008 @@ -19,7 +19,7 @@ def getllfuncptr(space, self): TP = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) ptr = lltype.functionptr(TP, stuff) - return space.wrap(rffi.cast(rffi.INT, ptr)) + return space.wrap(rffi.cast(rffi.Unsigned, ptr)) def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result): return W_CallbackPtr(space, w_callable, w_args, w_result) Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Tue Jan 15 19:43:19 2008 @@ -12,7 +12,7 @@ from pypy.module.struct.standardfmttable import min_max_acc_method from pypy.module.struct.nativefmttable import native_fmttable from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint class FfiValueError(Exception): def __init__(self, msg): @@ -178,15 +178,15 @@ class W_DataInstance(Wrappable): - def __init__(self, space, size, address=0): - if address != 0: + def __init__(self, space, size, address=r_uint(0)): + if address: self.ll_buffer = rffi.cast(rffi.VOIDP, address) else: self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', zero=True) def getbuffer(space, self): - return space.wrap(rffi.cast(lltype.Signed, self.ll_buffer)) + return space.wrap(rffi.cast(lltype.Unsigned, self.ll_buffer)) def byptr(self, space): from pypy.module._rawffi.array import get_array_cache @@ -204,6 +204,13 @@ free.unwrap_spec = ['self', ObjSpace] +def unwrap_truncate_int(TP, space, w_arg): + if space.is_true(space.isinstance(w_arg, space.w_int)): + return rffi.cast(TP, space.int_w(w_arg)) + else: + return rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask()) +unwrap_truncate_int._annspecialcase_ = 'specialize:arg(0)' + def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg): letter, _, _ = tp w = space.wrap @@ -214,11 +221,12 @@ space.float_w(w_arg))) elif letter in TYPEMAP_PTR_LETTERS: # check for NULL ptr - if space.is_true(space.isinstance(w_arg, space.w_int)): - push_func(add_arg, argdesc, rffi.cast(rffi.VOIDP, space.int_w(w_arg))) + datainstance = space.interpclass_w(w_arg) + if isinstance(datainstance, W_DataInstance): + ptr = datainstance.ll_buffer else: - datainstance = space.interp_w(W_DataInstance, w_arg) - push_func(add_arg, argdesc, datainstance.ll_buffer) + ptr = unwrap_truncate_int(rffi.VOIDP, space, w_arg) + push_func(add_arg, argdesc, ptr) elif letter == "c": s = space.str_w(w_arg) if len(s) != 1: @@ -230,10 +238,7 @@ for c in unroll_letters_for_numbers: if letter == c: TP = LL_TYPEMAP[c] - if space.is_true(space.isinstance(w_arg, space.w_int)): - val = rffi.cast(TP, space.int_w(w_arg)) - else: - val = rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask()) + val = unwrap_truncate_int(TP, space, w_arg) push_func(add_arg, argdesc, val) return else: @@ -249,7 +254,7 @@ if letter == c: if c in TYPEMAP_PTR_LETTERS: res = func(add_arg, argdesc, rffi.VOIDP) - return space.wrap(rffi.cast(lltype.Signed, res)) + return space.wrap(rffi.cast(lltype.Unsigned, res)) elif c == 'v': func(add_arg, argdesc, ll_type) return space.w_None @@ -335,4 +340,4 @@ return space.w_None s = rffi.charp2strn(rffi.cast(rffi.CCHARP, address), maxlength) return space.wrap(s) -charp2string.unwrap_spec = [ObjSpace, int, int] +charp2string.unwrap_spec = [ObjSpace, r_uint, int] Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Tue Jan 15 19:43:19 2008 @@ -14,7 +14,7 @@ from pypy.module._rawffi.interp_rawffi import W_DataInstance from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value from pypy.module._rawffi.interp_rawffi import unpack_typecode -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint def unpack_fields(space, w_fields): fields_w = space.unpackiterable(w_fields) @@ -87,7 +87,7 @@ def fromaddress(self, space, address): return space.wrap(W_StructureInstance(space, self, address, None)) - fromaddress.unwrap_spec = ['self', ObjSpace, int] + fromaddress.unwrap_spec = ['self', ObjSpace, r_uint] def descr_fieldoffset(self, space, attr): index = self.getindex(space, attr) @@ -137,8 +137,8 @@ self.setattr(space, field, w_value) def descr_repr(self, space): - addr = rffi.cast(lltype.Signed, self.ll_buffer) - return space.wrap("<_rawffi struct %d>" % (addr,)) + addr = rffi.cast(lltype.Unsigned, self.ll_buffer) + return space.wrap("<_rawffi struct %x>" % (addr,)) descr_repr.unwrap_spec = ['self', ObjSpace] def getattr(self, space, attr): @@ -160,7 +160,7 @@ def descr_fieldaddress(self, space, attr): i = self.shape.getindex(space, attr) ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i]) - return space.wrap(rffi.cast(lltype.Signed, ptr)) + return space.wrap(rffi.cast(lltype.Unsigned, ptr)) descr_fieldaddress.unwrap_spec = ['self', ObjSpace, str] Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Tue Jan 15 19:43:19 2008 @@ -454,7 +454,7 @@ a.free() def test_truncate(self): - import _rawffi + import _rawffi, struct a = _rawffi.Array('b')(1) a[0] = -5 assert a[0] == -5 @@ -504,3 +504,13 @@ a[0] = -2 assert a[0] == 65534 a.free() + + maxptr = (256 ** struct.calcsize("P")) - 1 + a = _rawffi.Array('P')(1) + a[0] = 123L + assert a[0] == 123 + a[0] = 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeee817d042 + assert a[0] == 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeee817d042 & maxptr + a[0] = -2 + assert a[0] == maxptr - 1 + a.free() From bigdog at codespeak.net Tue Jan 15 20:58:20 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Tue, 15 Jan 2008 20:58:20 +0100 (CET) Subject: [pypy-svn] r50652 - pypy/dist/pypy/rpython/lltypesystem/module Message-ID: <20080115195820.A9FA716850F@codespeak.net> Author: bigdog Date: Tue Jan 15 20:58:20 2008 New Revision: 50652 Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py Log: add check for windows before adding /m to the link line. Only add /m to the link line of non-windows platforms. Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py Tue Jan 15 20:58:20 2008 @@ -1,6 +1,8 @@ import math import errno import py +import sys + from pypy.rpython.lltypesystem import lltype, rffi from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import rposix @@ -56,7 +58,11 @@ else: raise ValueError("math domain error") -eci = ExternalCompilationInfo(libraries=['m']) +if sys.platform[:3] == "win": + eci = ExternalCompilationInfo(libraries=[]) +else: + eci = ExternalCompilationInfo(libraries=['m']) + def new_unary_math_function(name): c_func = rffi.llexternal(name, [rffi.DOUBLE], rffi.DOUBLE, From fijal at codespeak.net Tue Jan 15 22:20:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 15 Jan 2008 22:20:09 +0100 (CET) Subject: [pypy-svn] r50653 - pypy/dist/pypy/rpython/module Message-ID: <20080115212009.625581684D6@codespeak.net> Author: fijal Date: Tue Jan 15 22:20:07 2008 New Revision: 50653 Modified: pypy/dist/pypy/rpython/module/ll_os.py Log: Quick and dirty fix to make windows work. We need to have a sane way of doing this at some point (and making llvm happy at the same time) Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Tue Jan 15 22:20:07 2008 @@ -76,27 +76,28 @@ self.configure(CConfig) # we need an indirection via c functions to get macro calls working on llvm - decl_snippet = """ + if hasattr(os, 'WCOREDUMP'): + decl_snippet = """ %(ret_type)s pypy_macro_wrapper_%(name)s (int status); - """ - def_snippet = """ + """ + def_snippet = """ %(ret_type)s pypy_macro_wrapper_%(name)s (int status) { - return %(name)s(status); + return %(name)s(status); } - """ - decls = [] - defs = [] - for name in self.w_star: - data = {'ret_type': 'int', 'name': name} - decls.append(decl_snippet % data) - defs.append(def_snippet % data) - h_source = decls + defs - - self.compilation_info = self.compilation_info.merge( - ExternalCompilationInfo( - post_include_lines = decls, - separate_module_sources = ["\n".join(h_source)] - )) + """ + decls = [] + defs = [] + for name in self.w_star: + data = {'ret_type': 'int', 'name': name} + decls.append(decl_snippet % data) + defs.append(def_snippet % data) + h_source = decls + defs + + self.compilation_info = self.compilation_info.merge( + ExternalCompilationInfo( + post_include_lines = decls, + separate_module_sources = ["\n".join(h_source)] + )) # a simple, yet usefull factory def extdef_for_os_function_returning_int(self, name, **kwds): From antocuni at codespeak.net Wed Jan 16 00:03:21 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jan 2008 00:03:21 +0100 (CET) Subject: [pypy-svn] r50655 - in pypy/dist/pypy: config objspace objspace/test Message-ID: <20080115230321.C47D1168518@codespeak.net> Author: antocuni Date: Wed Jan 16 00:03:21 2008 New Revision: 50655 Added: pypy/dist/pypy/objspace/reflective.py (contents, props changed) pypy/dist/pypy/objspace/test/test_reflective.py (contents, props changed) Modified: pypy/dist/pypy/config/pypyoption.py Log: (cfbolz, antocuni) a completely experimental object space that allows to override space operations from applevel code. Reflection++ Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Wed Jan 16 00:03:21 2008 @@ -41,7 +41,7 @@ pypy_optiondescription = OptionDescription("objspace", "Object Space Options", [ ChoiceOption("name", "Object Space name", - ["std", "flow", "thunk", "dump", "taint"], + ["std", "flow", "thunk", "dump", "taint", "reflective"], "std", cmdline='--objspace -o'), Added: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/reflective.py Wed Jan 16 00:03:21 2008 @@ -0,0 +1,51 @@ +from pypy.interpreter import gateway +from pypy.interpreter.error import OperationError +from pypy.objspace import std +from pypy.objspace.proxy import patch_space_in_place + +def set_reflectivespace(space, w_reflectivespace): + ec = space.getexecutioncontext() + if space.is_w(ec.w_reflectivespace, space.w_None): + ec.w_reflectivespace = None + else: + ec.w_reflectivespace = w_reflectivespace +app_set_reflectivespace = gateway.interp2app(set_reflectivespace) + + +def proxymaker(space, opname, parentfn): + def fn(*args_w): + ec = space.getexecutioncontext() + if ec.w_reflectivespace is not None: + w_rspace = ec.w_reflectivespace + ec.w_reflectivespace = None + try: + w_f = space.getattr(w_rspace, space.wrap(opname)) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + w_res = space.call_function(w_f, *args_w) + ec.w_reflectivespace = w_rspace + return w_res + return parentfn(*args_w) + fn.func_name = opname + return fn + +def createexecutioncontextmaker(space, parentfn): + def createexecutioncontext(): + ec = parentfn() + ec.w_reflectivespace = None + return ec + return createexecutioncontext + +def Space(*args, **kwds): + space = std.Space(*args, **kwds) + space.createexecutioncontext = createexecutioncontextmaker( + space, space.createexecutioncontext) + space.getexecutioncontext().w_reflectivespace = None # patch the already built ec + patch_space_in_place(space, 'reflective', proxymaker) + w___pypy__ = space.getbuiltinmodule("__pypy__") + space.setattr(w___pypy__, space.wrap('set_reflectivespace'), + space.wrap(app_set_reflectivespace)) + return space + Added: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 16 00:03:21 2008 @@ -0,0 +1,26 @@ +from pypy.conftest import gettestobjspace + +class AppTest_Reflective: + + def setup_class(cls): + cls.space = gettestobjspace('reflective') + + def test_add(self): + from __pypy__ import set_reflectivespace + class Space: + def add(self, x, y): + return 40+2 + + set_reflectivespace(Space()) + assert 1+2 == 42 + + set_reflectivespace(None) + assert 1+2 == 3 + + def test_default_behaviour(self): + from __pypy__ import set_reflectivespace + class Space: + pass + + set_reflectivespace(Space()) + assert 1+2 == 3 From arigo at codespeak.net Wed Jan 16 11:00:54 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 11:00:54 +0100 (CET) Subject: [pypy-svn] r50657 - pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test Message-ID: <20080116100054.91DDD1684D6@codespeak.net> Author: arigo Date: Wed Jan 16 11:00:52 2008 New Revision: 50657 Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Log: Fix test. Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test__rawffi.py Wed Jan 16 11:00:52 2008 @@ -446,10 +446,10 @@ "<_rawffi.Structure 'x' 'yz' (%d, %d)>" % (2*s, s)) s = _rawffi.Structure([('x', 'i'), ('yz', 'i')])() - assert repr(s) == "<_rawffi struct %d>" % (s.buffer,) + assert repr(s) == "<_rawffi struct %x>" % (s.buffer,) s.free() a = _rawffi.Array('i')(5) - assert repr(a) == "<_rawffi array %d of length %d>" % (a.buffer, + assert repr(a) == "<_rawffi array %x of length %d>" % (a.buffer, len(a)) a.free() From cfbolz at codespeak.net Wed Jan 16 11:04:04 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 16 Jan 2008 11:04:04 +0100 (CET) Subject: [pypy-svn] r50658 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080116100404.B6C471684D4@codespeak.net> Author: cfbolz Date: Wed Jan 16 11:04:03 2008 New Revision: 50658 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: (all): planning for today Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Wed Jan 16 11:04:03 2008 @@ -11,18 +11,23 @@ - look at the RPython microbenchmarks for Java DONE, fixed sized-lists are slow - - work on CTypes (Carl Friedrich, Armin) + - work on CTypes more general non-progress + nested structure and arrays of structure support in rawffi - think about summarizing test outcomes - JVM integration (probably only when Anto is here) - look at the CLI integration on the clr-module-improvements/ branch and - maybe improve/merge it? SOME PROGRESS, we gave up because python.net wasn't - working correctly (Anto, Paul) + maybe improve/merge it? DONE, branch is to be merged - implement fixed-size lists as arrays in the ootypesystem (Carl Friedrich, - Toby) IN PROGRESS, jvm backend supported, minor problems - + Toby) IN PROGRESS, jvm backend supported, more minor problems + java bytecode verifier complains + + - give a JIT code walkthrough (Armin) + + - start writing more unit-style tests for the JIT (Armin, Anto, Maciek) + - explore the parsers a bit (Toby, Carl Friedrich) From fijal at codespeak.net Wed Jan 16 13:10:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 13:10:42 +0100 (CET) Subject: [pypy-svn] r50659 - in pypy/dist/pypy/rpython: . lltypesystem test Message-ID: <20080116121042.029FC1684DB@codespeak.net> Author: fijal Date: Wed Jan 16 13:10:41 2008 New Revision: 50659 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: (arigo, fijal) Fix casts: * longlong <-> ptr * 0 <-> ptr Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Wed Jan 16 13:10:41 2008 @@ -1767,6 +1767,8 @@ return ptr._cast_to_int() def cast_int_to_ptr(PTRTYPE, oddint): + if oddint == 0: + return nullptr(PTRTYPE.TO) assert oddint & 1, "only odd integers can be cast back to ptr" return _ptr(PTRTYPE, oddint, solid=True) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Wed Jan 16 13:10:41 2008 @@ -439,14 +439,12 @@ return llops.genop('cast_pointer', [v_value], resulttype = TGT) elif ORIG == llmemory.Address: return llops.genop('cast_adr_to_ptr', [v_value], resulttype = TGT) - elif isinstance(ORIG, lltype.Primitive) and ORIG in _cast_to_Signed: - op = _cast_to_Signed[ORIG] - if op: - v_value = llops.genop(op, [v_value], resulttype=lltype.Signed) + elif isinstance(ORIG, lltype.Primitive): + v_value = gen_cast(llops, lltype.Signed, v_value) return llops.genop('cast_int_to_ptr', [v_value], resulttype=TGT) elif TGT == llmemory.Address and isinstance(ORIG, lltype.Ptr): return llops.genop('cast_ptr_to_adr', [v_value], resulttype = TGT) - elif isinstance(TGT, lltype.Primitive) and TGT in _cast_from_Signed: + elif isinstance(TGT, lltype.Primitive): if isinstance(ORIG, lltype.Ptr): v_value = llops.genop('cast_ptr_to_int', [v_value], resulttype=lltype.Signed) @@ -456,10 +454,7 @@ else: raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT)) - op = _cast_from_Signed[TGT] - if op: - v_value = llops.genop(op, [v_value], resulttype=TGT) - return v_value + return gen_cast(llops, TGT, v_value) raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT)) def rtype_cast_ptr_to_int(hop): Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Wed Jan 16 13:10:41 2008 @@ -5,10 +5,10 @@ from pypy.rlib.debug import llinterpcall from pypy.rpython.lltypesystem import lltype from pypy.tool import udir -from pypy.rlib.rarithmetic import r_uint, intmask, r_longlong +from pypy.rlib.rarithmetic import r_uint, intmask, r_longlong, r_ulonglong from pypy.annotation.builtin import * from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin -from pypy.rpython.lltypesystem.rffi import SHORT +from pypy.rpython.lltypesystem import rffi from pypy.rpython import extfunc import py @@ -513,12 +513,21 @@ res = self.interpret(llf, [ord('x')], policy=LowLevelAnnotatorPolicy()) assert res == u'x' def llf(v): - return lltype.cast_primitive(SHORT, v) + return lltype.cast_primitive(rffi.SHORT, v) res = self.interpret(llf, [123], policy=LowLevelAnnotatorPolicy()) assert res == 123 - - + def test_cast(self): + def llfn(v): + return rffi.cast(rffi.VOIDP, v) + res = self.interpret(llfn, [r_ulonglong(0)]) + assert res == lltype.nullptr(rffi.VOIDP.TO) + def llfn(v): + return rffi.cast(rffi.LONGLONG, v) + res = self.interpret(llfn, [lltype.nullptr(rffi.VOIDP.TO)]) + assert res == 0 + assert isinstance(res, r_longlong) + class TestOOtype(BaseTestRbuiltin, OORtypeMixin): def test_instantiate_meta(self): From fijal at codespeak.net Wed Jan 16 13:15:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 13:15:03 +0100 (CET) Subject: [pypy-svn] r50660 - pypy/dist/pypy/rpython Message-ID: <20080116121503.F30C41684DB@codespeak.net> Author: fijal Date: Wed Jan 16 13:15:01 2008 New Revision: 50660 Modified: pypy/dist/pypy/rpython/rbuiltin.py Log: Add some operations which are recognized by a C backend. Still needs some tweaking Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Wed Jan 16 13:15:01 2008 @@ -397,20 +397,22 @@ return gen_cast(hop.llops, TGT, v_value) _cast_to_Signed = { - lltype.Signed: None, - lltype.Bool: 'cast_bool_to_int', - lltype.Char: 'cast_char_to_int', - lltype.UniChar: 'cast_unichar_to_int', - lltype.Float: 'cast_float_to_int', - lltype.Unsigned: 'cast_uint_to_int', + lltype.Signed: None, + lltype.Bool: 'cast_bool_to_int', + lltype.Char: 'cast_char_to_int', + lltype.UniChar: 'cast_unichar_to_int', + lltype.Float: 'cast_float_to_int', + lltype.Unsigned: 'cast_uint_to_int', + lltype.SignedLongLong: 'truncate_longlong_to_int', } _cast_from_Signed = { - lltype.Signed: None, - lltype.Bool: 'int_is_true', - lltype.Char: 'cast_int_to_char', - lltype.UniChar: 'cast_int_to_unichar', - lltype.Float: 'cast_int_to_float', - lltype.Unsigned: 'cast_int_to_uint', + lltype.Signed: None, + lltype.Bool: 'int_is_true', + lltype.Char: 'cast_int_to_char', + lltype.UniChar: 'cast_int_to_unichar', + lltype.Float: 'cast_int_to_float', + lltype.Unsigned: 'cast_int_to_uint', + lltype.SignedLongLong: 'cast_int_to_longlong', } def gen_cast(llops, TGT, v_value): ORIG = v_value.concretetype From fijal at codespeak.net Wed Jan 16 13:25:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 13:25:17 +0100 (CET) Subject: [pypy-svn] r50661 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080116122517.5BF031683D6@codespeak.net> Author: fijal Date: Wed Jan 16 13:25:15 2008 New Revision: 50661 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: Fix crappy tests to be more C-stylish Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Wed Jan 16 13:25:15 2008 @@ -216,9 +216,15 @@ def test_opaque_type(self): h_source = py.code.Source(""" + + #ifndef _OPAQUE_H_ + #define _OPAQUE_H_ + struct stuff { char data[38]; }; + + #endif """) c_source = py.code.Source(""" @@ -322,6 +328,15 @@ def eating_callback(self): h_source = py.code.Source(""" + #ifndef _CALLBACK_H_ + #define _CALLBACK_H_ + + int eating_callback(int arg, int(*call)(int)); + + #endif + """) + + c_source = py.code.Source(""" int eating_callback(int arg, int(*call)(int)) { int res = call(arg); @@ -329,13 +344,15 @@ return -1; return res; } + """) h_include = udir.join('callback.h') h_include.write(h_source) eci = ExternalCompilationInfo(includes=['callback.h'], - include_dirs=[str(udir)]) + include_dirs=[str(udir)], + separate_module_sources=[c_source]) args = [INT, CCallback([INT], INT)] eating_callback = llexternal('eating_callback', args, INT, From fijal at codespeak.net Wed Jan 16 13:28:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 13:28:23 +0100 (CET) Subject: [pypy-svn] r50662 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080116122823.0850616842C@codespeak.net> Author: fijal Date: Wed Jan 16 13:28:22 2008 New Revision: 50662 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Fix test Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Wed Jan 16 13:28:22 2008 @@ -680,10 +680,16 @@ def test_prebuilt_constant(self): header = py.code.Source(""" #include - + + #ifndef _SOME_H_H_ + #define _SOME_H_H_ + static int x = 3; - char **z = NULL; + char **z; + + #endif _SOME_H_H_ """) + h_file = udir.join("some_h.h") h_file.write(header) From arigo at codespeak.net Wed Jan 16 13:28:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:28:27 +0100 (CET) Subject: [pypy-svn] r50663 - pypy/dist/pypy/config Message-ID: <20080116122827.A6A40168430@codespeak.net> Author: arigo Date: Wed Jan 16 13:28:27 2008 New Revision: 50663 Added: pypy/dist/pypy/config/pypyoption.py.merge.tmp - copied, changed from r50660, pypy/dist/pypy/config/pypyoption.py Log: The _ffi module needs the interp-level struct module because the default app-level struct has no support for 'P'. From arigo at codespeak.net Wed Jan 16 13:28:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:28:31 +0100 (CET) Subject: [pypy-svn] r50664 - pypy/dist/pypy/rlib Message-ID: <20080116122831.06B0A168480@codespeak.net> Author: arigo Date: Wed Jan 16 13:28:30 2008 New Revision: 50664 Added: pypy/dist/pypy/rlib/libffi.py.merge.tmp - copied, changed from r50660, pypy/dist/pypy/rlib/libffi.py Log: (fijal, arigo) Refactor libffi.py to add a lower-level interface: RawFuncPtr. [merging of /branch/applevel-ctypes2/pypy/rlib/libffi.py revisions 50343 to 50660] From arigo at codespeak.net Wed Jan 16 13:28:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:28:34 +0100 (CET) Subject: [pypy-svn] r50665 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080116122834.3C5851684D3@codespeak.net> Author: arigo Date: Wed Jan 16 13:28:33 2008 New Revision: 50665 Added: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py.merge.tmp - copied, changed from r50660, pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: (fijal, arigo) ctypes bites again. Bug test and fix. [merging of /branch/applevel-ctypes2/pypy/rpython/lltypesystem/ll2ctypes.py revisions 50343 to 50660] From arigo at codespeak.net Wed Jan 16 13:30:48 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:30:48 +0100 (CET) Subject: [pypy-svn] r50666 - in pypy/dist/pypy: config doc/config interpreter interpreter/test lib module/_ffi module/_rawffi module/fcntl rlib rlib/test rpython/lltypesystem rpython/lltypesystem/test Message-ID: <20080116123048.DDD4416842C@codespeak.net> Author: arigo Date: Wed Jan 16 13:30:48 2008 New Revision: 50666 Added: pypy/dist/pypy/config/pypyoption.py - copied unchanged from r50665, pypy/dist/pypy/config/pypyoption.py.merge.tmp pypy/dist/pypy/doc/config/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/doc/config/ pypy/dist/pypy/interpreter/baseobjspace.py - copied unchanged from r50665, pypy/branch/applevel-ctypes2/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/gateway.py - copied unchanged from r50665, pypy/branch/applevel-ctypes2/pypy/interpreter/gateway.py pypy/dist/pypy/interpreter/test/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/interpreter/test/ pypy/dist/pypy/lib/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/lib/ pypy/dist/pypy/module/_ffi/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/module/_ffi/ pypy/dist/pypy/module/_rawffi/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/module/_rawffi/ pypy/dist/pypy/module/fcntl/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/module/fcntl/ pypy/dist/pypy/rlib/libffi.py - copied unchanged from r50665, pypy/dist/pypy/rlib/libffi.py.merge.tmp pypy/dist/pypy/rlib/rarithmetic.py - copied unchanged from r50665, pypy/branch/applevel-ctypes2/pypy/rlib/rarithmetic.py pypy/dist/pypy/rlib/rbigint.py - copied unchanged from r50665, pypy/branch/applevel-ctypes2/pypy/rlib/rbigint.py pypy/dist/pypy/rlib/test/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/rlib/test/ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py - copied unchanged from r50665, pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py.merge.tmp pypy/dist/pypy/rpython/lltypesystem/test/ - copied from r50665, pypy/branch/applevel-ctypes2/pypy/rpython/lltypesystem/test/ Removed: pypy/dist/pypy/config/pypyoption.py.merge.tmp pypy/dist/pypy/rlib/libffi.py.merge.tmp pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py.merge.tmp Log: (cfbolz, fijal, arigo) Merge the applevel-ctypes2 branch. This contains a reasonably promizing pure app-level ctypes approach. From arigo at codespeak.net Wed Jan 16 13:32:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:32:14 +0100 (CET) Subject: [pypy-svn] r50667 - in pypy/branch: applevel-ctypes applevel-ctypes2 Message-ID: <20080116123214.6D9DD16842C@codespeak.net> Author: arigo Date: Wed Jan 16 13:32:13 2008 New Revision: 50667 Removed: pypy/branch/applevel-ctypes/ pypy/branch/applevel-ctypes2/ Log: (fijal, arigo) Remove branches. From arigo at codespeak.net Wed Jan 16 13:41:46 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:41:46 +0100 (CET) Subject: [pypy-svn] r50668 - pypy/dist/pypy/doc Message-ID: <20080116124146.2A6FA16842C@codespeak.net> Author: arigo Date: Wed Jan 16 13:41:45 2008 New Revision: 50668 Removed: pypy/dist/pypy/doc/contact.html pypy/dist/pypy/doc/news.html Modified: pypy/dist/pypy/doc/redirections pypy/dist/pypy/doc/test_redirections.py Log: Generate news.html and contact.html by using 'redirections'. hpk: feel free to revert if there was a reason for which you didn't do that in the first place. Modified: pypy/dist/pypy/doc/redirections ============================================================================== --- pypy/dist/pypy/doc/redirections (original) +++ pypy/dist/pypy/doc/redirections Wed Jan 16 13:41:45 2008 @@ -33,5 +33,7 @@ 'draft-low-level-encapsulation.html': 'low-level-encapsulation.html', 'draft-memory-management-threading-model.html': 'translation-aspects.html', 'proxy.html': 'objspace-proxies.html#tproxy', + 'news.html': 'home.html', + 'contact.html': 'home.html', } Modified: pypy/dist/pypy/doc/test_redirections.py ============================================================================== --- pypy/dist/pypy/doc/test_redirections.py (original) +++ pypy/dist/pypy/doc/test_redirections.py Wed Jan 16 13:41:45 2008 @@ -40,13 +40,13 @@ oldpath.write(""" + content="0 ; URL=%s" /> - + X

- you should be redirected to + you should be automatically redirected to %s

From arigo at codespeak.net Wed Jan 16 13:47:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:47:12 +0100 (CET) Subject: [pypy-svn] r50669 - pypy/dist/pypy/doc Message-ID: <20080116124712.7FA51168434@codespeak.net> Author: arigo Date: Wed Jan 16 13:47:12 2008 New Revision: 50669 Modified: pypy/dist/pypy/doc/conftest.py Log: I *think* that generating the redirecting .html files by default is a good idea. Not sure why it wasn't enabled so far. Maybe we should trim down 'redirection' a bit, too. Modified: pypy/dist/pypy/doc/conftest.py ============================================================================== --- pypy/dist/pypy/doc/conftest.py (original) +++ pypy/dist/pypy/doc/conftest.py Wed Jan 16 13:47:12 2008 @@ -8,7 +8,7 @@ option = py.test.config.addoptions("pypy-doc options", Option('--generate-redirections', action="store_true", dest="generateredirections", - default=False, help="Generate the redirecting HTML files"), + default=True, help="Generate the redirecting HTML files"), Option('--enable-doctests', action="store_true", dest="doctests", default=False, help="enable doctests in .txt files"), From arigo at codespeak.net Wed Jan 16 13:48:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:48:37 +0100 (CET) Subject: [pypy-svn] r50670 - pypy/dist/pypy/doc Message-ID: <20080116124837.DF2A1168434@codespeak.net> Author: arigo Date: Wed Jan 16 13:48:37 2008 New Revision: 50670 Modified: pypy/dist/pypy/doc/test_redirections.py Log: Checked in this line by mistake. Modified: pypy/dist/pypy/doc/test_redirections.py ============================================================================== --- pypy/dist/pypy/doc/test_redirections.py (original) +++ pypy/dist/pypy/doc/test_redirections.py Wed Jan 16 13:48:37 2008 @@ -44,7 +44,7 @@ - X +

you should be automatically redirected to %s From arigo at codespeak.net Wed Jan 16 13:52:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 13:52:38 +0100 (CET) Subject: [pypy-svn] r50671 - pypy/dist/pypy/doc Message-ID: <20080116125238.893FF168434@codespeak.net> Author: arigo Date: Wed Jan 16 13:52:37 2008 New Revision: 50671 Modified: pypy/dist/pypy/doc/redirections Log: Trim down this file. Most entries are from 2005 or older; only the last three ones are worth keeping, I guess. Modified: pypy/dist/pypy/doc/redirections ============================================================================== --- pypy/dist/pypy/doc/redirections (original) +++ pypy/dist/pypy/doc/redirections Wed Jan 16 13:52:37 2008 @@ -1,37 +1,5 @@ # please make sure this is evaluable { - 'restrictedpy.html': 'coding-guide.html#restricted-python', - 'testdesign.html' : 'coding-guide.html#test-design', - - 'stdobjspace.html' : 'objspace.html#the-standard-object-space', - 'objspaceinterface.html': 'objspace.html#object-space-interface', - 'annotateobjspace.html' : 'objspace.html#the-flow-object-space', - 'wrapping.html' : 'objspace.html#wrapping-rules', - 'abstractobjspace.html' : 'theory.html#abstract-interpretation', - 'multimethod.html' : 'theory.html#multimethods', - - 'howtopypy.html' : 'getting-started.html#howtopypy', - 'howtosvn.html' : 'getting-started.html#howtosvn', - 'checking_ReST.html' : 'coding-guide.html#pypy-documentation', - 'optionaltools.html' : 'coding-guide.html#optionaltool', - - 'developers.html' : 'contributor.html', - 'goals.html' : 'architecture.html', - - 'annotation.html' : 'translation.html#annotator', - 'basicblock.asc' : 'objspace.html#the-flow-model', - - 'coding-style.html' : 'coding-guide.html', - - 'controlflow.html' : 'objspace.html#the-flow-model', - - 'getting_started.html' : 'getting-started.html', - 'getting_started.html#howtopypy' : 'getting-started.html#howtopypy', - 'getting_started.html#howtosvn' : 'getting-started.html#howtosvn', - - 'draft-dynamic-language-translation.html': 'dynamic-language-translation.html', - 'draft-low-level-encapsulation.html': 'low-level-encapsulation.html', - 'draft-memory-management-threading-model.html': 'translation-aspects.html', 'proxy.html': 'objspace-proxies.html#tproxy', 'news.html': 'home.html', 'contact.html': 'home.html', From fijal at codespeak.net Wed Jan 16 15:22:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 15:22:45 +0100 (CET) Subject: [pypy-svn] r50672 - in pypy/dist/pypy/module/struct: . test Message-ID: <20080116142245.35552168439@codespeak.net> Author: fijal Date: Wed Jan 16 15:22:43 2008 New Revision: 50672 Modified: pypy/dist/pypy/module/struct/ieee.py pypy/dist/pypy/module/struct/test/test_ieee.py Log: (arigo, fijal) Fix unpacking/packing for inf/nan, very obscure Modified: pypy/dist/pypy/module/struct/ieee.py ============================================================================== --- pypy/dist/pypy/module/struct/ieee.py (original) +++ pypy/dist/pypy/module/struct/ieee.py Wed Jan 16 15:22:43 2008 @@ -3,12 +3,7 @@ """ import math -from pypy.rlib.rarithmetic import r_longlong - - -def sane_float(man,e): - # TODO: XXX Implement checks for floats - return True +from pypy.rlib.rarithmetic import r_longlong, isinf, isnan, INFINITY, NAN def pack_float(result, number, size, bigendian): """Append to 'result' the 'size' characters of the 32-bit or 64-bit @@ -22,45 +17,49 @@ bias = 1023 exp = 11 prec = 52 - if number < 0: + + if isnan(number): sign = 0x80 - number *= -1 - elif number == 0.0: - for i in range(size): - result.append('\x00') - return + man, e = 1.5, 1024 else: - sign = 0x00 + if number < 0: + sign = 0x80 + number *= -1 + elif number == 0.0: + for i in range(size): + result.append('\x00') + return + else: + sign = 0x00 + if isinf(number): + man, e = 1.0, 1024 + else: + man, e = math.frexp(number) - man, e = math.frexp(number) if 0.5 <= man and man < 1.0: man *= 2 e -= 1 - if sane_float(man,e): - man -= 1 - e += bias - power_of_two = r_longlong(1) << prec - mantissa = r_longlong(power_of_two * man + 0.5) - if mantissa >> prec : - mantissa = 0 - e += 1 - - for i in range(size-2): - result.append(chr(mantissa & 0xff)) - mantissa >>= 8 - x = (mantissa & ((1<<(15-exp))-1)) | ((e & ((1<<(exp-7))-1))<<(15-exp)) - result.append(chr(x)) - x = sign | e >> (exp - 7) - result.append(chr(x)) - if bigendian: - first = len(result) - size - last = len(result) - 1 - for i in range(size // 2): - (result[first + i], result[last - i]) = ( - result[last - i], result[first + i]) - #else: - # ... - + man -= 1 + e += bias + power_of_two = r_longlong(1) << prec + mantissa = r_longlong(power_of_two * man + 0.5) + if mantissa >> prec : + mantissa = 0 + e += 1 + + for i in range(size-2): + result.append(chr(mantissa & 0xff)) + mantissa >>= 8 + x = (mantissa & ((1<<(15-exp))-1)) | ((e & ((1<<(exp-7))-1))<<(15-exp)) + result.append(chr(x)) + x = sign | e >> (exp - 7) + result.append(chr(x)) + if bigendian: + first = len(result) - size + last = len(result) - 1 + for i in range(size // 2): + (result[first + i], result[last - i]) = ( + result[last - i], result[first + i]) def unpack_float(input, bigendian): """Interpret the 'input' string into a 32-bit or 64-bit @@ -99,6 +98,12 @@ e -= bias e += 1 sign = bytes[-1] & 0x80 - number = math.ldexp(mantissa,e) + if e == 1025: + if mantissa == 0.5: + number = INFINITY + else: + return NAN + else: + number = math.ldexp(mantissa,e) if sign : number = -number return number Modified: pypy/dist/pypy/module/struct/test/test_ieee.py ============================================================================== --- pypy/dist/pypy/module/struct/test/test_ieee.py (original) +++ pypy/dist/pypy/module/struct/test/test_ieee.py Wed Jan 16 15:22:43 2008 @@ -1,5 +1,5 @@ from pypy.module.struct.ieee import pack_float, unpack_float - +from pypy.rlib.rarithmetic import isnan testcases = [ (-0.025, 4, False, '\xcd\xcc\xcc\xbc'), @@ -10,9 +10,28 @@ (2.0 ** 100, 8, False, '\x00\x00\x00\x00\x00\x000F'), (0.0, 8, True, '\x00\x00\x00\x00\x00\x00\x00\x00'), (-123456789, 8, True, '\xc1\x9do4T\x00\x00\x00'), + (1e200*1e200, 8, False, '\x00\x00\x00\x00\x00\x00\xf0\x7f'), + (-1e200*1e200, 8, False, '\x00\x00\x00\x00\x00\x00\xf0\xff'), + ((1e200*1e200)/(1e200*1e200), 8, False, '\x00\x00\x00\x00\x00\x00\xf8\xff') ] +def test_correct_tests(): + import struct + for number, size, bigendian, expected in testcases: + if bigendian: + fmt = '>' + else: + fmt = '<' + if size == 4: + fmt += 'f' + else: + fmt += 'd' + res, = struct.unpack(fmt, expected) + assert (isnan(res) and isnan(number)) or \ + res == number or abs(res - number) < 1E-6 + assert struct.pack(fmt, number) == expected + def test_pack(): for number, size, bigendian, expected in testcases: print 'test_pack:', number, size, bigendian @@ -26,10 +45,13 @@ print 'test_unpack:', expected, size, bigendian assert len(input) == size res = unpack_float(input, bigendian) - if size == 8: - assert res == expected # exact result expected + if isnan(res) and isnan(expected): + pass else: - assert abs(res - expected) < 1E-6 + if size == 8: + assert res == expected # exact result expected + else: + assert abs(res - expected) < 1E-6 def test_llinterpreted(): From fijal at codespeak.net Wed Jan 16 15:26:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 15:26:49 +0100 (CET) Subject: [pypy-svn] r50673 - in pypy/dist/pypy/module/struct: . test Message-ID: <20080116142649.1D7B9168439@codespeak.net> Author: fijal Date: Wed Jan 16 15:26:48 2008 New Revision: 50673 Modified: pypy/dist/pypy/module/struct/ieee.py pypy/dist/pypy/module/struct/test/test_ieee.py Log: (arigo, fijal) Fix this also for single precision floats Modified: pypy/dist/pypy/module/struct/ieee.py ============================================================================== --- pypy/dist/pypy/module/struct/ieee.py (original) +++ pypy/dist/pypy/module/struct/ieee.py Wed Jan 16 15:26:48 2008 @@ -20,7 +20,7 @@ if isnan(number): sign = 0x80 - man, e = 1.5, 1024 + man, e = 1.5, bias + 1 else: if number < 0: sign = 0x80 @@ -32,7 +32,7 @@ else: sign = 0x00 if isinf(number): - man, e = 1.0, 1024 + man, e = 1.0, bias + 1 else: man, e = math.frexp(number) @@ -98,7 +98,7 @@ e -= bias e += 1 sign = bytes[-1] & 0x80 - if e == 1025: + if e == bias + 2: if mantissa == 0.5: number = INFINITY else: Modified: pypy/dist/pypy/module/struct/test/test_ieee.py ============================================================================== --- pypy/dist/pypy/module/struct/test/test_ieee.py (original) +++ pypy/dist/pypy/module/struct/test/test_ieee.py Wed Jan 16 15:26:48 2008 @@ -10,6 +10,9 @@ (2.0 ** 100, 8, False, '\x00\x00\x00\x00\x00\x000F'), (0.0, 8, True, '\x00\x00\x00\x00\x00\x00\x00\x00'), (-123456789, 8, True, '\xc1\x9do4T\x00\x00\x00'), + (1e200*1e200, 4, False, '\x00\x00\x80\x7f'), + (-1e200*1e200, 4, False, '\x00\x00\x80\xff'), + ((1e200*1e200)/(1e200*1e200), 4, False, '\x00\x00\xc0\xff'), (1e200*1e200, 8, False, '\x00\x00\x00\x00\x00\x00\xf0\x7f'), (-1e200*1e200, 8, False, '\x00\x00\x00\x00\x00\x00\xf0\xff'), ((1e200*1e200)/(1e200*1e200), 8, False, '\x00\x00\x00\x00\x00\x00\xf8\xff') @@ -27,10 +30,10 @@ fmt += 'f' else: fmt += 'd' + assert struct.pack(fmt, number) == expected res, = struct.unpack(fmt, expected) assert (isnan(res) and isnan(number)) or \ res == number or abs(res - number) < 1E-6 - assert struct.pack(fmt, number) == expected def test_pack(): for number, size, bigendian, expected in testcases: @@ -51,7 +54,7 @@ if size == 8: assert res == expected # exact result expected else: - assert abs(res - expected) < 1E-6 + assert res == expected or abs(res - expected) < 1E-6 def test_llinterpreted(): From antocuni at codespeak.net Wed Jan 16 16:20:08 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jan 2008 16:20:08 +0100 (CET) Subject: [pypy-svn] r50674 - in pypy/dist/pypy: jit/codegen jit/codegen/llgraph jit/codegen/llgraph/test jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator Message-ID: <20080116152008.D3756168472@codespeak.net> Author: antocuni Date: Wed Jan 16 16:20:07 2008 New Revision: 50674 Modified: pypy/dist/pypy/jit/codegen/graph2rgenop.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_graph2rgenop.py pypy/dist/pypy/jit/timeshifter/exception.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/rpython/typesystem.py pypy/dist/pypy/translator/simplify.py Log: (antocuni, arigo) whack and hack until test_timeshift.test_very_simple passes for ootype Modified: pypy/dist/pypy/jit/codegen/graph2rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/graph2rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/graph2rgenop.py Wed Jan 16 16:20:07 2008 @@ -7,7 +7,7 @@ import random -def rcompile(rgenop, entrypoint, argtypes, random_seed=0): +def rcompile(rgenop, entrypoint, argtypes, random_seed=0, type_system='lltype'): from pypy.translator.translator import TranslationContext from pypy.annotation.policy import AnnotatorPolicy from pypy import conftest @@ -15,7 +15,7 @@ policy = AnnotatorPolicy() policy.allow_someobjects = False t.buildannotator(policy=policy).build_types(entrypoint, argtypes) - t.buildrtyper().specialize() + t.buildrtyper(type_system = type_system).specialize() # note that backend optimizations will constant-fold simple operations, # which is required by some backends that don't accept calls like 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 Wed Jan 16 16:20:07 2008 @@ -5,13 +5,14 @@ """ from pypy.rpython.lltypesystem import lltype, llmemory, rtupletype +from pypy.rpython.ootypesystem import ootype from pypy.objspace.flow import model as flowmodel from pypy.translator.simplify import eliminate_empty_blocks from pypy.translator.unsimplify import varoftype -from pypy.rpython.module.support import LLSupport +from pypy.rpython.module.support import LLSupport, OOSupport from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.llinterp import LLInterpreter -from pypy.rpython.lltypesystem.rclass import fishllattr +from pypy.rpython.rclass import fishllattr from pypy.rpython.lltypesystem.lloperation import llop def _from_opaque(opq): @@ -34,11 +35,18 @@ block = flowmodel.Block([]) return _to_opaque(block) +def from_opaque_string(s): + if isinstance(s, str): + return s + elif isinstance(s, ootype._string): + return OOSupport.from_rstr(s) + else: + return LLSupport.from_rstr(s) + def newgraph(gv_FUNCTYPE, name): FUNCTYPE = _from_opaque(gv_FUNCTYPE).value # 'name' is just a way to track things - if not isinstance(name, str): - name = LLSupport.from_rstr(name) + name = from_opaque_string(name) inputargs = [] erasedinputargs = [] for ARG in FUNCTYPE.ARGS: @@ -103,9 +111,8 @@ newvars = [] if not isinstance(vars, list): n = vars.ll_length() - vars = vars.ll_items() for i in range(n): - v = vars[i] + v = vars.ll_getitem_fast(i) if not v: v = dummy_placeholder else: @@ -156,8 +163,7 @@ 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) + opname = from_opaque_string(opname) block = _from_opaque(block) assert block.exits == [], "block already closed" opvars = _inputvars(vars_gv) @@ -222,10 +228,15 @@ return _to_opaque(c) def _generalcast(T, value): - if isinstance(T, lltype.Ptr): + if lltype.typeOf(value) == T: + return value + elif isinstance(T, lltype.Ptr): return lltype.cast_pointer(T, value) elif T == llmemory.Address: return llmemory.cast_ptr_to_adr(value) + elif isinstance(T, ootype.StaticMethod): + fn = value._obj + return ootype._static_meth(T, graph=fn.graph, _callable=fn._callable) else: T1 = lltype.typeOf(value) if T1 is llmemory.Address: @@ -243,6 +254,8 @@ def revealconstrepr(gv_value): c = _from_opaque(gv_value) + # XXX: what to do with ootype? + #import pdb;pdb.set_trace() return LLSupport.to_rstr(repr(c.value)) def isconst(gv_value): @@ -654,12 +667,18 @@ else: # specialize as direct_call def specialize_call(self, hop): - FUNCTYPE = lltype.FuncType([r.lowleveltype for r in hop.args_r], - hop.r_result.lowleveltype) + ARGS = [r.lowleveltype for r in hop.args_r] + RESULT = hop.r_result.lowleveltype + if hop.rtyper.type_system.name == 'lltypesystem': + FUNCTYPE = lltype.FuncType(ARGS, RESULT) + funcptr = lltype.functionptr(FUNCTYPE, func.__name__, + _callable=func, _debugexc=True) + cfunc = hop.inputconst(lltype.Ptr(FUNCTYPE), funcptr) + else: + FUNCTYPE = ootype.StaticMethod(ARGS, RESULT) + sm = ootype._static_meth(FUNCTYPE, _name=func.__name__, _callable=func) + cfunc = hop.inputconst(FUNCTYPE, sm) args_v = hop.inputargs(*hop.args_r) - funcptr = lltype.functionptr(FUNCTYPE, func.__name__, - _callable=func, _debugexc=True) - cfunc = hop.inputconst(lltype.Ptr(FUNCTYPE), funcptr) return hop.genop('direct_call', [cfunc] + args_v, hop.r_result) # annotations 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 Wed Jan 16 16:20:07 2008 @@ -1,10 +1,11 @@ from pypy.rlib.objectmodel import specialize from pypy.rlib.debug import ll_assert from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.llgraph import llimpl -from pypy.rpython.lltypesystem.rclass import fishllattr +from pypy.rpython.rclass import fishllattr from pypy.rpython.module.support import LLSupport @@ -380,6 +381,19 @@ place.absorbed = True return place.v +def getfieldtype(T, name): + if isinstance(T, ootype.OOType): + _, TYPE = T._lookup_field(name) + return TYPE + else: + assert name in T._flds + return getattr(T, name) + +def getptr(T): + if isinstance(T, ootype.OOType): + return T + else: + return lltype.Ptr(T) class RGenOp(AbstractRGenOp): gv_Void = gv_Void @@ -410,19 +424,18 @@ @staticmethod @specialize.memo() def fieldToken(T, name): - assert name in T._flds - FIELDTYPE = getattr(T, name) + FIELDTYPE = getfieldtype(T, name) if isinstance(FIELDTYPE, lltype.ContainerType): - FIELDTYPE = lltype.Ptr(FIELDTYPE) + FIELDTYPE = getptr(FIELDTYPE) return (LLConst(llimpl.constFieldName(name)), - gv_TYPE(lltype.Ptr(T)), + gv_TYPE(getptr(T)), gv_TYPE(FIELDTYPE)) @staticmethod @specialize.memo() def allocToken(TYPE): return (gv_TYPE(TYPE), - gv_TYPE(lltype.Ptr(TYPE))) + gv_TYPE(getptr(TYPE))) varsizeAllocToken = allocToken @@ -431,7 +444,7 @@ def arrayToken(A): ITEMTYPE = A.OF if isinstance(ITEMTYPE, lltype.ContainerType): - ITEMTYPE = lltype.Ptr(ITEMTYPE) + ITEMTYPE = getptr(ITEMTYPE) return gv_TYPE(ITEMTYPE) @staticmethod Modified: pypy/dist/pypy/jit/codegen/llgraph/test/test_graph2rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llgraph/test/test_graph2rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llgraph/test/test_graph2rgenop.py Wed Jan 16 16:20:07 2008 @@ -1,9 +1,9 @@ from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.jit.codegen.graph2rgenop import rcompile from pypy.jit.codegen.llgraph.rgenop import rgenop from pypy.jit.codegen.llgraph.llimpl import testgengraph - def demo(n): result = 1 while n > 1: @@ -12,11 +12,33 @@ n -= 1 return result +class BaseTest: + type_system = None + FuncType = None + Ptr = None + + def test_demo(self): + gv = rcompile(rgenop, demo, [int], type_system=self.type_system) + F1 = self.FuncType([lltype.Signed], lltype.Signed) + func = gv.revealconst(self.Ptr(F1)) + + res = testgengraph(self.deref(func).graph, [10]) + assert res == demo(10) == 945 + +class TestLLType(BaseTest): + type_system = 'lltype' + FuncType = lltype.FuncType + Ptr = lltype.Ptr + + def deref(self, ptr): + return ptr._obj + +class TestOOType(BaseTest): + type_system = 'ootype' + FuncType = ootype.StaticMethod -def test_demo(): - gv = rcompile(rgenop, demo, [int]) - F1 = lltype.FuncType([lltype.Signed], lltype.Signed) - ptr = gv.revealconst(lltype.Ptr(F1)) + def Ptr(self, x): + return x - res = testgengraph(ptr._obj.graph, [10]) - assert res == demo(10) == 945 + def deref(self, obj): + return obj Modified: pypy/dist/pypy/jit/timeshifter/exception.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/exception.py (original) +++ pypy/dist/pypy/jit/timeshifter/exception.py Wed Jan 16 16:20:07 2008 @@ -12,22 +12,30 @@ self.gv_excdata = RGenOp.constPrebuiltGlobal(self.exc_data_ptr) EXCDATA = self.etrafo.EXCDATA + LL_EXC_TYPE = self.etrafo.lltype_of_exception_type + LL_EXC_VALUE = self.etrafo.lltype_of_exception_value self.exc_type_token = RGenOp.fieldToken(EXCDATA, 'exc_type') self.exc_value_token = RGenOp.fieldToken(EXCDATA, 'exc_value') - self.exc_type_kind = RGenOp.kindToken(EXCDATA.exc_type) - self.exc_value_kind = RGenOp.kindToken(EXCDATA.exc_value) + self.exc_type_kind = RGenOp.kindToken(LL_EXC_TYPE) + self.exc_value_kind = RGenOp.kindToken(LL_EXC_VALUE) - LL_EXC_TYPE = EXCDATA.exc_type - LL_EXC_VALUE = EXCDATA.exc_value - - self.gv_null_exc_type = RGenOp.constPrebuiltGlobal( - lltype.nullptr(LL_EXC_TYPE.TO)) - self.gv_null_exc_value = RGenOp.constPrebuiltGlobal( - lltype.nullptr(LL_EXC_VALUE.TO)) - self.null_exc_type_box = rvalue.PtrRedBox(self.exc_type_kind, - self.gv_null_exc_type) - self.null_exc_value_box = rvalue.PtrRedBox(self.exc_value_kind, - self.gv_null_exc_value) + null_exc_type = self.etrafo.c_null_etype.value + null_exc_value = self.etrafo.c_null_evalue.value + self.gv_null_exc_type = RGenOp.constPrebuiltGlobal(null_exc_type) + self.gv_null_exc_value = RGenOp.constPrebuiltGlobal(null_exc_value) + + if hrtyper.rtyper.type_system.name == 'lltypesystem': + self.null_exc_type_box = rvalue.PtrRedBox(self.exc_type_kind, + self.gv_null_exc_type) + self.null_exc_value_box = rvalue.PtrRedBox(self.exc_value_kind, + self.gv_null_exc_value) + else: + # XXX: think more about exceptions + self.null_exc_type_box = rvalue.PtrRedBox(self.exc_type_kind, + RGenOp.constPrebuiltGlobal(llmemory.NULL)) + self.null_exc_value_box = rvalue.IntRedBox(self.exc_value_kind, + RGenOp.constPrebuiltGlobal(llmemory.NULL)) + self.lazy_exception_path = lazy_exception_path def _freeze_(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 Wed Jan 16 16:20:07 2008 @@ -47,35 +47,6 @@ t = annmodel.lltype_to_annotation(T) return a.typeannotation(t) -def hannotate(func, values, policy=None, inline=None, backendoptimize=False, - portal=None): - # build the normal ll graphs for ll_function - t = TranslationContext() - a = t.buildannotator() - argtypes = getargtypes(a, values) - a.build_types(func, argtypes) - rtyper = t.buildrtyper() - rtyper.specialize() - if inline: - auto_inlining(t, threshold=inline) - if backendoptimize: - from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(t, inline_threshold=inline or 0) - if portal is None: - portal = func - if hasattr(policy, "seetranslator"): - policy.seetranslator(t) - graph1 = graphof(t, portal) - # build hint annotator types - 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 - class TimeshiftingTests(object): RGenOp = LLRGenOp @@ -94,6 +65,46 @@ del cls._cache del cls._cache_order + def hannotate(self, func, values, policy=None, inline=None, backendoptimize=False, + portal=None): + # build the normal ll graphs for ll_function + t = TranslationContext() + a = t.buildannotator() + argtypes = getargtypes(a, values) + a.build_types(func, argtypes) + rtyper = t.buildrtyper(type_system = self.type_system) + rtyper.specialize() + if inline: + auto_inlining(t, threshold=inline) + if backendoptimize: + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t, inline_threshold=inline or 0) + if portal is None: + portal = func + + policy = self.fixpolicy(policy) + if hasattr(policy, "seetranslator"): + policy.seetranslator(t) + graph1 = graphof(t, portal) + # build hint annotator types + 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 + + def fixpolicy(self, policy): + import copy + if self.type_system == 'ootype' and policy is not None: + newpolicy = copy.copy(policy) + newpolicy.oopspec = False + return newpolicy + else: + return policy + def timeshift_cached(self, ll_function, values, inline=None, policy=None, check_raises='ignored anyway', backendoptimize=False): @@ -115,9 +126,9 @@ 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, - backendoptimize=backendoptimize) + hs, ha, rtyper = self.hannotate(ll_function, values, + inline=inline, policy=policy, + backendoptimize=backendoptimize) # make the timeshifted graphs hrtyper = HintRTyper(ha, rtyper, self.RGenOp) @@ -367,7 +378,7 @@ assert count == expected_count -class TestTimeshift(TimeshiftingTests): +class BaseTestTimeshift(TimeshiftingTests): def test_simple_fixed(self): py.test.skip("green return not working") @@ -1778,3 +1789,11 @@ hint(None, global_merge_point=True) return g(n) py.test.raises(AssertionError, self.timeshift, f, [7], []) + +class TestLLType(BaseTestTimeshift): + type_system = 'lltype' + +# skip it for now, only test_very_simple works +class xTestOOType(BaseTestTimeshift): + type_system = 'ootype' + Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed Jan 16 16:20:07 2008 @@ -8,8 +8,10 @@ from pypy.annotation.policy import AnnotatorPolicy, Sig from pypy.annotation.specialize import flatten_star_args from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.rpython import extregistry from pypy.objspace.flow.model import Constant +from pypy.translator.simplify import get_functype class KeyComp(object): def __init__(self, val): @@ -175,13 +177,19 @@ return Constant(p, lltype.typeOf(p)) 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 - name = "delayed!%s" % (graph.name,) - delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True) + if self.rtyper.type_system.name == 'lltypesystem': + 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 + name = "delayed!%s" % (graph.name,) + delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True) + else: + if FUNCTYPE is None: + FUNCTYPE = ootype.ForwardReference() + name = "delayed!%s" % (graph.name,) + delayedptr = ootype._forward_static_meth(FUNCTYPE, _name=name) self.delayedfuncs.append((delayedptr, graph)) return delayedptr @@ -270,9 +278,9 @@ for p, graph in self.delayedfuncs: self.newgraphs[graph] = True real_p = rtyper.getcallable(graph) - REAL = lltype.typeOf(real_p).TO - FUNCTYPE = lltype.typeOf(p).TO - if isinstance(FUNCTYPE, lltype.ForwardReference): + REAL = get_functype(lltype.typeOf(real_p)) + FUNCTYPE = get_functype(lltype.typeOf(p)) + if isinstance(FUNCTYPE, (lltype.ForwardReference, ootype.ForwardReference)): FUNCTYPE.become(REAL) assert FUNCTYPE == REAL p._become(real_p) @@ -320,9 +328,10 @@ p = self.instance.llfnptr TYPE = lltype.typeOf(p) c_func = Constant(p, TYPE) - for r_arg, ARGTYPE in zip(args_r, TYPE.TO.ARGS): + FUNCTYPE = get_functype(TYPE) + for r_arg, ARGTYPE in zip(args_r, FUNCTYPE.ARGS): assert r_arg.lowleveltype == ARGTYPE - assert r_res.lowleveltype == TYPE.TO.RESULT + assert r_res.lowleveltype == FUNCTYPE.RESULT hop.exception_is_here() return hop.genop('direct_call', [c_func] + vlist, resulttype = r_res) Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Wed Jan 16 16:20:07 2008 @@ -720,24 +720,6 @@ # ____________________________________________________________ -_missing = object() - -def fishllattr(inst, name, default=_missing): - p = widest = lltype.normalizeptr(inst) - while True: - try: - return getattr(p, 'inst_' + name) - except AttributeError: - pass - try: - p = p.super - except AttributeError: - break - if default is _missing: - 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: Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Wed Jan 16 16:20:07 2008 @@ -31,6 +31,18 @@ raise TypeError +class ForwardReference(OOType): + def become(self, realtype): + if not isinstance(realtype, OOType): + raise TypeError("ForwardReference can only be to an OOType, " + "not %r" % (realtype,)) + self.__class__ = realtype.__class__ + self.__dict__ = realtype.__dict__ + + def __hash__(self): + raise TypeError("%r object is not hashable" % self.__class__.__name__) + + class Class(OOType): def _defl(self): @@ -219,7 +231,6 @@ raise NotImplementedError class StaticMethod(SpecializableType): - __slots__ = ['_null'] def __init__(self, args, result): self.ARGS = tuple(args) @@ -924,9 +935,10 @@ class _static_meth(_callable): + allowed_types = (StaticMethod,) def __init__(self, STATICMETHOD, **attrs): - assert isinstance(STATICMETHOD, StaticMethod) + assert isinstance(STATICMETHOD, self.allowed_types) _callable.__init__(self, STATICMETHOD, **attrs) def __call__(self, *args): @@ -936,6 +948,18 @@ def __repr__(self): return 'sm %s' % self._name +class _forward_static_meth(_static_meth): + allowed_types = (StaticMethod, ForwardReference) + + def __eq__(self, other): + return self is other + + def __hash__(self): + return id(self) + + def _become(self, other): + assert isinstance(other, _static_meth) + self.__dict__ = other.__dict__ class _bound_meth(object): def __init__(self, DEFINST, inst, meth): Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jan 16 16:20:07 2008 @@ -193,3 +193,33 @@ def rtype_new_instance(rtyper, classdef, llops, classcallhop=None): rinstance = getinstancerepr(rtyper, classdef) return rinstance.new_instance(llops, classcallhop) + + +_missing = object() + +def fishllattr(inst, name, default=_missing): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.ootypesystem import ootype + if isinstance(inst, (ootype._instance, ootype._view)): + # XXX: we need to call ootypesystem.rclass.mangle, but we + # can't because we don't have a config object + mangled = 'o' + name + if default is _missing: + return getattr(inst, mangled) + else: + return getattr(inst, mangled, default) + else: + p = widest = lltype.normalizeptr(inst) + while True: + try: + return getattr(p, 'inst_' + name) + except AttributeError: + pass + try: + p = p.super + except AttributeError: + break + if default is _missing: + raise AttributeError("%s has no field %s" % (lltype.typeOf(widest), + name)) + return default 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 Jan 16 16:20:07 2008 @@ -1,5 +1,5 @@ from pypy.rpython.lltypesystem.lltype import * -from pypy.rpython.lltypesystem.rclass import OBJECTPTR, fishllattr +from pypy.rpython.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 Modified: pypy/dist/pypy/rpython/typesystem.py ============================================================================== --- pypy/dist/pypy/rpython/typesystem.py (original) +++ pypy/dist/pypy/rpython/typesystem.py Wed Jan 16 16:20:07 2008 @@ -153,6 +153,9 @@ vlist = hop.inputargs(repr) return hop.genop('oononnull', vlist, resulttype=ootype.Bool) + def getconcretetype(self, v): + return v.concretetype + def null_callable(self, T): return ootype.null(T) Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Wed Jan 16 16:20:07 2008 @@ -25,7 +25,7 @@ def get_functype(TYPE): if isinstance(TYPE, lltype.Ptr): return TYPE.TO - elif isinstance(TYPE, ootype.StaticMethod): + elif isinstance(TYPE, (ootype.StaticMethod, ootype.ForwardReference)): return TYPE assert False From arigo at codespeak.net Wed Jan 16 16:59:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 16:59:33 +0100 (CET) Subject: [pypy-svn] r50676 - pypy/dist/pypy/jit/codegen/demo Message-ID: <20080116155933.6E64B168472@codespeak.net> Author: arigo Date: Wed Jan 16 16:59:33 2008 New Revision: 50676 Added: pypy/dist/pypy/jit/codegen/demo/asm386.py (contents, props changed) Log: Convert a tool I had for a long time in my working copy to a demo. Added: pypy/dist/pypy/jit/codegen/demo/asm386.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/demo/asm386.py Wed Jan 16 16:59:33 2008 @@ -0,0 +1,57 @@ +#! /usr/bin/env python +""" +A demo using the ri386 module to assemble instructions. +""" + +from pypy.jit.codegen.i386.ri386 import * + +class CodeBuilder(I386CodeBuilder): + def __init__(self): + self.buffer = [] + + def write(self, data): + for c in data: + self.buffer.append(c) # extend the list of characters + + def tell(self): + return len(self.buffer) + + def getvalue(self): + return ''.join(self.buffer) + + def as_string(self): + lst = [] + for c in self.buffer: + lst.append('%02x' % ord(c)) + return ' '.join(lst) + + def dump(self): + print self.as_string() + del self.buffer[:] + + +def do(insn, *args): + s = CodeBuilder() + getattr(s, insn)(*args) + print '%24s ' % (s.as_string(),), + print insn, + for a in args: + print a, + print + + +do('PUSH', ebp) +do('MOV', ebp, esp) +do('MOV', ecx, mem(ebp, 12)) + +do('LEA', eax, memSIB(None, ecx, 2, 4)) + +do('SUB', esp, eax) +do('ADD', esp, eax) + +do('LEA', ecx, memSIB(edx, ecx, 2, 0)) + +do('CALL', mem(ebp, 8)) + +do('MOV', esp, ebp) + From antocuni at codespeak.net Wed Jan 16 19:27:27 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jan 2008 19:27:27 +0100 (CET) Subject: [pypy-svn] r50677 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20080116182727.D5AF01684DB@codespeak.net> Author: antocuni Date: Wed Jan 16 19:27:25 2008 New Revision: 50677 Added: pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py (contents, props changed) Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py Log: (antocuni, arigo) - unit tests for rvalue.py - make logic of learn_nonzeroness more precise Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/rvalue.py Wed Jan 16 19:27:25 2008 @@ -211,9 +211,9 @@ else: self.known_nonzero = True else: - if self.is_constant(): - ok = not self.genvar.revealconst(llmemory.Address) # ok if null - else: + if self.known_nonzero: + ok = False + elif not self.is_constant(): gv_null = jitstate.curbuilder.rgenop.genzeroconst(self.kind) self.setgenvar_hint(gv_null, known_nonzero=False) return ok Added: pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py Wed Jan 16 19:27:25 2008 @@ -0,0 +1,139 @@ +import py +from pypy.rpython.lltypesystem import lltype +from pypy.jit.timeshifter import rvalue +from pypy.jit.timeshifter import rcontainer +from pypy.jit.codegen.model import GenVar, GenConst + +class FakeJITState(object): + def __init__(self): + self.curbuilder = FakeBuilder() + +class FakeRGenOp(object): + def genzeroconst(self, kind): + if kind == "dummy pointer": + return FakeGenConst("NULL") + return FakeGenConst(0) + + @staticmethod + def kindToken(TYPE): + return TYPE + + @staticmethod + def fieldToken(TYPE, name): + return TYPE, name + + @staticmethod + def constPrebuiltGlobal(value): + return FakeGenConst(value) + + +class FakeBuilder(object): + ops_with_no_retval = set(['setfield']) + + def __init__(self): + self.ops = [] + self.varcount = 1 + self.rgenop = FakeRGenOp() + + def __getattr__(self, name): + if name.startswith('genop_'): + opname = name[len('genop_'):] + def genop_(*args): + if opname in self.ops_with_no_retval: + v = None + else: + v = FakeGenVar(self.varcount) + self.varcount += 1 + self.ops.append((opname, args, v)) + return v + genop_.func_name = name + return genop_ + else: + raise AttributeError, name + + +class FakeHRTyper(object): + RGenOp = FakeRGenOp + +class FakeGenVar(GenVar): + def __init__(self, count=0): + self.count=count + + def __repr__(self): + return "V%d" % self.count + + def __eq__(self, other): + return self.count == other.count + + +class FakeGenConst(GenConst): + def __init__(self, _value=None): + self._value = _value + + +def test_create_int_redbox_var(): + jitstate = FakeJITState() + gv = FakeGenVar() + box = rvalue.IntRedBox("dummy kind", gv) + assert not box.is_constant() + assert box.getgenvar(jitstate) is gv + gv2 = FakeGenVar() + box.setgenvar(gv2) # doesn't raises + assert box.getgenvar(jitstate) is gv2 + + +def test_create_int_redbox_const(): + jitstate = FakeJITState() + gv = FakeGenConst() + box = rvalue.IntRedBox("dummy kind", gv) + assert box.is_constant() + assert box.getgenvar(jitstate) is gv + gv2 = FakeGenVar() + py.test.raises(AssertionError, box.setgenvar, gv2) + +def test_forcevar(): + jitstate = FakeJITState() + gv = FakeGenVar() + intbox = rvalue.IntRedBox("dummy kind", gv) + assert intbox.forcevar(jitstate, rvalue.copy_memo(), False) is intbox + + doublebox = rvalue.DoubleRedBox("dummy kind", FakeGenConst()) + box2 = doublebox.forcevar(jitstate, rvalue.copy_memo(), False) + assert doublebox is not box2 + assert not box2.is_constant() + assert doublebox.genvar is not box2.genvar + +def test_learn_nonzeroness(): + jitstate = FakeJITState() + gv = FakeGenVar() + box = rvalue.PtrRedBox("dummy pointer", gv) + assert not box.known_nonzero + assert box.learn_nonzeroness(jitstate, True) + assert box.known_nonzero + + assert not box.learn_nonzeroness(jitstate, False) + assert box.learn_nonzeroness(jitstate, True) + + box = rvalue.PtrRedBox("dummy pointer", gv) + assert box.learn_nonzeroness(jitstate, False) + assert box.is_constant() + assert box.genvar._value == "NULL" + assert box.learn_nonzeroness(jitstate, False) + assert not box.learn_nonzeroness(jitstate, True) + +def test_box_get_set_field(): + jitstate = FakeJITState() + V0 = FakeGenVar() + box = rvalue.PtrRedBox("dummy pointer", V0) + STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) + desc = rcontainer.StructFieldDesc(FakeHRTyper(), lltype.Ptr(STRUCT), "foo", 0) + box2 = box.op_getfield(jitstate, desc) + V1 = box2.genvar + assert box.known_nonzero + assert jitstate.curbuilder.ops == [('getfield', ((STRUCT, 'foo'), V0), V1)] + + jitstate.curbuilder.ops = [] + V42 = FakeGenVar(42) + valuebox = rvalue.IntRedBox("dummy kind", V42) + box.op_setfield(jitstate, desc, valuebox) + assert jitstate.curbuilder.ops == [('setfield', ((STRUCT, 'foo'), V0, V42), None)] From antocuni at codespeak.net Wed Jan 16 20:19:42 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jan 2008 20:19:42 +0100 (CET) Subject: [pypy-svn] r50681 - in pypy/dist/pypy: jit/timeshifter/test rpython rpython/ootypesystem Message-ID: <20080116191942.C2CE5168509@codespeak.net> Author: antocuni Date: Wed Jan 16 20:19:40 2008 New Revision: 50681 Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/ootypesystem/ootype.py Log: - make test_convert_const_to_redbox passing on ootype - enable known to pass tests for ootype too 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 Jan 16 20:19:40 2008 @@ -1793,7 +1793,17 @@ class TestLLType(BaseTestTimeshift): type_system = 'lltype' -# skip it for now, only test_very_simple works -class xTestOOType(BaseTestTimeshift): +passing_ootype_tests = set([ + 'test_very_simple', + 'test_convert_const_to_redbox', + ]) +class TestOOType(BaseTestTimeshift): type_system = 'ootype' + def __getattribute__(self, name): + if name.startswith('test_') and name not in passing_ootype_tests: + def fn(): + py.test.skip("doesn't work yet") + return fn + else: + return object.__getattribute__(self, name) Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed Jan 16 20:19:40 2008 @@ -226,7 +226,10 @@ bk = self.rtyper.annotator.bookkeeper bk.immutablevalue(obj) - delayedptr = lltype._ptr(repr.lowleveltype, "delayed!") + if self.rtyper.type_system.name == 'lltypesystem': + delayedptr = lltype._ptr(repr.lowleveltype, "delayed!") + else: + delayedptr = ootype.make_instance(repr.lowleveltype) self.delayedconsts.append((delayedptr, repr, obj)) return delayedptr else: Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Wed Jan 16 20:19:40 2008 @@ -849,6 +849,11 @@ return res.__class__(res.DEFINST, _view(res.DEFINST, res.inst), res.meth) return res + def _become(self, other): + assert self._TYPE == other._TYPE + assert isinstance(other, _view) + self.__dict__['_inst'] = other._inst + def _instanceof(self, INSTANCE): return self._inst._instanceof(INSTANCE) From fijal at codespeak.net Wed Jan 16 20:23:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 20:23:58 +0100 (CET) Subject: [pypy-svn] r50682 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20080116192358.BF8D61684CA@codespeak.net> Author: fijal Date: Wed Jan 16 20:23:58 2008 New Revision: 50682 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py Log: (arigo, fijal) * Use our own magic number for pyc files. * Use marshal version 2 when writing pycfiles. This fixes issues with infs and nans appearing in .pycs for which marshal version one has undefined behavior. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jan 16 20:23:58 2008 @@ -378,47 +378,22 @@ a .pyc file in text mode the magic number will be wrong; also, the Apple MPW compiler swaps their values, botching string constants. - The magic numbers must be spaced apart atleast 2 values, as the - -U interpeter flag will cause MAGIC+1 being used. They have been - odd numbers for some time now. - - There were a variety of old schemes for setting the magic number. - The current working scheme is to increment the previous value by - 10. - - Known values: - Python 1.5: 20121 - Python 1.5.1: 20121 - Python 1.5.2: 20121 - Python 2.0: 50823 - Python 2.0.1: 50823 - Python 2.1: 60202 - Python 2.1.1: 60202 - Python 2.1.2: 60202 - Python 2.2: 60717 - Python 2.3a0: 62011 - Python 2.3a0: 62021 - Python 2.3a0: 62011 (!) - Python 2.4a0: 62041 - Python 2.4a3: 62051 - Python 2.4b1: 62061 - Python 2.5a0: 62071 + CPython uses values between 20121 - 62xxx + """ -# we decided to use the magic of 2.4.1 +# we decided to use our own magic 1024 and we have 10 potential bits +# for different opcodes free. # -# In addition, for now, the presence of special bytecodes bumps the +# The presence of special bytecodes bumps the # magic number: # # * CALL_LIKELY_BUILTIN +2 # * CALL_METHOD +4 # -# this is a bit of a hack waiting for a nicer general solution. -# Adding another bytecode is already a problem: if we bump the -# number by a total of +10 we collide with CPython's own magic -# number for 2.5a0. # -MAGIC = 62061 | (ord('\r')<<16) | (ord('\n')<<24) +MAGIC = 1024 | (ord('\r')<<16) | (ord('\n')<<24) +MARSHAL_VERSION_FOR_PYC = 2 def get_pyc_magic(space): result = MAGIC @@ -500,15 +475,10 @@ magic = _r_long(stream) try: if magic != get_pyc_magic(space): - # XXX what to do about Py_VerboseFlag ? - # PySys_WriteStderr("# %s has bad magic\n", cpathname); return -1 pyc_mtime = _r_long(stream) if pyc_mtime != mtime: - # PySys_WriteStderr("# %s has bad mtime\n", cpathname); return 0 - # if (Py_VerboseFlag) - # PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); finally: stream.close() return 1 @@ -556,7 +526,8 @@ """ w_marshal = space.getbuiltinmodule('marshal') try: - w_str = space.call_method(w_marshal, 'dumps', space.wrap(co)) + w_str = space.call_method(w_marshal, 'dumps', space.wrap(co), + space.wrap(MARSHAL_VERSION_FOR_PYC)) strbuf = space.str_w(w_str) except OperationError, e: if e.async(space): Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Wed Jan 16 20:23:58 2008 @@ -522,6 +522,9 @@ os.environ['PYTHONPATH'] = old class AppTestImportHooks(object): + def setup_class(cls): + cls.space = gettestobjspace(usemodules=['struct']) + def test_meta_path(self): tried_imports = [] class Importer(object): From exarkun at codespeak.net Wed Jan 16 20:32:44 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 16 Jan 2008 20:32:44 +0100 (CET) Subject: [pypy-svn] r50683 - pypy/build/buildbot Message-ID: <20080116193244.E838B1684CA@codespeak.net> Author: exarkun Date: Wed Jan 16 20:32:44 2008 New Revision: 50683 Modified: pypy/build/buildbot/pypy_status.py Log: version of the html status thing which really works this generates a table of the results of tests across different builders for recent builds which includes only tests which have failed recently Modified: pypy/build/buildbot/pypy_status.py ============================================================================== --- pypy/build/buildbot/pypy_status.py (original) +++ pypy/build/buildbot/pypy_status.py Wed Jan 16 20:32:44 2008 @@ -5,57 +5,73 @@ from nevow.url import URL from nevow.flat import flatten +from buildbot.interfaces import LOG_CHANNEL_STDOUT from buildbot.status.web.base import ICurrentBox, HtmlResource, map_branches, build_get_class class RecentlyFailingTests(HtmlResource): + oldBuildCount = 10 + + def getLog(self, build, name): + for log in build.getLogs(): + if log.name.endswith(name): + stdout = ''.join( + log.getChunks(channels=[LOG_CHANNEL_STDOUT], + onlyText=True)) + return stdout + return '' + def body(self, request): - status = self.getStatus(req) + status = self.getStatus(request) builderNames = status.getBuilderNames() - - # Keys are the names of tests which failed recently. Each - # value is a list the elements of which is a group of test - # results for a particular build. The group is a dict the - # keys of which are a builder name and the values of which are - # the result for that test on that builder for that build. - # eg - # - # {'foo.tests.test_foo.FooTests.test_foo': [ - # {'win32': 'passed', 'linux': 'failed'}, - # {'win32': 'passed', 'linux': 'passed'}, - # {'win32': 'failed', 'linux': 'passed'}]} failedTests = {} for name in builderNames: recentFailures = Set() builder = status.getBuilder(name) - recentBuilds = builder.generateFinishedBuilds(branches=[None], num_builds=10) + recentBuilds = builder.generateFinishedBuilds( + branches=[None], num_builds=self.oldBuildCount) for build in recentBuilds: - recentFailures.update(build.getLog('failed').splitlines()) + print build + recentFailures.update(self.getLog(build, 'failed').splitlines()) - for name in builderNames: - builder = status.getBuilder(name) - recentBuilds = builder.generateFinishedBuilds(branches=[None], num_builds=10) - for build in recentBuilds: - results = {} - for passed in build.getLog('passed').splitlines(): - results[passed] = 'passed' - for failed in build.getLog('failed').splitlines(): - results[failed] = 'failed' - for skipped in build.getLog('skipped').splitlines(): - results[skipped] = 'skipped' - for recentFailed in recentFailures: - - - - - table = tags.table[[ - tags.tr[[ - tags.td[[ - testResult[0] - for testResult - in testResultsForBuild], - tags.td[testName]] - for testResultsForBuild - in testResultsOverTime]] - for (testName, testResultsOverTime) - in failedTests.iteritems()]] + for builderName in builderNames: + builder = status.getBuilder(builderName) + recentBuilds = builder.generateFinishedBuilds( + branches=[None], num_builds=self.oldBuildCount) + for buildNumber, build in enumerate(recentBuilds): + results = dict.fromkeys( + self.getLog(build, 'passed').splitlines(), + tags.span(style="background-color: green;")['P']) + results.update( + dict.fromkeys( + self.getLog(build, 'failed').splitlines(), + tags.span(style="background-color: red;")['F'])) + results.update( + dict.fromkeys( + self.getLog(build, 'skipped').splitlines(), + tags.span(style="background-color: yellow;")['S'])) + + for testName in recentFailures: + key = (builderName, buildNumber, testName) + failedTests[key] = results.get( + testName, + tags.span(style="background-color: cyan;")['?']) + + table = tags.table() + heading = tags.tr() + for buildNumber in range(self.oldBuildCount): + heading[tags.td()[buildNumber]] + table[heading] + + for testName in recentFailures: + row = tags.tr() + for buildNumber in range(self.oldBuildCount): + result = [] + for builderName in builderNames: + key = (builderName, buildNumber, testName) + result.append(failedTests[key]) + row[tags.td()[result]] + row[tags.td()[testName]] + table[row] + + return flatten(table) From exarkun at codespeak.net Wed Jan 16 20:33:01 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 16 Jan 2008 20:33:01 +0100 (CET) Subject: [pypy-svn] r50684 - pypy/build/buildbot Message-ID: <20080116193301.5F1A11684CB@codespeak.net> Author: exarkun Date: Wed Jan 16 20:33:01 2008 New Revision: 50684 Modified: pypy/build/buildbot/master.cfg Log: use the RecentlyFailingTests status view Modified: pypy/build/buildbot/master.cfg ============================================================================== --- pypy/build/buildbot/master.cfg (original) +++ pypy/build/buildbot/master.cfg Wed Jan 16 20:33:01 2008 @@ -3,6 +3,7 @@ from buildbot.buildslave import BuildSlave from buildbot.status.html import WebStatus +from pypy_status import RecentlyFailingTests from pypybuilders import PyPyBuildFactory from slaveinfo import passwords @@ -17,6 +18,9 @@ server.Site = LoggingSite # So I did. +status = WebStatus(httpPortNumber, allowForce=True) +status.putChild('summary', RecentlyFailingTests()) + BuildmasterConfig = { 'slavePortnum': "tcp:10407", @@ -27,7 +31,7 @@ "pypy-c-allworkingmodules-faassen-64", "pypy-c-allworkingmodules-faassen-winxp32"], hour=19)], - 'status': [WebStatus(httpPortNumber, allowForce=True)], + 'status': [status], 'slaves': [BuildSlave(name, password) for (name, password) From arigo at codespeak.net Wed Jan 16 20:38:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 16 Jan 2008 20:38:22 +0100 (CET) Subject: [pypy-svn] r50685 - in pypy/dist/pypy: module/__builtin__/test objspace/std Message-ID: <20080116193822.8D5041684CA@codespeak.net> Author: arigo Date: Wed Jan 16 20:38:22 2008 New Revision: 50685 Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py pypy/dist/pypy/objspace/std/marshal_impl.py Log: We can now simplify marshal_impl.py to use directly ieee.py from pypy/module/struct/ instead of going via app-level. Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Wed Jan 16 20:38:22 2008 @@ -522,9 +522,6 @@ os.environ['PYTHONPATH'] = old class AppTestImportHooks(object): - def setup_class(cls): - cls.space = gettestobjspace(usemodules=['struct']) - def test_meta_path(self): tried_imports = [] class Importer(object): Modified: pypy/dist/pypy/objspace/std/marshal_impl.py ============================================================================== --- pypy/dist/pypy/objspace/std/marshal_impl.py (original) +++ pypy/dist/pypy/objspace/std/marshal_impl.py Wed Jan 16 20:38:22 2008 @@ -18,6 +18,7 @@ from pypy.interpreter.special import Ellipsis from pypy.interpreter.pycode import PyCode from pypy.interpreter import gateway +from pypy.module.struct import ieee from pypy.objspace.std.boolobject import W_BoolObject from pypy.objspace.std.complexobject import W_ComplexObject @@ -172,67 +173,58 @@ return res register(TYPE_INT64, unmarshal_Int64) -# support for marshal version 2: -# we call back into the struct module. -# XXX struct should become interp-level. -# XXX we also should have an rtyper operation -# that allows to typecast between double and char{8} +def pack_float(f): + result = [] + ieee.pack_float(result, f, 8, False) + return ''.join(result) -app = gateway.applevel(r''' - def float_to_str(fl): - import struct - return struct.pack(' 1: m.start(TYPE_BINARY_FLOAT) - m.put(space.str_w(float_to_str(space, w_float))) + m.put(pack_float(w_float.floatval)) else: m.start(TYPE_FLOAT) m.put_pascal(space.str_w(repr_float(space, w_float))) def unmarshal_Float(space, u, tc): - if tc == TYPE_BINARY_FLOAT: - w_ret = str_to_float(space, space.wrap(u.get(8))) - return W_FloatObject(space.float_w(w_ret)) - else: - return space.call_function(space.builtin.get('float'), - space.wrap(u.get_pascal())) -register(TYPE_FLOAT + TYPE_BINARY_FLOAT, unmarshal_Float) + return space.call_function(space.builtin.get('float'), + space.wrap(u.get_pascal())) +register(TYPE_FLOAT, unmarshal_Float) + +def unmarshal_Float_bin(space, u, tc): + return W_FloatObject(unpack_float(u.get(8))) +register(TYPE_BINARY_FLOAT, unmarshal_Float_bin) def marshal_w__Complex(space, w_complex, m): - # XXX a bit too wrap-happy - w_real = space.wrap(w_complex.realval) - w_imag = space.wrap(w_complex.imagval) if m.version > 1: m.start(TYPE_BINARY_COMPLEX) - m.put(space.str_w(float_to_str(space, w_real))) - m.put(space.str_w(float_to_str(space, w_imag))) + m.put(pack_float(w_complex.realval)) + m.put(pack_float(w_complex.imagval)) else: + # XXX a bit too wrap-happy + w_real = space.wrap(w_complex.realval) + w_imag = space.wrap(w_complex.imagval) m.start(TYPE_COMPLEX) m.put_pascal(space.str_w(repr_float(space, w_real))) m.put_pascal(space.str_w(repr_float(space, w_imag))) def unmarshal_Complex(space, u, tc): - if tc == TYPE_BINARY_COMPLEX: - w_real = str_to_float(space, space.wrap(u.get(8))) - w_imag = str_to_float(space, space.wrap(u.get(8))) - else: - w_real = space.call_function(space.builtin.get('float'), - space.wrap(u.get_pascal())) - w_imag = space.call_function(space.builtin.get('float'), - space.wrap(u.get_pascal())) + w_real = space.call_function(space.builtin.get('float'), + space.wrap(u.get_pascal())) + w_imag = space.call_function(space.builtin.get('float'), + space.wrap(u.get_pascal())) w_t = space.builtin.get('complex') return space.call_function(w_t, w_real, w_imag) -register(TYPE_COMPLEX + TYPE_BINARY_COMPLEX, unmarshal_Complex) +register(TYPE_COMPLEX, unmarshal_Complex) + +def unmarshal_Complex_bin(space, u, tc): + real = unpack_float(u.get(8)) + imag = unpack_float(u.get(8)) + return W_ComplexObject(real, imag) +register(TYPE_BINARY_COMPLEX, unmarshal_Complex_bin) def marshal_w__Long(space, w_long, m): assert long_bits == 15, """if long_bits is not 15, From xoraxax at codespeak.net Wed Jan 16 20:59:43 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 16 Jan 2008 20:59:43 +0100 (CET) Subject: [pypy-svn] r50686 - pypy/dist/pypy/module/__builtin__ Message-ID: <20080116195943.567461684C9@codespeak.net> Author: xoraxax Date: Wed Jan 16 20:59:43 2008 New Revision: 50686 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Minor rewording of the comment. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jan 16 20:59:43 2008 @@ -382,8 +382,8 @@ """ -# we decided to use our own magic 1024 and we have 10 potential bits -# for different opcodes free. +# we decided to use our own magic number starting from 1024 +# and we have 10 potential bits for different opcodes free. # # The presence of special bytecodes bumps the # magic number: From fijal at codespeak.net Wed Jan 16 21:04:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 21:04:01 +0100 (CET) Subject: [pypy-svn] r50687 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080116200401.E6FEE1684CB@codespeak.net> Author: fijal Date: Wed Jan 16 21:04:01 2008 New Revision: 50687 Modified: pypy/dist/pypy/lib/_ctypes/basics.py Log: Make address accepted, even if it's negative Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Wed Jan 16 21:04:01 2008 @@ -1,5 +1,6 @@ import _rawffi +import sys class _CDataMeta(type): def from_param(self, value): @@ -80,6 +81,8 @@ return pointer(cdata) def cdata_from_address(self, address): + # fix the address, in case it's unsigned + address = address & (sys.maxint * 2 + 1) instance = self.__new__(self) lgt = getattr(self, '_length_', 1) instance._buffer = self._ffiarray.fromaddress(address, lgt) From antocuni at codespeak.net Wed Jan 16 21:06:37 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jan 2008 21:06:37 +0100 (CET) Subject: [pypy-svn] r50688 - in pypy/dist/pypy: jit/codegen/llgraph jit/timeshifter/test rpython/ootypesystem Message-ID: <20080116200637.EF5C01684D7@codespeak.net> Author: antocuni Date: Wed Jan 16 21:06:35 2008 New Revision: 50688 Added: pypy/dist/pypy/rpython/ootypesystem/rtupletype.py (contents, props changed) Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: (antocuni, arigo) a lot of tests passed out of the box, but test_loop_merging needed a very weird hack to pass 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 Wed Jan 16 21:06:35 2008 @@ -4,8 +4,8 @@ that can be used to produce any other kind of graph. """ -from pypy.rpython.lltypesystem import lltype, llmemory, rtupletype -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype, llmemory, rtupletype as llrtupletype +from pypy.rpython.ootypesystem import ootype, rtupletype as oortupletype from pypy.objspace.flow import model as flowmodel from pypy.translator.simplify import eliminate_empty_blocks from pypy.translator.unsimplify import varoftype @@ -475,11 +475,25 @@ block.recloseblock(*exits) return _to_opaque(default_link) +# incredible hack here; pseudotuple must pretend to be both a LL tuple +# and an OO tuple, so we need to make the llinterpreter thinking that +# its _TYPE is compatible both with a struct and a +# record. TwoFacedType does exactly this. +class TwoFacedType(ootype.BuiltinType): + def __init__(self, TYPE1, TYPE2): + self.TYPE1 = TYPE1 + self.TYPE2 = TYPE2 + + def __eq__(self, other): + return self.TYPE1 == other or self.TYPE2 == other + class pseudotuple(object): - # something that looks both like a hl and a ll tuple + # something that looks both like a hl, a ll tuple and an oo tuple def __init__(self, *items): - self._TYPE = rtupletype.TUPLE_TYPE( - [lltype.typeOf(item) for item in items]) + fields = [lltype.typeOf(item) for item in items] + TYPE1 = llrtupletype.TUPLE_TYPE(fields) + TYPE2 = oortupletype.TUPLE_TYPE(fields) + self._TYPE = TwoFacedType(TYPE1, TYPE2) for i, item in enumerate(items): setattr(self, 'item%d' % i, item) self._items = items 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 Jan 16 21:06:35 2008 @@ -1796,6 +1796,10 @@ passing_ootype_tests = set([ 'test_very_simple', 'test_convert_const_to_redbox', + 'test_simple_opt_const_propagation1', + 'test_simple_opt_const_propagation2', + 'test_loop_folding', + 'test_loop_merging', ]) class TestOOType(BaseTestTimeshift): type_system = 'ootype' Added: pypy/dist/pypy/rpython/ootypesystem/rtupletype.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/ootypesystem/rtupletype.py Wed Jan 16 21:06:35 2008 @@ -0,0 +1,13 @@ +# Helper to build the lowleveltype corresponding to an RPython tuple. +# This is not in rtuple.py so that it can be imported without bringing +# the whole rtyper in. + +from pypy.rpython.ootypesystem import ootype + + +def TUPLE_TYPE(field_lltypes): + if len(field_lltypes) == 0: + return Void # empty tuple + else: + fields = [('item%d' % i, TYPE) for i, TYPE in enumerate(field_lltypes)] + return ootype.Record(dict(fields)) From antocuni at codespeak.net Wed Jan 16 21:18:41 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 16 Jan 2008 21:18:41 +0100 (CET) Subject: [pypy-svn] r50689 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080116201841.79A381684BF@codespeak.net> Author: antocuni Date: Wed Jan 16 21:18:39 2008 New Revision: 50689 Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: more tests passes out of the box 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 Jan 16 21:18:39 2008 @@ -1800,6 +1800,13 @@ 'test_simple_opt_const_propagation2', 'test_loop_folding', 'test_loop_merging', + 'test_two_loops_merging', + 'test_convert_greenvar_to_redvar', + 'test_green_across_split', + 'test_merge_const_before_return', + 'test_merge_3_redconsts_before_return', + 'test_merge_const_at_return', + 'test_arith_plus_minus', ]) class TestOOType(BaseTestTimeshift): type_system = 'ootype' From fijal at codespeak.net Wed Jan 16 22:25:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 22:25:02 +0100 (CET) Subject: [pypy-svn] r50690 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080116212502.35493168476@codespeak.net> Author: fijal Date: Wed Jan 16 22:25:00 2008 New Revision: 50690 Modified: pypy/dist/pypy/lib/_ctypes/primitive.py Log: Replicate the bogus logic from the CPython ctypes. Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Wed Jan 16 22:25:00 2008 @@ -43,7 +43,7 @@ result._ffiletter = tp result._ffiarray = ffiarray if tp == 'z': - # c_char_p special cases + # c_char_p from _ctypes import Array, _Pointer def _getvalue(self): @@ -52,6 +52,7 @@ return None else: return _rawffi.charp2string(addr) + def _setvalue(self, value): if isinstance(value, str): array = _rawffi.Array('c')(len(value)+1, value) @@ -62,16 +63,40 @@ self._buffer[0] = value result.value = property(_getvalue, _setvalue) + elif tp == 'P': + # c_void_p + + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + return addr + + def _setvalue(self, value): + if isinstance(value, str): + array = _rawffi.Array('c')(len(value)+1, value) + value = array.buffer + # XXX free 'array' later + elif value is None: + value = 0 + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) + + if tp == 'z' or tp == 'P': + from _ctypes import Array, _Pointer + # c_char_p and c_void_p def from_param(self, value): if value is None: return None if isinstance(value, basestring): return self(value) - if isinstance(value, self): + if isinstance(value, _SimpleCData) and \ + type(value)._type_ in 'zP': return value if isinstance(value, (Array, _Pointer)): - from ctypes import c_char - if type(value)._type_ == c_char: + from ctypes import c_char, c_byte + if type(value)._type_ == c_char or \ + type(value)._type_ == c_byte: return value return SimpleType.from_param(self, value) result.from_param = classmethod(from_param) From fijal at codespeak.net Wed Jan 16 22:59:12 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 22:59:12 +0100 (CET) Subject: [pypy-svn] r50691 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080116215912.C2104168472@codespeak.net> Author: fijal Date: Wed Jan 16 22:59:12 2008 New Revision: 50691 Modified: pypy/dist/pypy/lib/_ctypes/structure.py Log: Implement a bit of insane logic about structure inheritance hierarchy. One test passes. Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Wed Jan 16 22:59:12 2008 @@ -1,15 +1,19 @@ import _rawffi from _ctypes.basics import _CData, _CDataMeta +import inspect class StructureMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: - names = [name for name, ctype in typedict['_fields_']] - res._fieldtypes = dict(typedict['_fields_']) + all_fields = typedict['_fields_'][:] + for cls in inspect.getmro(cls[0]): + all_fields += getattr(cls, '_fields_', []) + names = [name for name, ctype in all_fields] + res._fieldtypes = dict(all_fields) rawfields = [(name, ctype._ffiletter) - for name, ctype in typedict['_fields_']] + for name, ctype in all_fields] ffistruct = _rawffi.Structure(rawfields) res._ffistruct = ffistruct @@ -33,6 +37,8 @@ instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) return instance + def _sizeofinstances(self): + return self._ffistruct.size class Structure(_CData): __metaclass__ = StructureMeta From fijal at codespeak.net Wed Jan 16 23:39:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 23:39:26 +0100 (CET) Subject: [pypy-svn] r50692 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080116223926.B9254168430@codespeak.net> Author: fijal Date: Wed Jan 16 23:39:25 2008 New Revision: 50692 Modified: pypy/dist/pypy/lib/_ctypes/structure.py Log: Another portion of very broken logic. Two more bugs replicated. Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Wed Jan 16 23:39:25 2008 @@ -3,41 +3,60 @@ from _ctypes.basics import _CData, _CDataMeta import inspect +def names_and_fields(_fields_, superclass): + all_fields = _fields_[:] + for cls in inspect.getmro(superclass): + all_fields += getattr(cls, '_fields_', []) + names = [name for name, ctype in all_fields] + rawfields = [(name, ctype._ffiletter) + for name, ctype in all_fields] + return names, rawfields, dict(all_fields) + class StructureMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: - all_fields = typedict['_fields_'][:] - for cls in inspect.getmro(cls[0]): - all_fields += getattr(cls, '_fields_', []) - names = [name for name, ctype in all_fields] - res._fieldtypes = dict(all_fields) - rawfields = [(name, ctype._ffiletter) - for name, ctype in all_fields] - ffistruct = _rawffi.Structure(rawfields) - res._ffistruct = ffistruct - - def __init__(self, *args, **kwds): - self.__dict__['_buffer'] = ffistruct() - if len(args) > len(names): - raise TypeError("too many arguments") - for name, arg in zip(names, args): - if name in kwds: - raise TypeError("duplicate value for argument %r" % ( - name,)) - self.__setattr__(name, arg) - for name, arg in kwds.items(): - self.__setattr__(name, arg) - res.__init__ = __init__ + res._names, rawfields, res._fieldtypes = names_and_fields( + typedict['_fields_'], cls[0]) + res._ffistruct = _rawffi.Structure(rawfields) + + def __init__(self, *args, **kwds): + if not hasattr(self, '_ffistruct'): + raise TypeError("Cannot instantiate structure, has no _fields_") + self.__dict__['_buffer'] = self._ffistruct() + if len(args) > len(self._names): + raise TypeError("too many arguments") + for name, arg in zip(self._names, args): + if name in kwds: + raise TypeError("duplicate value for argument %r" % ( + name,)) + self.__setattr__(name, arg) + for name, arg in kwds.items(): + self.__setattr__(name, arg) + res.__init__ = __init__ + return res + def __setattr__(self, name, value): + if name == '_fields_': + if self.__dict__.get('_fields_', None): + raise TypeError("Fields already final") + self._names, rawfields, self._fieldtypes = names_and_fields( + value, self.__bases__[0]) + self._ffistruct = _rawffi.Structure(rawfields) + _CDataMeta.__setattr__(self, '_fields_', value) + return + _CDataMeta.__setattr__(self, name, value) + def from_address(self, address): instance = self.__new__(self) instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) return instance def _sizeofinstances(self): + if not hasattr(self, '_ffistruct'): + return 0 return self._ffistruct.size class Structure(_CData): From fijal at codespeak.net Wed Jan 16 23:54:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 16 Jan 2008 23:54:58 +0100 (CET) Subject: [pypy-svn] r50693 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080116225458.5F3CF168473@codespeak.net> Author: fijal Date: Wed Jan 16 23:54:58 2008 New Revision: 50693 Added: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (contents, props changed) Log: Add this test, we pass few of those. Added: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Wed Jan 16 23:54:58 2008 @@ -0,0 +1,429 @@ +from ctypes import * +from struct import calcsize + +import py + +class TestSubclasses: + def test_subclass(self): + class X(Structure): + _fields_ = [("a", c_int)] + + class Y(X): + _fields_ = [("b", c_int)] + + class Z(X): + pass + + assert sizeof(X) == sizeof(c_int) + assert sizeof(Y) == sizeof(c_int)*2 + assert sizeof(Z) == sizeof(c_int) + assert X._fields_ == [("a", c_int)] + assert Y._fields_ == [("b", c_int)] + assert Z._fields_ == [("a", c_int)] + + def test_subclass_delayed(self): + class X(Structure): + pass + assert sizeof(X) == 0 + X._fields_ = [("a", c_int)] + + class Y(X): + pass + assert sizeof(Y) == sizeof(X) + Y._fields_ = [("b", c_int)] + + class Z(X): + pass + + assert sizeof(X) == sizeof(c_int) + assert sizeof(Y) == sizeof(c_int)*2 + assert sizeof(Z) == sizeof(c_int) + assert X._fields_ == [("a", c_int)] + assert Y._fields_ == [("b", c_int)] + assert Z._fields_ == [("a", c_int)] + +class TestStructure: + formats = {"c": c_char, + "b": c_byte, + "B": c_ubyte, + "h": c_short, + "H": c_ushort, + "i": c_int, + "I": c_uint, + "l": c_long, + "L": c_ulong, + "q": c_longlong, + "Q": c_ulonglong, + "f": c_float, + "d": c_double, + } + + def test_simple_structs(self): + for code, tp in self.formats.items(): + class X(Structure): + _fields_ = [("x", c_char), + ("y", tp)] + assert (sizeof(X), code) == ( + (calcsize("c%c0%c" % (code, code)), code)) + + def test_unions(self): + py.test.skip("No unions support") + for code, tp in self.formats.items(): + class X(Union): + _fields_ = [("x", c_char), + ("y", tp)] + assert (sizeof(X), code) == ( + (calcsize("%c" % (code)), code)) + + def test_struct_alignment(self): + py.test.skip("???") + class X(Structure): + _fields_ = [("x", c_char * 3)] + assert alignment(X) == calcsize("s") + assert sizeof(X) == calcsize("3s") + + class Y(Structure): + _fields_ = [("x", c_char * 3), + ("y", c_int)] + assert alignment(Y) == calcsize("i") + assert sizeof(Y) == calcsize("3si") + + class SI(Structure): + _fields_ = [("a", X), + ("b", Y)] + assert alignment(SI) == max(alignment(Y), alignment(X)) + assert sizeof(SI) == calcsize("3s0i 3si 0i") + + class IS(Structure): + _fields_ = [("b", Y), + ("a", X)] + + assert alignment(SI) == max(alignment(X), alignment(Y)) + assert sizeof(IS) == calcsize("3si 3s 0i") + + class XX(Structure): + _fields_ = [("a", X), + ("b", X)] + assert alignment(XX) == alignment(X) + assert sizeof(XX) == calcsize("3s 3s 0s") + + def test_emtpy(self): + py.test.skip("No unions support") + # I had problems with these + # + # Although these are patological cases: Empty Structures! + class X(Structure): + _fields_ = [] + + class Y(Union): + _fields_ = [] + + # Is this really the correct alignment, or should it be 0? + assert alignment(X) == alignment(Y) == 1 + assert sizeof(X) == sizeof(Y) == 0 + + class XX(Structure): + _fields_ = [("a", X), + ("b", X)] + + assert alignment(XX) == 1 + assert sizeof(XX) == 0 + + def test_fields(self): + py.test.skip("???") + # test the offset and size attributes of Structure/Unoin fields. + class X(Structure): + _fields_ = [("x", c_int), + ("y", c_char)] + + assert X.x.offset == 0 + assert X.x.size == sizeof(c_int) + + assert X.y.offset == sizeof(c_int) + assert X.y.size == sizeof(c_char) + + # readonly + raises((TypeError, AttributeError), setattr, X.x, "offset", 92) + raises((TypeError, AttributeError), setattr, X.x, "size", 92) + + class X(Union): + _fields_ = [("x", c_int), + ("y", c_char)] + + assert X.x.offset == 0 + assert X.x.size == sizeof(c_int) + + assert X.y.offset == 0 + assert X.y.size == sizeof(c_char) + + # readonly + raises((TypeError, AttributeError), setattr, X.x, "offset", 92) + raises((TypeError, AttributeError), setattr, X.x, "size", 92) + + # XXX Should we check nested data types also? + # offset is always relative to the class... + + def test_packed(self): + py.test.skip("???") + class X(Structure): + _fields_ = [("a", c_byte), + ("b", c_longlong)] + _pack_ = 1 + + assert sizeof(X) == 9 + assert X.b.offset == 1 + + class X(Structure): + _fields_ = [("a", c_byte), + ("b", c_longlong)] + _pack_ = 2 + assert sizeof(X) == 10 + assert X.b.offset == 2 + + class X(Structure): + _fields_ = [("a", c_byte), + ("b", c_longlong)] + _pack_ = 4 + assert sizeof(X) == 12 + assert X.b.offset == 4 + + import struct + longlong_size = struct.calcsize("q") + longlong_align = struct.calcsize("bq") - longlong_size + + class X(Structure): + _fields_ = [("a", c_byte), + ("b", c_longlong)] + _pack_ = 8 + + assert sizeof(X) == longlong_align + longlong_size + assert X.b.offset == min(8, longlong_align) + + + d = {"_fields_": [("a", "b"), + ("b", "q")], + "_pack_": -1} + raises(ValueError, type(Structure), "X", (Structure,), d) + + def test_initializers(self): + py.test.skip("???") + class Person(Structure): + _fields_ = [("name", c_char*6), + ("age", c_int)] + + raises(TypeError, Person, 42) + raises(ValueError, Person, "asldkjaslkdjaslkdj") + raises(TypeError, Person, "Name", "HI") + + # short enough + assert Person("12345", 5).name == "12345" + # exact fit + assert Person("123456", 5).name == "123456" + # too long + raises(ValueError, Person, "1234567", 5) + + + def test_keyword_initializers(self): + class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] + pt = POINT(1, 2) + assert (pt.x, pt.y) == (1, 2) + + pt = POINT(y=2, x=1) + assert (pt.x, pt.y) == (1, 2) + + def test_invalid_field_types(self): + py.test.skip("???") + class POINT(Structure): + pass + raises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)]) + + def test_intarray_fields(self): + py.test.skip("???") + class SomeInts(Structure): + _fields_ = [("a", c_int * 4)] + + # can use tuple to initialize array (but not list!) + assert SomeInts((1, 2)).a[:] == [1, 2, 0, 0] + assert SomeInts((1, 2, 3, 4)).a[:] == [1, 2, 3, 4] + # too long + # XXX Should raise ValueError?, not RuntimeError + raises(RuntimeError, SomeInts, (1, 2, 3, 4, 5)) + + def test_nested_initializers(self): + py.test.skip("???") + # test initializing nested structures + class Phone(Structure): + _fields_ = [("areacode", c_char*6), + ("number", c_char*12)] + + class Person(Structure): + _fields_ = [("name", c_char * 12), + ("phone", Phone), + ("age", c_int)] + + p = Person("Someone", ("1234", "5678"), 5) + + assert p.name == "Someone" + assert p.phone.areacode == "1234" + assert p.phone.number == "5678" + assert p.age == 5 + + def test_structures_with_wchar(self): + try: + c_wchar + except NameError: + return # no unicode + + class PersonW(Structure): + _fields_ = [("name", c_wchar * 12), + ("age", c_int)] + + p = PersonW(u"Someone") + assert p.name == "Someone" + + assert PersonW(u"1234567890").name == u"1234567890" + assert PersonW(u"12345678901").name == u"12345678901" + # exact fit + assert PersonW(u"123456789012").name == u"123456789012" + #too long + raises(ValueError, PersonW, u"1234567890123") + + def test_init_errors(self): + py.test.skip("???") + class Phone(Structure): + _fields_ = [("areacode", c_char*6), + ("number", c_char*12)] + + class Person(Structure): + _fields_ = [("name", c_char * 12), + ("phone", Phone), + ("age", c_int)] + + cls, msg = self.get_except(Person, "Someone", (1, 2)) + assert cls == RuntimeError + # In Python 2.5, Exception is a new-style class, and the repr changed + if issubclass(Exception, object): + assert msg == ( + "(Phone) : " + "expected string or Unicode object, int found") + else: + assert msg == ( + "(Phone) exceptions.TypeError: " + "expected string or Unicode object, int found") + + cls, msg = self.get_except(Person, "Someone", ("a", "b", "c")) + assert cls == RuntimeError + if issubclass(Exception, object): + assert msg == ( + "(Phone) : too many initializers") + else: + assert msg == "(Phone) exceptions.ValueError: too many initializers" + + + def get_except(self, func, *args): + try: + func(*args) + except Exception, detail: + return detail.__class__, str(detail) + + +## def test_subclass_creation(self): +## meta = type(Structure) +## # same as 'class X(Structure): pass' +## # fails, since we need either a _fields_ or a _abstract_ attribute +## cls, msg = self.get_except(meta, "X", (Structure,), {}) +## self.failUnlessEqual((cls, msg), +## (AttributeError, "class must define a '_fields_' attribute")) + + def test_abstract_class(self): + py.test.skip("???") + class X(Structure): + _abstract_ = "something" + # try 'X()' + cls, msg = self.get_except(eval, "X()", locals()) + assert (cls, msg) == (TypeError, "abstract class") + + def test_methods(self): + py.test.skip("???") +## class X(Structure): +## _fields_ = [] + + assert "in_dll" in dir(type(Structure)) + assert "from_address" in dir(type(Structure)) + assert "in_dll" in dir(type(Structure)) + +class TestPointerMember: + + def test_1(self): + # a Structure with a POINTER field + class S(Structure): + _fields_ = [("array", POINTER(c_int))] + + s = S() + # We can assign arrays of the correct type + s.array = (c_int * 3)(1, 2, 3) + items = [s.array[i] for i in range(3)] + assert items == [1, 2, 3] + + # The following are bugs, but are included here because the unittests + # also describe the current behaviour. + # + # This fails with SystemError: bad arg to internal function + # or with IndexError (with a patch I have) + + s.array[0] = 42 + + items = [s.array[i] for i in range(3)] + assert items == [42, 2, 3] + + s.array[0] = 1 + +## s.array[1] = 42 + + items = [s.array[i] for i in range(3)] + assert items == [1, 2, 3] + + def test_none_to_pointer_fields(self): + py.test.skip("???") + class S(Structure): + _fields_ = [("x", c_int), + ("p", POINTER(c_int))] + + s = S() + s.x = 12345678 + s.p = None + assert s.x == 12345678 + +class TestRecursiveStructure: + def test_contains_itself(self): + py.test.skip("???") + class Recursive(Structure): + pass + + try: + Recursive._fields_ = [("next", Recursive)] + except AttributeError, details: + assert ("Structure or union cannot contain itself" in + str(details)) + else: + raise AssertionError, "Structure or union cannot contain itself" + + + def test_vice_versa(self): + py.test.skip("???") + class First(Structure): + pass + class Second(Structure): + pass + + First._fields_ = [("second", Second)] + + try: + Second._fields_ = [("first", First)] + except AttributeError, details: + assert ("_fields_ is final" in + str(details)) + else: + raise AssertionError, "AttributeError not raised" + From fijal at codespeak.net Thu Jan 17 00:09:21 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 00:09:21 +0100 (CET) Subject: [pypy-svn] r50695 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080116230921.7F3FD168449@codespeak.net> Author: fijal Date: Thu Jan 17 00:09:20 2008 New Revision: 50695 Modified: pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/_ctypes/basics.py pypy/dist/pypy/lib/_ctypes/function.py pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/_ctypes/structure.py Log: A bit of wacking to make the tests just commited work a bit Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Thu Jan 17 00:09:20 2008 @@ -6,11 +6,10 @@ class ArrayMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) - res._ffiletter = 'P' if '_type_' in typedict: ffiarray = _rawffi.Array(typedict['_type_']._ffiletter) res._ffiarray = ffiarray - if typedict['_type_']._type_ == 'c': + if getattr(typedict['_type_'], '_type_', None) == 'c': def getvalue(self): return _rawffi.charp2string(self._buffer.buffer, self._length_) @@ -41,8 +40,12 @@ size, alignment = self._ffiarray.gettypecode(self._length_) return size + def _alignmentofinstances(self): + return self._type_._alignmentofinstances() + class Array(_CData): __metaclass__ = ArrayMeta + _ffiletter = 'P' def __init__(self, *args): self._buffer = self._ffiarray(self._length_) Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Thu Jan 17 00:09:20 2008 @@ -73,8 +73,13 @@ return tp._sizeofinstances() def alignment(tp): - ffitp = tp._type_ - return _rawffi.alignment(ffitp) + if not isinstance(tp, _CDataMeta): + if isinstance(tp, _CData): + tp = type(tp) + else: + raise TypeError("ctypes type or instance expected, got %r" % ( + type(tp).__name__,)) + return tp._alignmentofinstances() def byref(cdata): from ctypes import pointer Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Thu Jan 17 00:09:20 2008 @@ -11,6 +11,8 @@ _argtypes_ = None _restype_ = None + _ffiletter = 'P' + _buffer = 0 def _getargtypes(self): return self._argtypes_ @@ -48,6 +50,9 @@ return restype._CData_output(resarray) def _getfuncptr(self, argtypes, restype): + if restype is None: + import ctypes + restype = ctypes.c_int argletters = [arg._ffiletter for arg in argtypes] return self.dll._handle.ptr(self.name, argletters, restype._ffiletter) Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Thu Jan 17 00:09:20 2008 @@ -48,9 +48,15 @@ def _sizeofinstances(self): return _rawffi.sizeof('P') + def _alignmentofinstances(self): + return _rawffi.alignment('P') + def _is_pointer_like(self): return True + def set_type(self, TP): + pass # XXX??? + from_address = cdata_from_address class _Pointer(_CData): Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Thu Jan 17 00:09:20 2008 @@ -116,6 +116,9 @@ def _sizeofinstances(self): return _rawffi.sizeof(self._type_) + def _alignmentofinstances(self): + return _rawffi.alignment(self._type_) + def _is_pointer_like(self): return self._type_ in "sPzUZXO" Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 00:09:20 2008 @@ -41,7 +41,7 @@ def __setattr__(self, name, value): if name == '_fields_': if self.__dict__.get('_fields_', None): - raise TypeError("Fields already final") + raise AttributeError("_fields_ is final") self._names, rawfields, self._fieldtypes = names_and_fields( value, self.__bases__[0]) self._ffistruct = _rawffi.Structure(rawfields) @@ -59,8 +59,12 @@ return 0 return self._ffistruct.size + def _alignmentofinstances(self): + return self._ffistruct.alignment + class Structure(_CData): __metaclass__ = StructureMeta + _ffiletter = 'P' def _subarray(self, fieldtype, name): """Return a _rawffi array of length 1 whose address is the same as From cfbolz at codespeak.net Thu Jan 17 11:03:42 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 11:03:42 +0100 (CET) Subject: [pypy-svn] r50696 - in pypy/dist/pypy/objspace: . test Message-ID: <20080117100342.C659F168449@codespeak.net> Author: cfbolz Date: Thu Jan 17 11:03:36 2008 New Revision: 50696 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: do more sensible things with new* operations Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 11:03:36 2008 @@ -11,23 +11,65 @@ ec.w_reflectivespace = w_reflectivespace app_set_reflectivespace = gateway.interp2app(set_reflectivespace) +def get_reflective_space(space): + ec = space.getexecutioncontext() + if ec.w_reflectivespace is not None: + w_rspace = ec.w_reflectivespace + ec.w_reflectivespace = None + return w_rspace + return None + +def reset_reflective_space(space, w_rspace): + ec = space.getexecutioncontext() + ec.w_reflectivespace = w_rspace + def proxymaker(space, opname, parentfn): - def fn(*args_w): - ec = space.getexecutioncontext() - if ec.w_reflectivespace is not None: - w_rspace = ec.w_reflectivespace - ec.w_reflectivespace = None - try: - w_f = space.getattr(w_rspace, space.wrap(opname)) - except OperationError, e: - if not e.match(space, space.w_AttributeError): - raise - else: - w_res = space.call_function(w_f, *args_w) - ec.w_reflectivespace = w_rspace - return w_res - return parentfn(*args_w) + if opname == "wrap": + return parentfn # no way to override wrapping for now + elif opname == "newdict": # grr grr kwargs + def fn(track_builtin_shadowing=False): + w_obj = parentfn(track_builtin_shadowing) + w_rspace = get_reflective_space(space) + if w_rspace is not None: + try: + w_f = space.getattr(w_rspace, space.wrap("newdict")) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + w_obj = space.call_function(w_f, w_obj) + reset_reflective_space(space, w_rspace) + return w_obj + elif opname.startswith("new"): + def fn(*args_w, **kwargs): + w_obj = parentfn(*args_w, **kwargs) + w_rspace = get_reflective_space(space) + if w_rspace is not None: + try: + w_f = space.getattr(w_rspace, space.wrap(opname)) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + w_obj = space.call_function(w_f, w_obj) + reset_reflective_space(space, w_rspace) + return w_obj + else: + def fn(*args_w): + ec = space.getexecutioncontext() + w_rspace = get_reflective_space(space) + if w_rspace is not None: + try: + w_f = space.getattr(w_rspace, space.wrap(opname)) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + w_res = space.call_function(w_f, *args_w) + reset_reflective_space(space, w_rspace) + return w_res + return parentfn(*args_w) fn.func_name = opname return fn Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Thu Jan 17 11:03:36 2008 @@ -12,7 +12,9 @@ return 40+2 set_reflectivespace(Space()) - assert 1+2 == 42 + x = 1 + y = 2 + assert x + y == 42 set_reflectivespace(None) assert 1+2 == 3 @@ -24,3 +26,28 @@ set_reflectivespace(Space()) assert 1+2 == 3 + + def test_newdict(self): + from __pypy__ import set_reflectivespace + class Space: + def newdict(self, d): + d['surprise'] = 42 + return d + + set_reflectivespace(Space()) + d = {"b": 1} + assert d["surprise"] == 42 + set_reflectivespace(None) + + + def test_newlist(self): + from __pypy__ import set_reflectivespace + class Space: + def newlist(self, l): + l.append(len(l)) + return l + + set_reflectivespace(Space()) + l = [1, 2, 3, 4, 5] + assert len(l) == 6 + set_reflectivespace(None) From cfbolz at codespeak.net Thu Jan 17 11:14:12 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 11:14:12 +0100 (CET) Subject: [pypy-svn] r50697 - pypy/dist/pypy/objspace Message-ID: <20080117101412.090B5168449@codespeak.net> Author: cfbolz Date: Thu Jan 17 11:14:11 2008 New Revision: 50697 Modified: pypy/dist/pypy/objspace/reflective.py Log: get rid of unnecessary **kwargs Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 11:14:11 2008 @@ -42,8 +42,8 @@ reset_reflective_space(space, w_rspace) return w_obj elif opname.startswith("new"): - def fn(*args_w, **kwargs): - w_obj = parentfn(*args_w, **kwargs) + def fn(*args_w): + w_obj = parentfn(*args_w) w_rspace = get_reflective_space(space) if w_rspace is not None: try: From cfbolz at codespeak.net Thu Jan 17 11:24:56 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 11:24:56 +0100 (CET) Subject: [pypy-svn] r50698 - pypy/dist/pypy/objspace Message-ID: <20080117102456.3D43116845F@codespeak.net> Author: cfbolz Date: Thu Jan 17 11:24:55 2008 New Revision: 50698 Modified: pypy/dist/pypy/objspace/reflective.py Log: don't wrap call_args either Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 11:24:55 2008 @@ -25,7 +25,7 @@ def proxymaker(space, opname, parentfn): - if opname == "wrap": + if opname in ["wrap", "call_args"]: return parentfn # no way to override wrapping for now elif opname == "newdict": # grr grr kwargs def fn(track_builtin_shadowing=False): From cfbolz at codespeak.net Thu Jan 17 11:31:00 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 11:31:00 +0100 (CET) Subject: [pypy-svn] r50699 - pypy/dist/pypy/objspace Message-ID: <20080117103100.1AE0516845F@codespeak.net> Author: cfbolz Date: Thu Jan 17 11:30:59 2008 New Revision: 50699 Modified: pypy/dist/pypy/objspace/reflective.py Log: be a bit more consistent in which operations not to wrap. I guess some of them should still be exposed, but later. Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 11:30:59 2008 @@ -24,8 +24,24 @@ ec.w_reflectivespace = w_rspace +DontWrapMe = [ + 'wrap', + 'str_w', + 'int_w', + 'float_w', + 'uint_w', + 'bigint_w', + 'unicode_w', + 'interpclass_w', + 'unwrap', + 'is_true', + 'is_w', + 'call_args', + 'marshal_w', + ] + def proxymaker(space, opname, parentfn): - if opname in ["wrap", "call_args"]: + if opname in DontWrapMe: return parentfn # no way to override wrapping for now elif opname == "newdict": # grr grr kwargs def fn(track_builtin_shadowing=False): From cfbolz at codespeak.net Thu Jan 17 12:07:06 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 12:07:06 +0100 (CET) Subject: [pypy-svn] r50700 - pypy/dist/pypy/objspace Message-ID: <20080117110706.C489416845F@codespeak.net> Author: cfbolz Date: Thu Jan 17 12:07:06 2008 New Revision: 50700 Modified: pypy/dist/pypy/objspace/reflective.py Log: use the proper way not to wrap something Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 12:07:06 2008 @@ -42,7 +42,7 @@ def proxymaker(space, opname, parentfn): if opname in DontWrapMe: - return parentfn # no way to override wrapping for now + return None elif opname == "newdict": # grr grr kwargs def fn(track_builtin_shadowing=False): w_obj = parentfn(track_builtin_shadowing) From exarkun at codespeak.net Thu Jan 17 14:47:01 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 14:47:01 +0100 (CET) Subject: [pypy-svn] r50701 - pypy/dist/pypy/module/select/test Message-ID: <20080117134701.E6D571684C5@codespeak.net> Author: exarkun Date: Thu Jan 17 14:47:00 2008 New Revision: 50701 Modified: pypy/dist/pypy/module/select/test/test_select.py Log: add docstrings for the select module test methods and clean up files in test_sleep Modified: pypy/dist/pypy/module/select/test/test_select.py ============================================================================== --- pypy/dist/pypy/module/select/test/test_select.py (original) +++ pypy/dist/pypy/module/select/test/test_select.py Thu Jan 17 14:47:00 2008 @@ -3,15 +3,28 @@ class _AppTestSelect: def test_sleep(self): + """ + The timeout parameter to select.select specifies the approximate + maximum amount of time for that function to block before it returns + to report that no results are available. + """ import time, select readend, writeend = getpair() - start = time.time() - iwtd, owtd, ewtd = select.select([readend], [], [], 0.3) - end = time.time() - assert iwtd == owtd == ewtd == [] - assert end - start > 0.25 + try: + start = time.time() + iwtd, owtd, ewtd = select.select([readend], [], [], 0.3) + end = time.time() + assert iwtd == owtd == ewtd == [] + assert end - start > 0.25 + finally: + readend.close() + writeend.close() def test_readable(self): + """ + select.select returns elements from the "read list" (the first + parameter) which may have data available to be read. + """ import select readend, writeend = getpair() try: @@ -26,6 +39,13 @@ readend.close() def test_write_read(self): + """ + select.select returns elements from the "write list" (the second + parameter) on which a write/send may be possible. select.select + returns elements from the "read list" (the first parameter) which + may have data available to be read. (the second part of this test + overlaps significantly with test_readable. -exarkun) + """ import select readend, writeend = getpair() try: @@ -54,6 +74,10 @@ readend.close() def test_close(self): + """ + select.select returns elements from the "read list" (the first + parameter) which have no data to be read but which have been closed. + """ import select, sys readend, writeend = getpair() try: @@ -83,6 +107,11 @@ readend.close() def test_read_many(self): + """ + select.select returns only the elements from the "read list" (the + first parameter) which may have data available to be read. + (test_readable has a lot of overlap with this test. -exarkun) + """ import select readends = [] writeends = [] @@ -108,6 +137,12 @@ fd.close() def test_read_end_closed(self): + """ + select.select returns elements from the "write list" (the second + parameter) when they are not writable but when the corresponding + read end has been closed. (this test currently doesn't make the + write end non-writable before testing its selectability. -exarkun) + """ import select readend, writeend = getpair() readend.close() From cfbolz at codespeak.net Thu Jan 17 16:17:33 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 16:17:33 +0100 (CET) Subject: [pypy-svn] r50702 - pypy/dist/pypy/objspace/test Message-ID: <20080117151733.999621684C9@codespeak.net> Author: cfbolz Date: Thu Jan 17 16:17:32 2008 New Revision: 50702 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: prevent the bytecode compiler optimizations from turning this into a non-test Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Thu Jan 17 16:17:32 2008 @@ -25,7 +25,9 @@ pass set_reflectivespace(Space()) - assert 1+2 == 3 + x = 1 + y = 2 + assert x + y == 3 def test_newdict(self): from __pypy__ import set_reflectivespace From arigo at codespeak.net Thu Jan 17 16:27:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 16:27:23 +0100 (CET) Subject: [pypy-svn] r50703 - pypy/dist/pypy/doc Message-ID: <20080117152723.DE4A91684C9@codespeak.net> Author: arigo Date: Thu Jan 17 16:27:21 2008 New Revision: 50703 Modified: pypy/dist/pypy/doc/eventhistory.txt Log: Fix link. Modified: pypy/dist/pypy/doc/eventhistory.txt ============================================================================== --- pypy/dist/pypy/doc/eventhistory.txt (original) +++ pypy/dist/pypy/doc/eventhistory.txt Thu Jan 17 16:27:21 2008 @@ -2,10 +2,10 @@ The PyPy project is a worldwide collaborative effort and its members are organising sprints and presenting results at conferences - all year round. The list of past events follows - see `news`_ + all year round. The list of past events follows - see `our blog`_ for upcoming events. -.. _news: news.html +.. _`our blog`: http://morepypy.blogspot.com/ EuroPython PyPy sprint 6-9 July 2006 ================================================================== From antocuni at codespeak.net Thu Jan 17 16:32:48 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jan 2008 16:32:48 +0100 (CET) Subject: [pypy-svn] r50704 - in pypy/dist/pypy/jit: codegen/i386/test codegen/llvm/test codegen/ppc/test timeshifter/test Message-ID: <20080117153248.BCB381684C9@codespeak.net> Author: antocuni Date: Thu Jan 17 16:32:48 2008 New Revision: 50704 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/ppc/test/test_interp_ts.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: oups... rename TestTimeshift a bit everywhere 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 Jan 17 16:32:48 2008 @@ -145,7 +145,7 @@ "Cannot check instructions in the generated assembler." class TestTimeshiftI386(I386TimeshiftingTestMixin, - test_timeshift.TestTimeshift): + test_timeshift.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_timeshift.py 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 Thu Jan 17 16:32:48 2008 @@ -44,7 +44,7 @@ class TestTimeshiftI386LLInterp(I386LLInterpTimeshiftingTestMixin, - test_timeshift.TestTimeshift): + test_timeshift.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_timeshift.py Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py Thu Jan 17 16:32:48 2008 @@ -10,7 +10,7 @@ class TestTimeshiftLLVM(LLVMTimeshiftingTestMixin, - test_timeshift.TestTimeshift): + test_timeshift.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_timeshift.py Modified: pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py (original) +++ pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py Thu Jan 17 16:32:48 2008 @@ -7,7 +7,7 @@ RGenOp = RPPCGenOp class TestTimeshiftPPC(PPCTimeshiftingTestMixin, - test_timeshift.TestTimeshift): + test_timeshift.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_timeshift.py Modified: pypy/dist/pypy/jit/codegen/ppc/test/test_interp_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/ppc/test/test_interp_ts.py (original) +++ pypy/dist/pypy/jit/codegen/ppc/test/test_interp_ts.py Thu Jan 17 16:32:48 2008 @@ -12,7 +12,7 @@ from pypy.jit.codegen.ppc.test.test_interp import LLTypeRGenOp as RGenOp class TestTimeshiftPPC(PPCLLInterpTimeshiftingTestMixin, - test_timeshift.TestTimeshift): + test_timeshift.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_timeshift.py 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 Jan 17 16:32:48 2008 @@ -701,11 +701,11 @@ res = self.timeshift(ll_function, [0], []) assert res == "4" - if self.__class__ is TestTimeshift: + if self.__class__ in (TestLLType, TestOOType): assert lltype.parentlink(glob_result.s._obj) == (None, None) res = self.timeshift(ll_function, [1], []) assert res == "3" - if self.__class__ is TestTimeshift: + if self.__class__ in (TestLLType, TestOOType): parent, parentindex = lltype.parentlink(glob_result.s._obj) assert parentindex == 's' assert parent.n == 3.25 From fijal at codespeak.net Thu Jan 17 16:36:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 16:36:26 +0100 (CET) Subject: [pypy-svn] r50705 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080117153626.77FA31684CE@codespeak.net> Author: fijal Date: Thu Jan 17 16:36:25 2008 New Revision: 50705 Modified: pypy/dist/pypy/lib/_ctypes/pointer.py Log: Kill tab Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Thu Jan 17 16:36:25 2008 @@ -35,8 +35,8 @@ def from_param(self, value): if value is None: return 0 - # If we expect POINTER(), but receive a instance, accept - # it by calling byref(). + # If we expect POINTER(), but receive a instance, accept + # it by calling byref(). if isinstance(value, self._type_): return byref(value) # Array instances are also pointers when the item types are the same. From arigo at codespeak.net Thu Jan 17 16:55:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 16:55:49 +0100 (CET) Subject: [pypy-svn] r50706 - pypy/dist/pypy/jit/codegen/llgraph Message-ID: <20080117155549.B5C091684C5@codespeak.net> Author: arigo Date: Thu Jan 17 16:55:49 2008 New Revision: 50706 Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Log: Fix test. 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 Jan 17 16:55:49 2008 @@ -479,9 +479,10 @@ # and an OO tuple, so we need to make the llinterpreter thinking that # its _TYPE is compatible both with a struct and a # record. TwoFacedType does exactly this. -class TwoFacedType(ootype.BuiltinType): +class TwoFacedType(lltype.Ptr, ootype.BuiltinType): def __init__(self, TYPE1, TYPE2): self.TYPE1 = TYPE1 + self.TO = TYPE1.TO # this must be the LL type, a Ptr self.TYPE2 = TYPE2 def __eq__(self, other): From arigo at codespeak.net Thu Jan 17 17:00:54 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:00:54 +0100 (CET) Subject: [pypy-svn] r50707 - pypy/dist/pypy/rpython/test Message-ID: <20080117160054.CF5801684C5@codespeak.net> Author: arigo Date: Thu Jan 17 17:00:54 2008 New Revision: 50707 Modified: pypy/dist/pypy/rpython/test/test_llann.py Log: Fix imports. 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 Thu Jan 17 17:00:54 2008 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem.lltype import * -from pypy.rpython.rclass import OBJECTPTR, fishllattr +from pypy.rpython.lltypesystem.rclass import OBJECTPTR +from pypy.rpython.rclass import fishllattr from pypy.translator.translator import TranslationContext from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import annotate_lowlevel_helper From arigo at codespeak.net Thu Jan 17 17:04:41 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:04:41 +0100 (CET) Subject: [pypy-svn] r50708 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080117160441.23C351684C5@codespeak.net> Author: arigo Date: Thu Jan 17 17:04:40 2008 New Revision: 50708 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: Comment. Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Thu Jan 17 17:04:40 2008 @@ -638,6 +638,8 @@ raise NotImplementedError("casting %r to %r" % (TYPE1, RESTYPE)) if isinstance(RESTYPE, lltype.Ptr): + # upgrade to a more recent ctypes (e.g. 1.0.2) if you get + # an OverflowError on the following line. cvalue = ctypes.cast(ctypes.c_void_p(cvalue), cresulttype) else: cvalue = cresulttype(cvalue).value # mask high bits off if needed From arigo at codespeak.net Thu Jan 17 17:08:06 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:08:06 +0100 (CET) Subject: [pypy-svn] r50709 - pypy/dist/pypy/lib/app_test Message-ID: <20080117160806.186771684C5@codespeak.net> Author: arigo Date: Thu Jan 17 17:08:05 2008 New Revision: 50709 Removed: pypy/dist/pypy/lib/app_test/test_ctypes.py Log: (fijal) Kill old tests. From arigo at codespeak.net Thu Jan 17 17:17:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:17:58 +0100 (CET) Subject: [pypy-svn] r50710 - in pypy/dist/pypy/lib: _ctypes/test ctypes/test Message-ID: <20080117161758.177411684C5@codespeak.net> Author: arigo Date: Thu Jan 17 17:17:57 2008 New Revision: 50710 Added: pypy/dist/pypy/lib/ctypes/test/conftest.py (contents, props changed) Removed: pypy/dist/pypy/lib/_ctypes/test/ Log: Kill old tests. Skip the original (unported) ctypes tests. Added: pypy/dist/pypy/lib/ctypes/test/conftest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/ctypes/test/conftest.py Thu Jan 17 17:17:57 2008 @@ -0,0 +1,8 @@ +"""These are the original ctypes tests. +You can try to run them with 'pypy-c runtests.py'.""" + +import py + +class Directory(py.test.collect.Directory): + def run(self): + py.test.skip(__doc__) From arigo at codespeak.net Thu Jan 17 17:39:01 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:39:01 +0100 (CET) Subject: [pypy-svn] r50711 - in pypy/dist/pypy: module/fcntl rpython/lltypesystem Message-ID: <20080117163901.A0BF31684C9@codespeak.net> Author: arigo Date: Thu Jan 17 17:38:59 2008 New Revision: 50711 Modified: pypy/dist/pypy/module/fcntl/interp_fcntl.py pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Fix fcntl. Add a helper rffi.charpsize2str(). Modified: pypy/dist/pypy/module/fcntl/interp_fcntl.py ============================================================================== --- pypy/dist/pypy/module/fcntl/interp_fcntl.py (original) +++ pypy/dist/pypy/module/fcntl/interp_fcntl.py Thu Jan 17 17:38:59 2008 @@ -122,12 +122,12 @@ return space.wrap(rv) elif space.is_w(space.type(w_arg), space.w_str): arg = space.str_w(w_arg) - if len(arg) > 1024: + if len(arg) > 1024: # XXX probably makes no sense for PyPy raise OperationError(space.w_ValueError, space.wrap("fcntl string arg too long")) ll_arg = rffi.str2charp(arg) rv = fcntl_str(fd, op, ll_arg) - arg = rffi.charp2str(ll_arg) + arg = rffi.charpsize2str(ll_arg, len(arg)) lltype.free(ll_arg, flavor='raw') if rv < 0: raise OperationError(space.w_IOError, Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Jan 17 17:38:59 2008 @@ -410,6 +410,11 @@ i += 1 return "".join(l) +# char* and size -> str (which can contain null bytes) +def charpsize2str(cp, size): + l = [cp[i] for i in range(size)] + return "".join(l) + # char** CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True})) From arigo at codespeak.net Thu Jan 17 17:42:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:42:31 +0100 (CET) Subject: [pypy-svn] r50712 - pypy/dist/pypy/module/struct/test Message-ID: <20080117164231.015D61684C9@codespeak.net> Author: arigo Date: Thu Jan 17 17:42:31 2008 New Revision: 50712 Modified: pypy/dist/pypy/module/struct/test/test_ieee.py Log: CPython 2.4's struct module doesn't fully support 'inf' and 'nan'. Modified: pypy/dist/pypy/module/struct/test/test_ieee.py ============================================================================== --- pypy/dist/pypy/module/struct/test/test_ieee.py (original) +++ pypy/dist/pypy/module/struct/test/test_ieee.py Thu Jan 17 17:42:31 2008 @@ -1,5 +1,6 @@ +import sys from pypy.module.struct.ieee import pack_float, unpack_float -from pypy.rlib.rarithmetic import isnan +from pypy.rlib.rarithmetic import isinf, isnan testcases = [ (-0.025, 4, False, '\xcd\xcc\xcc\xbc'), @@ -22,6 +23,8 @@ def test_correct_tests(): import struct for number, size, bigendian, expected in testcases: + if sys.version < (2, 5) and (isinf(number) or isnan(number)): + continue # 'inf' and 'nan' unsupported in CPython 2.4's struct if bigendian: fmt = '>' else: From arigo at codespeak.net Thu Jan 17 17:47:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:47:10 +0100 (CET) Subject: [pypy-svn] r50713 - pypy/dist/pypy/module/fcntl Message-ID: <20080117164710.789BA1684C9@codespeak.net> Author: arigo Date: Thu Jan 17 17:47:10 2008 New Revision: 50713 Modified: pypy/dist/pypy/module/fcntl/interp_fcntl.py Log: Fix fcntl.ioctl() in the same way. The appropriate test-that-failed-before-this-fix is in test_termios. Modified: pypy/dist/pypy/module/fcntl/interp_fcntl.py ============================================================================== --- pypy/dist/pypy/module/fcntl/interp_fcntl.py (original) +++ pypy/dist/pypy/module/fcntl/interp_fcntl.py Thu Jan 17 17:47:10 2008 @@ -263,7 +263,7 @@ ll_arg = rffi.str2charp(arg) rv = ioctl_str(fd, op, ll_arg) - arg = rffi.charp2str(ll_arg) + arg = rffi.charpsize2str(ll_arg, len(arg)) lltype.free(ll_arg, flavor='raw') if rv < 0: raise OperationError(space.w_IOError, From arigo at codespeak.net Thu Jan 17 17:49:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:49:10 +0100 (CET) Subject: [pypy-svn] r50714 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080117164910.826021684C9@codespeak.net> Author: arigo Date: Thu Jan 17 17:49:10 2008 New Revision: 50714 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Fix test. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Jan 17 17:49:10 2008 @@ -683,10 +683,15 @@ def test_prebuilt_constant(self): header = py.code.Source(""" + #ifndef _SOME_H + #define _SOME_H + #include static int x = 3; char **z = NULL; + + #endif /* _SOME_H */ """) h_file = udir.join("some_h.h") h_file.write(header) From exarkun at codespeak.net Thu Jan 17 17:54:58 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 17:54:58 +0100 (CET) Subject: [pypy-svn] r50715 - in pypy/dist/pypy/module/select: . test Message-ID: <20080117165458.050E21684C9@codespeak.net> Author: exarkun Date: Thu Jan 17 17:54:58 2008 New Revision: 50715 Modified: pypy/dist/pypy/module/select/app_select.py pypy/dist/pypy/module/select/test/test_select.py Log: Fix select readability of write pipes Add a test asserting that the write end of a pipe is indicated as readable by select when the read end has been closed. The read set indicates either that data may be available or that the file descriptor is at EOF. There are probably still some bugs in select.select() (particularly the exception set). Modified: pypy/dist/pypy/module/select/app_select.py ============================================================================== --- pypy/dist/pypy/module/select/app_select.py (original) +++ pypy/dist/pypy/module/select/app_select.py Thu Jan 17 17:54:58 2008 @@ -63,7 +63,7 @@ else: ret = dict(p.poll()) - iretd = [ f for f in iwtd if ret.get(fddict[id(f)], 0) & (POLLIN|POLLHUP)] + iretd = [ f for f in iwtd if ret.get(fddict[id(f)], 0) & (POLLIN|POLLHUP|POLLERR)] oretd = [ f for f in owtd if ret.get(fddict[id(f)], 0) & POLLOUT] eretd = [ f for f in ewtd if ret.get(fddict[id(f)], 0) & (POLLERR|POLLPRI)] Modified: pypy/dist/pypy/module/select/test/test_select.py ============================================================================== --- pypy/dist/pypy/module/select/test/test_select.py (original) +++ pypy/dist/pypy/module/select/test/test_select.py Thu Jan 17 17:54:58 2008 @@ -38,6 +38,21 @@ writeend.close() readend.close() + def test_writable(self): + """ + select.select returns elements from the "write list" (the second + parameter) on which a write/send may be possible. + """ + import select + readend, writeend = getpair() + try: + iwtd, owtd, ewtd = select.select([], [writeend], [], 0) + assert iwtd == ewtd == [] + assert owtd == [writeend] + finally: + writeend.close() + readend.close() + def test_write_read(self): """ select.select returns elements from the "write list" (the second @@ -73,7 +88,7 @@ writeend.close() readend.close() - def test_close(self): + def test_write_close(self): """ select.select returns elements from the "read list" (the first parameter) which have no data to be read but which have been closed. @@ -106,6 +121,22 @@ finally: readend.close() + def test_read_closed(self): + """ + select.select returns elements from the "read list" (the first + parameter) which are at eof (even if they are the write end of a + pipe). + """ + import select + readend, writeend = getpair() + try: + readend.close() + iwtd, owtd, ewtd = select.select([writeend], [], [], 0) + assert iwtd == [writeend] + assert owtd == ewtd == [] + finally: + writeend.close() + def test_read_many(self): """ select.select returns only the elements from the "read list" (the From arigo at codespeak.net Thu Jan 17 17:56:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 17:56:19 +0100 (CET) Subject: [pypy-svn] r50716 - pypy/dist/pypy/translator/tool Message-ID: <20080117165619.1943A1684C9@codespeak.net> Author: arigo Date: Thu Jan 17 17:56:18 2008 New Revision: 50716 Modified: pypy/dist/pypy/translator/tool/cbuild.py Log: Silence some of the warnings 'no newline at the end of file'. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Thu Jan 17 17:56:18 2008 @@ -131,7 +131,10 @@ if being_main: f.write("#define PYPY_NOT_MAIN_FILE\n") self.write_c_header(f) - f.write(str(source)) + source = str(source) + f.write(source) + if not source.endswith('\n'): + f.write('\n') f.close() files.append(str(filename)) d = self._copy_attributes() From arigo at codespeak.net Thu Jan 17 18:02:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 18:02:32 +0100 (CET) Subject: [pypy-svn] r50717 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080117170232.19D31168444@codespeak.net> Author: arigo Date: Thu Jan 17 18:02:31 2008 New Revision: 50717 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: Fix tests. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Thu Jan 17 18:02:31 2008 @@ -216,9 +216,12 @@ def test_opaque_type(self): h_source = py.code.Source(""" + #ifndef _OPAQUE_H + #define _OPAQUE_H struct stuff { char data[38]; }; + #endif /* _OPAQUE_H */ """) c_source = py.code.Source(""" @@ -322,6 +325,16 @@ def eating_callback(self): h_source = py.code.Source(""" + #ifndef _CALLBACK_H + #define _CALLBACK_H + extern int eating_callback(int arg, int(*call)(int)); + #endif /* _CALLBACK_H */ + """) + + h_include = udir.join('callback.h') + h_include.write(h_source) + + c_source = py.code.Source(""" int eating_callback(int arg, int(*call)(int)) { int res = call(arg); @@ -330,12 +343,10 @@ return res; } """) - - h_include = udir.join('callback.h') - h_include.write(h_source) eci = ExternalCompilationInfo(includes=['callback.h'], - include_dirs=[str(udir)]) + include_dirs=[str(udir)], + separate_module_sources=[c_source]) args = [INT, CCallback([INT], INT)] eating_callback = llexternal('eating_callback', args, INT, From antocuni at codespeak.net Thu Jan 17 18:20:16 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jan 2008 18:20:16 +0100 (CET) Subject: [pypy-svn] r50718 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080117172016.2CC011684CB@codespeak.net> Author: antocuni Date: Thu Jan 17 18:20:16 2008 New Revision: 50718 Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: fix some more tests Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_portal.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_portal.py Thu Jan 17 18:20:16 2008 @@ -1,6 +1,6 @@ from pypy import conftest from pypy.translator.translator import graphof -from pypy.jit.timeshifter.test.test_timeshift import hannotate, getargtypes +from pypy.jit.timeshifter.test.test_timeshift import TestLLType as TSTestLLType, getargtypes from pypy.jit.timeshifter.hrtyper import HintRTyper from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL, StopAtXPolicy from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC @@ -53,7 +53,7 @@ assert argtypes == getargtypes(self.rtyper.annotator, main_args) return main_args - hs, ha, self.rtyper = hannotate(main, main_args, portal=portal, + hs, ha, self.rtyper = TSTestLLType.hannotate(main, main_args, portal=portal, policy=policy, inline=inline, backendoptimize=backendoptimize) 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 Jan 17 18:20:16 2008 @@ -49,8 +49,8 @@ class TimeshiftingTests(object): RGenOp = LLRGenOp - small = True + type_system = 'lltype' # because a lot of tests inherits from this class def setup_class(cls): from pypy.jit.timeshifter.test.conftest import option @@ -65,14 +65,15 @@ del cls._cache del cls._cache_order - def hannotate(self, func, values, policy=None, inline=None, backendoptimize=False, + @classmethod + def hannotate(cls, func, values, policy=None, inline=None, backendoptimize=False, portal=None): # build the normal ll graphs for ll_function t = TranslationContext() a = t.buildannotator() argtypes = getargtypes(a, values) a.build_types(func, argtypes) - rtyper = t.buildrtyper(type_system = self.type_system) + rtyper = t.buildrtyper(type_system = cls.type_system) rtyper.specialize() if inline: auto_inlining(t, threshold=inline) @@ -82,7 +83,7 @@ if portal is None: portal = func - policy = self.fixpolicy(policy) + policy = cls.fixpolicy(policy) if hasattr(policy, "seetranslator"): policy.seetranslator(t) graph1 = graphof(t, portal) @@ -96,9 +97,10 @@ hannotator.translator.view() return hs, hannotator, rtyper - def fixpolicy(self, policy): + @classmethod + def fixpolicy(cls, policy): import copy - if self.type_system == 'ootype' and policy is not None: + if cls.type_system == 'ootype' and policy is not None: newpolicy = copy.copy(policy) newpolicy.oopspec = False return newpolicy From cfbolz at codespeak.net Thu Jan 17 18:25:34 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 18:25:34 +0100 (CET) Subject: [pypy-svn] r50719 - pypy/dist/pypy/objspace/std Message-ID: <20080117172534.CD7A41684CB@codespeak.net> Author: cfbolz Date: Thu Jan 17 18:25:32 2008 New Revision: 50719 Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py pypy/dist/pypy/objspace/std/dictobject.py pypy/dist/pypy/objspace/std/listmultiobject.py pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/objspace.py Log: fix a bug in the std object space that only occurred in combination with the reflective object space: createexecutioncontext must not call space methods that need the execution context to already exist. Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Thu Jan 17 18:25:32 2008 @@ -1286,7 +1286,10 @@ def repr__DictMulti(space, w_dict): if w_dict.implementation.length() == 0: return space.wrap('{}') - w_currently_in_repr = space.getexecutioncontext()._py_repr + ec = space.getexecutioncontext() + w_currently_in_repr = ec._py_repr + if w_currently_in_repr is None: + w_currently_in_repr = ec._py_repr = space.newdict() return dictrepr(space, w_currently_in_repr, w_dict) Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Thu Jan 17 18:25:32 2008 @@ -217,7 +217,10 @@ def repr__Dict(space, w_dict): if len(w_dict.content) == 0: return space.wrap('{}') - w_currently_in_repr = space.getexecutioncontext()._py_repr + ec = space.getexecutioncontext() + w_currently_in_repr = ec._py_repr + if w_currently_in_repr is None: + w_currently_in_repr = ec._py_repr = space.newdict() return dictrepr(space, w_currently_in_repr, w_dict) Modified: pypy/dist/pypy/objspace/std/listmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/listmultiobject.py Thu Jan 17 18:25:32 2008 @@ -1154,7 +1154,10 @@ def repr__ListMulti(space, w_list): if w_list.implementation.length() == 0: return space.wrap('[]') - w_currently_in_repr = space.getexecutioncontext()._py_repr + ec = space.getexecutioncontext() + w_currently_in_repr = ec._py_repr + if w_currently_in_repr is None: + w_currently_in_repr = ec._py_repr = space.newdict() return listrepr(space, w_currently_in_repr, w_list) def list_insert__ListMulti_ANY_ANY(space, w_list, w_where, w_any): Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Thu Jan 17 18:25:32 2008 @@ -327,7 +327,10 @@ def repr__List(space, w_list): if len(w_list.wrappeditems) == 0: return space.wrap('[]') - w_currently_in_repr = space.getexecutioncontext()._py_repr + ec = space.getexecutioncontext() + w_currently_in_repr = ec._py_repr + if w_currently_in_repr is None: + w_currently_in_repr = ec._py_repr = space.newdict() return listrepr(space, w_currently_in_repr, w_list) def list_insert__List_ANY_ANY(space, w_list, w_where, w_any): Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jan 17 18:25:32 2008 @@ -364,8 +364,10 @@ def createexecutioncontext(self): # add space specific fields to execution context + # note that this method must not call space methods that might need an + # execution context themselves (e.g. nearly all space methods) ec = ObjSpace.createexecutioncontext(self) - ec._py_repr = self.newdict() + ec._py_repr = None if self.config.objspace.std.withmethodcache: SIZE = 1 << self.config.objspace.std.methodcachesizeexp ec.method_cache_versions = [None] * SIZE From cfbolz at codespeak.net Thu Jan 17 18:25:53 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 18:25:53 +0100 (CET) Subject: [pypy-svn] r50720 - pypy/dist/pypy/objspace Message-ID: <20080117172553.972F81684CE@codespeak.net> Author: cfbolz Date: Thu Jan 17 18:25:52 2008 New Revision: 50720 Modified: pypy/dist/pypy/objspace/reflective.py Log: simplify a bit Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 18:25:52 2008 @@ -89,18 +89,14 @@ fn.func_name = opname return fn -def createexecutioncontextmaker(space, parentfn): - def createexecutioncontext(): - ec = parentfn() +class ReflectiveObjSpace(std.Space): + def createexecutioncontext(self): + ec = std.Space.createexecutioncontext(self) ec.w_reflectivespace = None return ec - return createexecutioncontext def Space(*args, **kwds): - space = std.Space(*args, **kwds) - space.createexecutioncontext = createexecutioncontextmaker( - space, space.createexecutioncontext) - space.getexecutioncontext().w_reflectivespace = None # patch the already built ec + space = ReflectiveObjSpace(*args, **kwds) patch_space_in_place(space, 'reflective', proxymaker) w___pypy__ = space.getbuiltinmodule("__pypy__") space.setattr(w___pypy__, space.wrap('set_reflectivespace'), From cfbolz at codespeak.net Thu Jan 17 18:48:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 18:48:10 +0100 (CET) Subject: [pypy-svn] r50721 - pypy/dist/pypy/objspace/std Message-ID: <20080117174810.2C3CC1684CA@codespeak.net> Author: cfbolz Date: Thu Jan 17 18:48:09 2008 New Revision: 50721 Modified: pypy/dist/pypy/objspace/std/typeobject.py Log: bug coming apparent only when your space.newdict does something sufficiently strange Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Thu Jan 17 18:48:09 2008 @@ -403,7 +403,10 @@ dictspec = [] for key, w_value in w_self.dict_w.items(): dictspec.append((space.wrap(key), w_value)) - newdic = space.newdict() + # speed hack: instantiate a dict object cls directly + # NB: cannot use newdict, because that could return something else + # than an instance of DictObjectCls + newdic = space.DictObjectCls(space) newdic.initialize_content(dictspec) return W_DictProxyObject(newdic) From antocuni at codespeak.net Thu Jan 17 18:51:31 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jan 2008 18:51:31 +0100 (CET) Subject: [pypy-svn] r50722 - pypy/dist/pypy/translator/jvm Message-ID: <20080117175131.0B3CF1684CA@codespeak.net> Author: antocuni Date: Thu Jan 17 18:51:31 2008 New Revision: 50722 Modified: pypy/dist/pypy/translator/jvm/generator.py Log: don't put unnecessary spaces at the end of the line Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Thu Jan 17 18:51:31 2008 @@ -1456,7 +1456,7 @@ strargs = [jasmin_syntax(arg) for arg in args] instr_text = '%s %s' % (jvmstr, " ".join(strargs)) self.curclass.out(' .line %d\n' % self.curclass.line_number) - self.curclass.out(' %-60s\n' % (instr_text,)) + self.curclass.out(' %s\n' % (instr_text,)) self.curfunc.instr_counter+=1 def try_catch_region(self, jexcclsty, trystartlbl, tryendlbl, catchlbl): From arigo at codespeak.net Thu Jan 17 18:54:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 17 Jan 2008 18:54:36 +0100 (CET) Subject: [pypy-svn] r50723 - pypy/dist/pypy/rpython/test Message-ID: <20080117175436.3F6981684CA@codespeak.net> Author: arigo Date: Thu Jan 17 18:54:35 2008 New Revision: 50723 Modified: pypy/dist/pypy/rpython/test/test_rclass.py Log: Add a test that explains why test_specialize_methods fails in the jvm backend. Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Thu Jan 17 18:54:35 2008 @@ -592,6 +592,27 @@ res = self.interpret(f, []) assert res == -7 + def test_instantiate_despite_abstract_methods(self): + class A: + pass + class B(A): + def foo(self): + return 42 + def fn(n): + # Although the code below is a bit strange, there are + # subtle ways in which the same situation could occur. + # One is shown by test_specialize_methods(). + if n < 0: + x = B() + else: + x = A() + if n < -3: + return x.foo() + else: + return 100 + assert self.interpret(fn, [-5]) == 42 + assert self.interpret(fn, [5]) == 100 + def test_specialize_methods(self): from pypy.rlib.objectmodel import specialize class A: From cfbolz at codespeak.net Thu Jan 17 19:16:48 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 19:16:48 +0100 (CET) Subject: [pypy-svn] r50724 - pypy/dist/pypy/objspace Message-ID: <20080117181648.F149C1684CA@codespeak.net> Author: cfbolz Date: Thu Jan 17 19:16:48 2008 New Revision: 50724 Modified: pypy/dist/pypy/objspace/reflective.py Log: factor out some common code Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 19:16:48 2008 @@ -43,48 +43,40 @@ def proxymaker(space, opname, parentfn): if opname in DontWrapMe: return None - elif opname == "newdict": # grr grr kwargs + def user_hook(*args_w): + if w_rspace is not None: + try: + w_f = space.getattr(w_rspace, space.wrap("newdict")) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + w_obj = space.call_function(w_f, w_obj) + reset_reflective_space(space, w_rspace) + return w_obj + return None + + if opname == "newdict": # grr grr kwargs def fn(track_builtin_shadowing=False): w_obj = parentfn(track_builtin_shadowing) w_rspace = get_reflective_space(space) - if w_rspace is not None: - try: - w_f = space.getattr(w_rspace, space.wrap("newdict")) - except OperationError, e: - if not e.match(space, space.w_AttributeError): - raise - else: - w_obj = space.call_function(w_f, w_obj) - reset_reflective_space(space, w_rspace) + w_newobj = user_hook(w_obj) + if w_newobj is not None: + return w_newobj return w_obj elif opname.startswith("new"): def fn(*args_w): w_obj = parentfn(*args_w) w_rspace = get_reflective_space(space) - if w_rspace is not None: - try: - w_f = space.getattr(w_rspace, space.wrap(opname)) - except OperationError, e: - if not e.match(space, space.w_AttributeError): - raise - else: - w_obj = space.call_function(w_f, w_obj) - reset_reflective_space(space, w_rspace) + w_newobj = user_hook(w_obj) + if w_newobj is not None: + return w_newobj return w_obj else: def fn(*args_w): - ec = space.getexecutioncontext() - w_rspace = get_reflective_space(space) - if w_rspace is not None: - try: - w_f = space.getattr(w_rspace, space.wrap(opname)) - except OperationError, e: - if not e.match(space, space.w_AttributeError): - raise - else: - w_res = space.call_function(w_f, *args_w) - reset_reflective_space(space, w_rspace) - return w_res + w_obj = user_hook(*args_w) + if w_obj is not None: + return w_obj return parentfn(*args_w) fn.func_name = opname return fn From cfbolz at codespeak.net Thu Jan 17 19:25:22 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 19:25:22 +0100 (CET) Subject: [pypy-svn] r50725 - pypy/dist/pypy/objspace Message-ID: <20080117182522.E80EB16840A@codespeak.net> Author: cfbolz Date: Thu Jan 17 19:25:20 2008 New Revision: 50725 Modified: pypy/dist/pypy/objspace/reflective.py Log: running tests is good Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 19:25:20 2008 @@ -1,6 +1,7 @@ from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.objspace import std +from pypy.objspace.std.typeobject import W_TypeObject from pypy.objspace.proxy import patch_space_in_place def set_reflectivespace(space, w_reflectivespace): @@ -44,14 +45,15 @@ if opname in DontWrapMe: return None def user_hook(*args_w): + w_rspace = get_reflective_space(space) if w_rspace is not None: try: - w_f = space.getattr(w_rspace, space.wrap("newdict")) + w_f = space.getattr(w_rspace, space.wrap(opname)) except OperationError, e: if not e.match(space, space.w_AttributeError): raise else: - w_obj = space.call_function(w_f, w_obj) + w_obj = space.call_function(w_f, *args_w) reset_reflective_space(space, w_rspace) return w_obj return None @@ -59,7 +61,6 @@ if opname == "newdict": # grr grr kwargs def fn(track_builtin_shadowing=False): w_obj = parentfn(track_builtin_shadowing) - w_rspace = get_reflective_space(space) w_newobj = user_hook(w_obj) if w_newobj is not None: return w_newobj @@ -67,7 +68,6 @@ elif opname.startswith("new"): def fn(*args_w): w_obj = parentfn(*args_w) - w_rspace = get_reflective_space(space) w_newobj = user_hook(w_obj) if w_newobj is not None: return w_newobj From antocuni at codespeak.net Thu Jan 17 20:01:14 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jan 2008 20:01:14 +0100 (CET) Subject: [pypy-svn] r50726 - in pypy/dist/pypy/translator/jvm: . src/pypy Message-ID: <20080117190114.87F7C168473@codespeak.net> Author: antocuni Date: Thu Jan 17 20:01:13 2008 New Revision: 50726 Added: pypy/dist/pypy/translator/jvm/src/pypy/AbstractMethodException.java Modified: pypy/dist/pypy/translator/jvm/node.py pypy/dist/pypy/translator/jvm/typesystem.py Log: (antocuni, arigo) fix a couple a failing tests Modified: pypy/dist/pypy/translator/jvm/node.py ============================================================================== --- pypy/dist/pypy/translator/jvm/node.py (original) +++ pypy/dist/pypy/translator/jvm/node.py Thu Jan 17 20:01:13 2008 @@ -22,7 +22,7 @@ from pypy.translator.jvm.typesystem import \ JvmGeneratedClassType, jString, jStringArray, jVoid, jThrowable, jInt, \ jObject, JvmType, jStringBuilder, jPyPyInterlink, jCallbackInterfaces, \ - JvmGeneratedInterfaceType, jPyPy + JvmGeneratedInterfaceType, jPyPy, jPyPyAbstractMethodException from pypy.translator.jvm.opcodes import \ opcodes from pypy.translator.jvm.option import \ @@ -687,7 +687,6 @@ """ JvmGeneratedClassType.__init__(self, name) self.rendered = False # has rendering occurred? - self.abstract = False # is this an abstract class? self.fields = {} # maps field name to jvmgen.Field object self.interfaces = [] # list of JvmTypes self.methods = {} # maps method name to a Function object* @@ -744,12 +743,11 @@ """ Adds an abstract method to our list of methods; jmethod should be a jvmgen.Method object """ assert jmethod.method_name not in self.methods - self.abstract = True self.abstract_methods[jmethod.method_name] = jmethod def render(self, gen): self.rendered = True - gen.begin_class(self, self.super_class, abstract=self.abstract) + gen.begin_class(self, self.super_class) for inter in self.interfaces: gen.implements(inter) @@ -772,7 +770,9 @@ method.render(gen) for method in self.abstract_methods.values(): - gen.begin_j_function(self, method, abstract=True) + gen.begin_j_function(self, method) + gen.new_with_jtype(jPyPyAbstractMethodException) + gen.throw() gen.end_function() gen.end_class() Added: pypy/dist/pypy/translator/jvm/src/pypy/AbstractMethodException.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/pypy/AbstractMethodException.java Thu Jan 17 20:01:13 2008 @@ -0,0 +1,8 @@ +package pypy; + +public class AbstractMethodException extends Exception { + + public AbstractMethodException(){ + super("Cannot call RPython abstract methods"); + } +} Modified: pypy/dist/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/dist/pypy/translator/jvm/typesystem.py (original) +++ pypy/dist/pypy/translator/jvm/typesystem.py Thu Jan 17 20:01:13 2008 @@ -199,6 +199,7 @@ jPyPyRecordStringString = JvmClassType('pypy.RecordStringString') jPyPyRecordFloatSigned = JvmClassType('pypy.RecordFloatSigned') jPyPyRecordFloatFloat = JvmClassType('pypy.RecordFloatFloat') +jPyPyAbstractMethodException = JvmClassType('pypy.AbstractMethodException') jArithmeticException = JvmClassType('java.lang.ArithmeticException', throwable=True) From cfbolz at codespeak.net Thu Jan 17 20:14:24 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 17 Jan 2008 20:14:24 +0100 (CET) Subject: [pypy-svn] r50727 - in pypy/dist/pypy/objspace: . test Message-ID: <20080117191424.581B61684CB@codespeak.net> Author: cfbolz Date: Thu Jan 17 20:14:24 2008 New Revision: 50727 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: (arigo, antocuni, cfbolz): force space.type to return a W_TypeObject Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 17 20:14:24 2008 @@ -6,7 +6,7 @@ def set_reflectivespace(space, w_reflectivespace): ec = space.getexecutioncontext() - if space.is_w(ec.w_reflectivespace, space.w_None): + if space.is_w(w_reflectivespace, space.w_None): ec.w_reflectivespace = None else: ec.w_reflectivespace = w_reflectivespace @@ -48,14 +48,15 @@ w_rspace = get_reflective_space(space) if w_rspace is not None: try: - w_f = space.getattr(w_rspace, space.wrap(opname)) - except OperationError, e: - if not e.match(space, space.w_AttributeError): - raise - else: - w_obj = space.call_function(w_f, *args_w) + try: + w_f = space.getattr(w_rspace, space.wrap(opname)) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + return space.call_function(w_f, *args_w) + finally: reset_reflective_space(space, w_rspace) - return w_obj return None if opname == "newdict": # grr grr kwargs @@ -66,12 +67,22 @@ return w_newobj return w_obj elif opname.startswith("new"): - def fn(*args_w): - w_obj = parentfn(*args_w) + def fn(*args): + w_obj = parentfn(*args) w_newobj = user_hook(w_obj) if w_newobj is not None: return w_newobj return w_obj + elif opname == "type": + def fn(*args_w): + w_obj = user_hook(*args_w) + if w_obj is not None: + if not isinstance(w_obj, W_TypeObject): + raise OperationError( + space.w_TypeError, + space.wrap("space.type must return a type object!")) + return w_obj + return parentfn(*args_w) else: def fn(*args_w): w_obj = user_hook(*args_w) Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Thu Jan 17 20:14:24 2008 @@ -17,7 +17,9 @@ assert x + y == 42 set_reflectivespace(None) - assert 1+2 == 3 + x = 1 + y = 2 + assert x + y == 3 def test_default_behaviour(self): from __pypy__ import set_reflectivespace @@ -53,3 +55,31 @@ l = [1, 2, 3, 4, 5] assert len(l) == 6 set_reflectivespace(None) + + def test_type_must_return_type(self): + from __pypy__ import set_reflectivespace + class Space: + def type(self, o): + if o is l: + return 1 + return type(o) + l = [] + set_reflectivespace(Space()) + raises(TypeError, type, l) + set_reflectivespace(None) + + def test_type(self): + from __pypy__ import set_reflectivespace + class Space: + def type(self, o): + if o is a: + return B + return type(o) + type(1) + class A(object): + f = lambda self: 1 + class B(object): + f = lambda self: 2 + a = A() + set_reflectivespace(Space()) + assert a.f() == 2 From fijal at codespeak.net Thu Jan 17 20:23:14 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 20:23:14 +0100 (CET) Subject: [pypy-svn] r50728 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080117192314.F04F21684DD@codespeak.net> Author: fijal Date: Thu Jan 17 20:23:14 2008 New Revision: 50728 Modified: pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: A bit of hacking for having two different letters stored - one for calling the other for structures. This eventually dies together with _rawffi support. Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Thu Jan 17 20:23:14 2008 @@ -7,7 +7,7 @@ def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_type_' in typedict: - ffiarray = _rawffi.Array(typedict['_type_']._ffiletter) + ffiarray = _rawffi.Array(typedict['_type_']._ffishape) res._ffiarray = ffiarray if getattr(typedict['_type_'], '_type_', None) == 'c': def getvalue(self): @@ -30,6 +30,8 @@ for i in range(len(buffer)): self[i] = buffer[i] res.raw = property(getraw, setraw) + if '_length_' in typedict: + res._ffishape = ffiarray.gettypecode(typedict['_length_']) else: res._ffiarray = None return res Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Thu Jan 17 20:23:14 2008 @@ -12,7 +12,8 @@ size = _rawffi.sizeof('P'), align = _rawffi.alignment('P'), length = 1, - _ffiletter = 'P' + _ffiletter = 'P', + _ffishape = 'P', ) # XXX check if typedict['_type_'] is any sane # XXX remember about paramfunc Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Thu Jan 17 20:23:14 2008 @@ -41,6 +41,7 @@ ffiarray = _rawffi.Array(tp) result = type.__new__(self, name, bases, dct) result._ffiletter = tp + result._ffishape = tp result._ffiarray = ffiarray if tp == 'z': # c_char_p Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 20:23:14 2008 @@ -8,7 +8,7 @@ for cls in inspect.getmro(superclass): all_fields += getattr(cls, '_fields_', []) names = [name for name, ctype in all_fields] - rawfields = [(name, ctype._ffiletter) + rawfields = [(name, ctype._ffishape) for name, ctype in all_fields] return names, rawfields, dict(all_fields) @@ -18,7 +18,8 @@ if '_fields_' in typedict: res._names, rawfields, res._fieldtypes = names_and_fields( typedict['_fields_'], cls[0]) - res._ffistruct = _rawffi.Structure(rawfields) + res._ffistruct = _rawffi.Structure(rawfields) + res._ffishape = res._ffistruct.gettypecode() def __init__(self, *args, **kwds): if not hasattr(self, '_ffistruct'): @@ -46,6 +47,7 @@ value, self.__bases__[0]) self._ffistruct = _rawffi.Structure(rawfields) _CDataMeta.__setattr__(self, '_fields_', value) + self._ffishape = self._ffistruct.gettypecode() return _CDataMeta.__setattr__(self, name, value) @@ -70,7 +72,7 @@ """Return a _rawffi array of length 1 whose address is the same as the address of the field 'name' of self.""" address = self._buffer.fieldaddress(name) - A = _rawffi.Array(fieldtype._ffiletter) + A = _rawffi.Array(fieldtype._ffishape) return A.fromaddress(address, 1) def __setattr__(self, name, value): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Thu Jan 17 20:23:14 2008 @@ -76,7 +76,6 @@ (calcsize("%c" % (code)), code)) def test_struct_alignment(self): - py.test.skip("???") class X(Structure): _fields_ = [("x", c_char * 3)] assert alignment(X) == calcsize("s") From fijal at codespeak.net Thu Jan 17 21:08:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 21:08:27 +0100 (CET) Subject: [pypy-svn] r50729 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080117200827.0E1971684CE@codespeak.net> Author: fijal Date: Thu Jan 17 21:08:22 2008 New Revision: 50729 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Copy bits and pieces from _rawffi logic in order to present correct fields. Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 21:08:22 2008 @@ -3,14 +3,46 @@ from _ctypes.basics import _CData, _CDataMeta import inspect +def round_up(size, alignment): + return (size + alignment - 1) & -alignment + +def size_alignment_pos(fields): + import ctypes + size = 0 + alignment = 1 + pos = [] + for fieldname, ctype in fields: + letter = ctype._ffiletter + fieldsize = ctypes.sizeof(ctype) + fieldalignment = ctypes.alignment(ctype) + size = round_up(size, fieldalignment) + alignment = max(alignment, fieldalignment) + pos.append(size) + size += fieldsize + size = round_up(size, alignment) + return size, alignment, pos + def names_and_fields(_fields_, superclass): + import ctypes all_fields = _fields_[:] for cls in inspect.getmro(superclass): all_fields += getattr(cls, '_fields_', []) names = [name for name, ctype in all_fields] rawfields = [(name, ctype._ffishape) for name, ctype in all_fields] - return names, rawfields, dict(all_fields) + _, _, pos = size_alignment_pos(all_fields) + fields = {} + for i, (name, ctype) in enumerate(all_fields): + fields[name] = Field(name, pos[i], ctypes.sizeof(ctype), ctype) + return names, rawfields, fields + +class Field(object): + def __init__(self, name, offset, size, ctype): + for k in ('name', 'offset', 'size', 'ctype'): + self.__dict__[k] = locals()[k] + + def __setattr__(self, name, value): + raise AttributeError(name) class StructureMeta(_CDataMeta): def __new__(self, name, cls, typedict): @@ -51,6 +83,12 @@ return _CDataMeta.__setattr__(self, name, value) + def __getattr__(self, name): + if hasattr(self, '_fieldtypes') and name in self._fieldtypes: + return self._fieldtypes[name] + return _CDataMeta.__getattr__(self, name) + #return Field(name, + def from_address(self, address): instance = self.__new__(self) instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) @@ -77,7 +115,7 @@ def __setattr__(self, name, value): try: - fieldtype = self._fieldtypes[name] + fieldtype = self._fieldtypes[name].ctype except KeyError: raise AttributeError(name) value = fieldtype._CData_input(value) @@ -85,7 +123,7 @@ def __getattr__(self, name): try: - fieldtype = self._fieldtypes[name] + fieldtype = self._fieldtypes[name].ctype except KeyError: raise AttributeError(name) return fieldtype._CData_output(self._subarray(fieldtype, name)) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Thu Jan 17 21:08:22 2008 @@ -129,7 +129,6 @@ assert sizeof(XX) == 0 def test_fields(self): - py.test.skip("???") # test the offset and size attributes of Structure/Unoin fields. class X(Structure): _fields_ = [("x", c_int), @@ -145,6 +144,7 @@ raises((TypeError, AttributeError), setattr, X.x, "offset", 92) raises((TypeError, AttributeError), setattr, X.x, "size", 92) + py.test.skip("No unions support") class X(Union): _fields_ = [("x", c_int), ("y", c_char)] From exarkun at codespeak.net Thu Jan 17 21:50:09 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 21:50:09 +0100 (CET) Subject: [pypy-svn] r50730 - pypy/build/buildbot Message-ID: <20080117205009.A8DD81684D8@codespeak.net> Author: exarkun Date: Thu Jan 17 21:50:08 2008 New Revision: 50730 Modified: pypy/build/buildbot/pypybuilders.py Log: hack up the trial command so it works on windows too Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Thu Jan 17 21:50:08 2008 @@ -118,15 +118,16 @@ self.addStep( SVN, - workdir="build/twisted-src", + workdir="build/Twisted-src", svnurl="svn://svn.twistedmatrix.com/svn/Twisted/trunk", mode="copy") self.addStep( Trial, - workdir="build/twisted-src", - python=["../pypy-src/pypy/translator/goal/pypy-c", + workdir="build/pypy-src/pypy/translator/goal", + python=["pypy-c", "--oldstyle"], testpath=None, - trial="bin/trial", - tests=["twisted"]) + trial="../../../../Twisted-src/bin/trial", + tests=["twisted.test.test_memcache"], + env={"PATH": "."}) From exarkun at codespeak.net Thu Jan 17 21:50:22 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 21:50:22 +0100 (CET) Subject: [pypy-svn] r50731 - pypy/build/buildbot Message-ID: <20080117205022.1BD8A1684DF@codespeak.net> Author: exarkun Date: Thu Jan 17 21:50:22 2008 New Revision: 50731 Modified: pypy/build/buildbot/master.cfg Log: --allworkingmodules on windows Modified: pypy/build/buildbot/master.cfg ============================================================================== --- pypy/build/buildbot/master.cfg (original) +++ pypy/build/buildbot/master.cfg Thu Jan 17 21:50:22 2008 @@ -65,7 +65,7 @@ "builddir": "pypy-c-allworkingmodules-faassen-winxp32", "factory": PyPyBuildFactory([], [], - [])}, + ["--allworkingmodules"])}, ], 'buildbotURL': 'http://office.divmod.com:%d/' % (httpPortNumber,), From fijal at codespeak.net Thu Jan 17 21:57:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 21:57:09 +0100 (CET) Subject: [pypy-svn] r50732 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080117205709.5AC211684BF@codespeak.net> Author: fijal Date: Thu Jan 17 21:57:08 2008 New Revision: 50732 Modified: pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/_ctypes/function.py pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/_ctypes/structure.py Log: Few minor things. I hope to find tests for these features one day... (rewritten from C) Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Thu Jan 17 21:57:08 2008 @@ -45,6 +45,14 @@ def _alignmentofinstances(self): return self._type_._alignmentofinstances() + def from_param(self, value): + # check for iterable + if hasattr(value, '__iter__'): + if len(value) > self._length_: + raise ValueError("%s too long" % (value,)) + return self(*value) + return _CDataMeta.from_param(self, value) + class Array(_CData): __metaclass__ = ArrayMeta _ffiletter = 'P' Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Thu Jan 17 21:57:08 2008 @@ -1,10 +1,16 @@ import types from _ctypes.basics import _CData, _CDataMeta +import _rawffi class CFuncPtrType(_CDataMeta): # XXX write down here defaults and such things - pass + + def _sizeofinstances(self): + return _rawffi.sizeof('P') + + def _alignmentofinstances(self): + return _rawffi.alignment('P') class CFuncPtr(_CData): __metaclass__ = CFuncPtrType @@ -12,7 +18,7 @@ _argtypes_ = None _restype_ = None _ffiletter = 'P' - _buffer = 0 + _ffishape = 'P' def _getargtypes(self): return self._argtypes_ @@ -31,6 +37,8 @@ self.name, self.dll = address_or_name_and_dll else: self.address = address_or_name_and_dll + if isinstance(self.address, int): + self._buffer = _rawffi.Array('P').fromaddress(self.address, 1) self.name = None def __call__(self, *args): Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Thu Jan 17 21:57:08 2008 @@ -21,16 +21,11 @@ for k, v in d.iteritems(): setattr(obj, k, v) if '_type_' in typedict: - ffiarray = _rawffi.Array('P') - def __init__(self, value=None): - self._buffer = ffiarray(1) - if value is not None: - self.contents = value - obj._ffiarray = ffiarray + self.set_type(obj, typedict['_type_']) else: def __init__(self, value=None): raise TypeError("%s has no type" % obj) - obj.__init__ = __init__ + obj.__init__ = __init__ return obj def from_param(self, value): @@ -56,7 +51,14 @@ return True def set_type(self, TP): - pass # XXX??? + ffiarray = _rawffi.Array('P') + def __init__(self, value=None): + self._buffer = ffiarray(1) + if value is not None: + self.contents = value + self._ffiarray = ffiarray + self.__init__ = __init__ + self._type_ = TP from_address = cdata_from_address Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 21:57:08 2008 @@ -44,6 +44,10 @@ def __setattr__(self, name, value): raise AttributeError(name) + def __repr__(self): + return "" % (self.name, self.offset, + self.size) + class StructureMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) From exarkun at codespeak.net Thu Jan 17 21:57:59 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 21:57:59 +0100 (CET) Subject: [pypy-svn] r50733 - pypy/build/buildbot Message-ID: <20080117205759.C29721684BF@codespeak.net> Author: exarkun Date: Thu Jan 17 21:57:59 2008 New Revision: 50733 Modified: pypy/build/buildbot/pypy_status.py Log: trivial visual improvements * something one might mistake for part of a legend * better ordering of build results (I guess) Modified: pypy/build/buildbot/pypy_status.py ============================================================================== --- pypy/build/buildbot/pypy_status.py (original) +++ pypy/build/buildbot/pypy_status.py Thu Jan 17 21:57:59 2008 @@ -25,6 +25,8 @@ builderNames = status.getBuilderNames() failedTests = {} + buildNumbers = range(self.oldBuildCount - 1, -1, -1) + for name in builderNames: recentFailures = Set() builder = status.getBuilder(name) @@ -57,21 +59,30 @@ testName, tags.span(style="background-color: cyan;")['?']) - table = tags.table() + testResultsTable = tags.table() heading = tags.tr() - for buildNumber in range(self.oldBuildCount): + for buildNumber in buildNumbers: heading[tags.td()[buildNumber]] - table[heading] + heading[tags.td()["<- How many builds ago"]] + testResultsTable[heading] for testName in recentFailures: row = tags.tr() - for buildNumber in range(self.oldBuildCount): + for buildNumber in buildNumbers: result = [] for builderName in builderNames: key = (builderName, buildNumber, testName) result.append(failedTests[key]) row[tags.td()[result]] row[tags.td()[testName]] - table[row] + testResultsTable[row] - return flatten(table) + legend = tags.div[ + tags.div()["P - Passed"], + tags.div()["F - Failed"], + tags.div()["S - Skipped"], + tags.div()["? - No result available"]] + + return flatten(tags.div()[ + legend, + testResultsTable]) From exarkun at codespeak.net Thu Jan 17 22:36:04 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 22:36:04 +0100 (CET) Subject: [pypy-svn] r50734 - pypy/build/buildbot Message-ID: <20080117213604.823451684CB@codespeak.net> Author: exarkun Date: Thu Jan 17 22:36:03 2008 New Revision: 50734 Modified: pypy/build/buildbot/pypybuilders.py Log: run the whole twisted test suite, not just the memcache tests Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Thu Jan 17 22:36:03 2008 @@ -129,5 +129,5 @@ "--oldstyle"], testpath=None, trial="../../../../Twisted-src/bin/trial", - tests=["twisted.test.test_memcache"], + tests=["twisted"], env={"PATH": "."}) From fijal at codespeak.net Thu Jan 17 22:59:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 22:59:28 +0100 (CET) Subject: [pypy-svn] r50735 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080117215928.37BCB1684CE@codespeak.net> Author: fijal Date: Thu Jan 17 22:59:27 2008 New Revision: 50735 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Complain louder, test passes Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 22:59:27 2008 @@ -23,6 +23,9 @@ return size, alignment, pos def names_and_fields(_fields_, superclass): + for _, tp in _fields_: + if not isinstance(tp, _CDataMeta): + raise TypeError("Expected CData subclass, got %s" % (tp,)) import ctypes all_fields = _fields_[:] for cls in inspect.getmro(superclass): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Thu Jan 17 22:59:27 2008 @@ -205,7 +205,7 @@ raises(ValueError, type(Structure), "X", (Structure,), d) def test_initializers(self): - py.test.skip("???") + py.test.skip("unsupported") class Person(Structure): _fields_ = [("name", c_char*6), ("age", c_int)] @@ -232,7 +232,6 @@ assert (pt.x, pt.y) == (1, 2) def test_invalid_field_types(self): - py.test.skip("???") class POINT(Structure): pass raises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)]) From exarkun at codespeak.net Thu Jan 17 22:59:29 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 17 Jan 2008 22:59:29 +0100 (CET) Subject: [pypy-svn] r50736 - pypy/build/buildbot Message-ID: <20080117215929.9B8011684D7@codespeak.net> Author: exarkun Date: Thu Jan 17 22:59:28 2008 New Revision: 50736 Modified: pypy/build/buildbot/pypybuilders.py Log: run py.test -A with pypy-c after translation Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Thu Jan 17 22:59:28 2008 @@ -27,14 +27,26 @@ name = "py.test pypy" description = ["PyPy", "Tests"] - command = ["find", "-name", "test", "-type", "d", "-exec", "python", "py/bin/py.test", "--session=MySession", "{}", ";"] + PYTHON_EXECUTABLE = object() + TEST_PACKAGE = object() + TEST_ARGUMENTS = object() + + command = [ + "find", TEST_PACKAGE, "-name", "test", "-type", "d", "-exec", + PYTHON_EXECUTABLE, + "py/bin/py.test", "--session=MySession", TEST_ARGUMENTS, "{}", ";"] + haltOnFailure = False - def __init__(self, testPackage, testArguments, workdir="build/pypy-src", *a, **kw): + def __init__(self, testPackage, testArguments, workdir="build/pypy-src", + python="python", *a, **kw): ShellCommand.__init__(self, workdir, *a, **kw) self.command = list(self.command) - self.command[1:1] = [testPackage] - self.command[-2:-2] = testArguments + for (marker, replacement) in [(self.PYTHON_EXECUTABLE, [python]), + (self.TEST_PACKAGE, [testPackage]), + (self.TEST_ARGUMENTS, testArguments)]: + index = self.command.index(marker) + self.command[index:index + 1] = replacement def createSummary(self, log): @@ -112,6 +124,14 @@ translationArgs=translationArguments, targetArgs=targetArguments) + if pytestArguments is not None: + self.addStep( + PyTest, + python="pypy/translator/goal/pypy-c", + testPackage="pypy", + testArguments=["-A"] + pytestArguments, + timeout=60 * 60) + # self.addStep(FileUpload, # slavesrc="pypy-src/pypy/translator/goal/pypy-c", # masterdest="pypy-c") From antocuni at codespeak.net Thu Jan 17 23:07:48 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 17 Jan 2008 23:07:48 +0100 (CET) Subject: [pypy-svn] r50737 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080117220748.18B341684CB@codespeak.net> Author: antocuni Date: Thu Jan 17 23:07:47 2008 New Revision: 50737 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Log: store the info about namespaces and generics in a global object inside interp_clr.py, which app_importer queries when needed. Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Thu Jan 17 23:07:47 2008 @@ -14,10 +14,8 @@ '_CliObject_internal': 'interp_clr.W_CliObject', 'call_staticmethod': 'interp_clr.call_staticmethod', 'load_cli_class': 'interp_clr.load_cli_class', - 'get_extra_type_info': 'interp_clr.get_extra_type_info', + 'get_assemblies_info': 'interp_clr.get_assemblies_info', 'isDotNetType': 'interp_clr.isDotNetType', - #'load_assembly': 'interp_clr.load_assembly', - #'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies', } def startup(self, space): Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Thu Jan 17 23:07:47 2008 @@ -19,25 +19,16 @@ When importer.find_module("spam.eggs.ham") is called, "spam.eggs" has already been imported and added to sys.modules. ''' - def __init__(self): - self.valid_namespaces = None - self.generic_mappings = None def find_module(self, fullname, path=None): import clr - if self.valid_namespaces is None: - # this might not be the correct place to load the valid NameSpaces - valid_namespaces, generic_mappings = clr.get_extra_type_info() - self.valid_namespaces = set(valid_namespaces) - self.generic_mappings = dict(generic_mappings) - - if fullname in self.valid_namespaces or fullname in self.generic_mappings or clr.isDotNetType(fullname): - # fullname is a .Net Module - return self + namespaces, generic_map = clr.get_assemblies_info() + + if fullname in namespaces or fullname in generic_map or clr.isDotNetType(fullname): + return self # fullname is a .NET Module else: - # fullname is not a .Net Module - return None - + return None # fullname is not a .NET Module + def load_module(self, fullname): ''' The load_module() must fulfill the following *before* it runs any code: @@ -63,11 +54,13 @@ ''' # If it is a call for a Class then return with the Class reference import clr - if clr.isDotNetType(fullname) or fullname in self.generic_mappings: + namespaces, generic_map = clr.get_assemblies_info() + + if clr.isDotNetType(fullname) or fullname in generic_map: ''' Task is to breakup System.Collections.ArrayList and call clr.load_cli_class('System.Collections','ArrayList') ''' - fullname = self.generic_mappings.get(fullname, fullname) + fullname = generic_map.get(fullname, fullname) rindex = fullname.rfind('.') if rindex != -1: leftStr = fullname[:rindex] @@ -86,15 +79,6 @@ # if it is a PACKAGE then we are to initialize the __path__ for the module # we won't deal with Packages here - - - # treating System.Collections.Generic specially here. - # this treatment is done after the empty module insertion - #if fullname == "System.Collections.Generic": - # genericClassList = clr.list_of_generic_classes() - # for genericClass in genericClassList: - # sys.modules[genericClass[: genericClass.find('`')]] = clr.load_cli_class("System.Collections.Generic", genericClass) - return sys.modules[fullname] class CLRModule(types.ModuleType): Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Thu Jan 17 23:07:47 2008 @@ -193,43 +193,50 @@ return self.cache.get(fullname, None) CliClassCache = _CliClassCache() -def get_extra_type_info(space): - """ - We use this function to play with reflection - and then return useful data to the app_importer module - - Parameters: - - Return: List of Valid .NET namespaces - """ - namespaces = {} - generics = [] - currentDomain = System.AppDomain.get_CurrentDomain() - assems = currentDomain.GetAssemblies() - for i in range(len(assems)): - loadedAssembly = assems[i] - typesInAssembly = loadedAssembly.GetTypes() - for i in range(len(typesInAssembly)): - ttype = typesInAssembly[i] - namespace = ttype.get_Namespace() - if namespace is not None: - chunks = namespace.split(".") - temp_name = chunks[0] - namespaces[temp_name] = None - for chunk in chunks[1:]: - temp_name += "."+chunk - namespaces[temp_name] = None - if ttype.get_IsGenericType(): - fullname = ttype.get_FullName() - if '+' not in fullname: - # else it's a nested type, ignore it - index = fullname.rfind("`") - assert index >= 0 - generics.append((fullname[0:index], fullname)) - w_listOfNamespaces = wrap_list_of_strings(space, namespaces.keys()) - w_generic_mappings = wrap_list_of_pairs(space, generics) - return space.newtuple([w_listOfNamespaces, w_generic_mappings]) -get_extra_type_info.unwrap_spec = [ObjSpace] +class _AssembliesInfo: + w_namespaces = None + w_generic_map = None + w_info = None # a tuple containing (w_namespaces, w_generic_map) +AssembliesInfo = _AssembliesInfo() + +def save_info_for_assembly(space, b_assembly): + info = AssembliesInfo + b_types = b_assembly.GetTypes() + for i in range(len(b_types)): + b_type = b_types[i] + namespace = b_type.get_Namespace() + if namespace is not None: + # builds all possible sub-namespaces + # (e.g. 'System', 'System.Windows', 'System.Windows.Forms') + chunks = namespace.split(".") + temp_name = chunks[0] + space.setitem(info.w_namespaces, space.wrap(temp_name), space.w_None) + for chunk in chunks[1:]: + temp_name += "."+chunk + space.setitem(info.w_namespaces, space.wrap(temp_name), space.w_None) + if b_type.get_IsGenericType(): + fullname = b_type.get_FullName() + if '+' not in fullname: + index = fullname.rfind("`") + assert index >= 0 + pyName = fullname[0:index] + space.setitem(info.w_generic_map, space.wrap(pyName), space.wrap(fullname)) + +def save_info_for_all_assemblies(space): + b_currentDomain = System.AppDomain.get_CurrentDomain() + b_assems = b_currentDomain.GetAssemblies() + for i in range(len(b_assems)): + save_info_for_assembly(space, b_assems[i]) + +def get_assemblies_info(space): + info = AssembliesInfo + if info.w_info is None: + info.w_namespaces = space.newdict() + info.w_generic_map = space.newdict() + info.w_info = space.newtuple([info.w_namespaces, info.w_generic_map]) + save_info_for_all_assemblies(space) # cache info for all standard assemblies + return info.w_info +get_assemblies_info.unwrap_spec = [ObjSpace] def isDotNetType(space, nameFromImporter): """ @@ -241,57 +248,6 @@ return space.wrap(System.Type.GetType(nameFromImporter) is not None) isDotNetType.unwrap_spec = [ObjSpace, str] -##def list_of_loadedAssemblies(space): -## """ -## return a List of currently loaded .NET assembliesy - -## return: -## list eg: ['System.Xml','System.Data','mscorlib'] -## """ -## loadedAssemblies = [] -## currentDomain = System.AppDomain.get_CurrentDomain() -## currentLoadedAssemblies = currentDomain.GetAssemblies() - -## for i in range(len(currentLoadedAssemblies)): -## lAssembly = currentLoadedAssemblies[i] -## strName = lAssembly.get_FullName() -## rindexComma = strName.find(',') -## if rindexComma != -1: -## loadedAssemblies.append(strName[:rindexComma]) -## return space.wrap(loadedAssemblies) -##list_of_loadedAssemblies.unwrap_spec = [ObjSpace] - -##def load_assembly(space, assemblyPath): -## """ -## Load the given .NET assembly into the PyPy interpreter - -## Parameters: - -## - assemblyPath: the full path of the assembly -## (e.g., /usr/lib/mono/2.0/System.Data.dll). -## """ -## assemblyToLoad = "" -## loadedAssemblies = space.unwrap(list_of_loadedAssemblies(space)) - -## # split the name to pull out "System.Data.dll" -## # then check if it has already been loaded. -## rindexSlash = assemblyPath.rfind('/') -## if rindexSlash != -1: -## strAfterSlash = assemblyPath[rindexSlash +1 : ] -## rindexDot = strAfterSlash.rfind('.') -## if rindexDot != -1: -## assemblyToLoad = strAfterSlash[: rindexDot] - -## if assemblyToLoad in loadedAssemblies: -## print " won't reload loaded assembly " -## pass -## else: -## try: -## System.Reflection.Assembly.LoadFile(assemblyPath) -## print "Loaded %s"%assemblyPath -## except: -## print " can not load the assembly " -##load_assembly.unwrap_spec = [ObjSpace, str] def load_cli_class(space, namespace, classname): """ Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Thu Jan 17 23:07:47 2008 @@ -7,7 +7,7 @@ def test_list_of_valid_namespaces(self): import clr - ns, gen = clr.get_extra_type_info() + ns, gen = clr.get_assemblies_info() assert 'System' in ns assert 'System.Collections' in ns From fijal at codespeak.net Thu Jan 17 23:11:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 23:11:02 +0100 (CET) Subject: [pypy-svn] r50738 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080117221102.EB9A71684CB@codespeak.net> Author: fijal Date: Thu Jan 17 23:11:02 2008 New Revision: 50738 Modified: pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Small tweak and another test passes Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Thu Jan 17 23:11:02 2008 @@ -30,7 +30,7 @@ def from_param(self, value): if value is None: - return 0 + return self(None) # If we expect POINTER(), but receive a instance, accept # it by calling byref(). if isinstance(value, self._type_): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Thu Jan 17 23:11:02 2008 @@ -237,7 +237,7 @@ raises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)]) def test_intarray_fields(self): - py.test.skip("???") + py.test.skip("unsupported") class SomeInts(Structure): _fields_ = [("a", c_int * 4)] @@ -383,7 +383,6 @@ assert items == [1, 2, 3] def test_none_to_pointer_fields(self): - py.test.skip("???") class S(Structure): _fields_ = [("x", c_int), ("p", POINTER(c_int))] From fijal at codespeak.net Thu Jan 17 23:12:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 23:12:57 +0100 (CET) Subject: [pypy-svn] r50739 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080117221257.11C9A1684CB@codespeak.net> Author: fijal Date: Thu Jan 17 23:12:56 2008 New Revision: 50739 Modified: pypy/dist/pypy/lib/_ctypes/structure.py Log: "typo" Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 23:12:56 2008 @@ -93,7 +93,7 @@ def __getattr__(self, name): if hasattr(self, '_fieldtypes') and name in self._fieldtypes: return self._fieldtypes[name] - return _CDataMeta.__getattr__(self, name) + return _CDataMeta.__getattribute__(self, name) #return Field(name, def from_address(self, address): From fijal at codespeak.net Thu Jan 17 23:17:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 17 Jan 2008 23:17:39 +0100 (CET) Subject: [pypy-svn] r50740 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080117221739.B5D881684CA@codespeak.net> Author: fijal Date: Thu Jan 17 23:17:39 2008 New Revision: 50740 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Another explicit AttributeError Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 17 23:17:39 2008 @@ -82,6 +82,8 @@ if name == '_fields_': if self.__dict__.get('_fields_', None): raise AttributeError("_fields_ is final") + if self in [v for k, v in value]: + raise AttributeError("Structure or union cannot contain itself") self._names, rawfields, self._fieldtypes = names_and_fields( value, self.__bases__[0]) self._ffistruct = _rawffi.Structure(rawfields) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Thu Jan 17 23:17:39 2008 @@ -394,7 +394,6 @@ class TestRecursiveStructure: def test_contains_itself(self): - py.test.skip("???") class Recursive(Structure): pass From cfbolz at codespeak.net Fri Jan 18 11:05:01 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 18 Jan 2008 11:05:01 +0100 (CET) Subject: [pypy-svn] r50742 - pypy/extradoc/sprintinfo/leysin-winter-2008 Message-ID: <20080118100501.3EEAC16840C@codespeak.net> Author: cfbolz Date: Fri Jan 18 11:04:59 2008 New Revision: 50742 Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Log: (all): planning for today Modified: pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2008/planning.txt Fri Jan 18 11:04:59 2008 @@ -2,6 +2,8 @@ Task ideas ========== + - skiing/snowboarding/snow hiking: IN-PROGRESS + - try getting debug information in the Java class files DONE - benchmark the size of the young nursery for generational GC @@ -13,21 +15,37 @@ - work on CTypes more general non-progress - nested structure and arrays of structure support in rawffi + nested structure and arrays of structure support in rawffi DONE + + - callbacks in rawffi + + - write tests for GIL handling in callbacks in rffi (maciek) - think about summarizing test outcomes - JVM integration (probably only when Anto is here) + - does JPype support reflection? (Paul, Anto around) + wrap it into an rlib module + - look at the CLI integration on the clr-module-improvements/ branch and - maybe improve/merge it? DONE, branch is to be merged + maybe improve/merge it? Some problems left: newly loaded assemblies are a + problem - implement fixed-size lists as arrays in the ootypesystem (Carl Friedrich, Toby) IN PROGRESS, jvm backend supported, more minor problems java bytecode verifier complains - - give a JIT code walkthrough (Armin) + - give a JIT code walkthrough DONE + + - give a JIT promotion walkthrough (Armin) - - start writing more unit-style tests for the JIT (Armin, Anto, Maciek) + - start writing more unit-style tests for the JIT (Armin, Carl Friedrich, + Anto) + SOME PROGRESS + + - ported some JIT tests to ootype - - explore the parsers a bit (Toby, Carl Friedrich) + - explore the parsers a bit DONE + + - hack a bit on an AVM backend (Toby, Maciek) From arigo at codespeak.net Fri Jan 18 11:36:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 11:36:47 +0100 (CET) Subject: [pypy-svn] r50743 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080118103647.A50EF168509@codespeak.net> Author: arigo Date: Fri Jan 18 11:36:46 2008 New Revision: 50743 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: (fijal, arigo) Attempt to fix the callbacks GIL handling. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Fri Jan 18 11:36:46 2008 @@ -1,4 +1,4 @@ - +import py from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem import ll2ctypes @@ -168,20 +168,31 @@ else: before = None after = None - def wrapper(*args): - try: - if before: - before() - result = callable(*args) + args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) + source = py.code.Source(r""" + def wrapper(%s): # no *args - no GIL for mallocing the tuple if after: after() + # from now on we hold the GIL + try: + result = callable(%s) + except Exception, e: + os.write(2, + "Warning: uncaught exception in callback: %%s %%s\n" %% + (str(callable), str(e))) + result = errorcode + if before: + before() + # here we don't hold the GIL any more. As in the wrapper() produced + # by llexternal, it is essential that no exception checking occurs + # after the call to before(). return result - except Exception, e: - if after: - after() - os.write(2, "Warning: uncaught exception in callback: %s %s\n" % (str(callable), str(e))) - return errorcode - return wrapper + """ % (args, args)) + miniglobals = locals().copy() + miniglobals['Exception'] = Exception + miniglobals['os'] = os + exec source.compile() in miniglobals + return miniglobals['wrapper'] _make_wrapper_for._annspecialcase_ = 'specialize:memo' AroundFnPtr = lltype.Ptr(lltype.FuncType([], lltype.Void)) From fijal at codespeak.net Fri Jan 18 11:43:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jan 2008 11:43:29 +0100 (CET) Subject: [pypy-svn] r50744 - pypy/dist/pypy/tool Message-ID: <20080118104329.E3AFF16857D@codespeak.net> Author: fijal Date: Fri Jan 18 11:43:29 2008 New Revision: 50744 Modified: pypy/dist/pypy/tool/slaveproc.py Log: Try hard to obey the cpython deletion order and not to complain at the end of tests. Modified: pypy/dist/pypy/tool/slaveproc.py ============================================================================== --- pypy/dist/pypy/tool/slaveproc.py (original) +++ pypy/dist/pypy/tool/slaveproc.py Fri Jan 18 11:43:29 2008 @@ -6,12 +6,16 @@ self.inp = inp def send(self, data): + if marshal is None: + return s = marshal.dumps(data) h = struct.pack('L', len(s)) self.out.write(h+s) self.out.flush() def recv(self): + if not struct: + return 'done' HSIZE = struct.calcsize('L') h = self.inp.read(HSIZE) if len(h) < HSIZE: From arigo at codespeak.net Fri Jan 18 12:10:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 12:10:20 +0100 (CET) Subject: [pypy-svn] r50745 - pypy/dist/pypy/translator/goal Message-ID: <20080118111020.574B0169E1A@codespeak.net> Author: arigo Date: Fri Jan 18 12:10:19 2008 New Revision: 50745 Modified: pypy/dist/pypy/translator/goal/timing.py Log: Print "---" instead of "-" in order to avoid confusion. It looked too much like negative times. Modified: pypy/dist/pypy/translator/goal/timing.py ============================================================================== --- pypy/dist/pypy/translator/goal/timing.py (original) +++ pypy/dist/pypy/translator/goal/timing.py Fri Jan 18 12:10:19 2008 @@ -37,11 +37,11 @@ """ Pretty print """ spacing = " "*(30 - len("Total:")) - total = "Total:%s - %.1f s" % (spacing, self.ttime()) + total = "Total:%s --- %.1f s" % (spacing, self.ttime()) log.bold("Timings:") for event, time in self.events: spacing = " "*(30 - len(event)) - first = "%s%s - " % (event, spacing) + first = "%s%s --- " % (event, spacing) second = "%.1f s" % (time,) additional_spaces = " " * (len(total) - len(first) - len(second)) log.bold("%s%s%s" % (first, additional_spaces, second)) From fijal at codespeak.net Fri Jan 18 12:37:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jan 2008 12:37:50 +0100 (CET) Subject: [pypy-svn] r50746 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080118113750.DDC4D169E24@codespeak.net> Author: fijal Date: Fri Jan 18 12:37:49 2008 New Revision: 50746 Modified: pypy/dist/pypy/lib/_ctypes/function.py Log: A bit more magic for non-specified arguments. Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Fri Jan 18 12:37:49 2008 @@ -29,6 +29,8 @@ def _getrestype(self): return self._restype_ def _setrestype(self, restype): + if not isinstance(restype, _CDataMeta) and not restype is None: + raise TypeError("Expected ctypes type, got %s" % (restype,)) self._restype_ = restype restype = property(_getrestype, _setrestype) @@ -66,10 +68,17 @@ def _guess_argtypes(self, args): from _ctypes import _CData + from ctypes import c_char_p, c_void_p res = [] for arg in args: - assert isinstance(arg, _CData) - res.append(type(arg)) + if isinstance(arg, str): + res.append(c_char_p) + elif isinstance(arg, _CData): + res.append(type(arg)) + elif arg is None: + res.append(c_void_p) + else: + raise TypeError("Dont know how to handle %s" % (arg,)) return res def _wrap_args(self, argtypes, args): From fijal at codespeak.net Fri Jan 18 12:38:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 18 Jan 2008 12:38:36 +0100 (CET) Subject: [pypy-svn] r50747 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080118113836.2E59816846C@codespeak.net> Author: fijal Date: Fri Jan 18 12:38:35 2008 New Revision: 50747 Modified: pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py Log: (cfbolz, fijal) Automatically cast byref() results to c_void_p, when c_void_p is expected as function argument. Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Fri Jan 18 12:38:35 2008 @@ -83,12 +83,12 @@ self._buffer[0] = value result.value = property(_getvalue, _setvalue) - if tp == 'z' or tp == 'P': + if tp == 'z': from _ctypes import Array, _Pointer - # c_char_p and c_void_p + # c_char_p def from_param(self, value): if value is None: - return None + return self(None) if isinstance(value, basestring): return self(value) if isinstance(value, _SimpleCData) and \ @@ -101,6 +101,26 @@ return value return SimpleType.from_param(self, value) result.from_param = classmethod(from_param) + elif tp == 'P': + from _ctypes import Array, _Pointer + # c_void_p + def from_param(self, value): + if value is None: + return self(None) + if isinstance(value, basestring): + return self(value) + if isinstance(value, _SimpleCData) and \ + type(value)._type_ in 'zP': + return value + if isinstance(value, Array): + from ctypes import c_char, c_byte + if type(value)._type_ == c_char or \ + type(value)._type_ == c_byte: + return value + if isinstance(value, _Pointer): + return self.from_address(value._buffer.buffer) + return SimpleType.from_param(self, value) + result.from_param = classmethod(from_param) return result Modified: pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py Fri Jan 18 12:38:35 2008 @@ -235,3 +235,16 @@ py.test.raises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted py.test.raises(TypeError, c_void_p, object()) # nor other objects + + def test_c_char_p_byref(self): + dll = CDLL(_ctypes_test) + TwoOutArgs = dll.TwoOutArgs + TwoOutArgs.restype = None + TwoOutArgs.argtypes = [c_int, c_void_p, c_int, c_void_p] + a = c_int(3) + b = c_int(4) + c = c_int(5) + d = c_int(6) + TwoOutArgs(a, byref(b), c, byref(d)) + assert b.value == 7 + assert d.value == 11 From arigo at codespeak.net Fri Jan 18 14:58:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 14:58:22 +0100 (CET) Subject: [pypy-svn] r50748 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080118135822.7A588169E1B@codespeak.net> Author: arigo Date: Fri Jan 18 14:58:21 2008 New Revision: 50748 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: Fix test. 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 Fri Jan 18 14:58:21 2008 @@ -213,6 +213,11 @@ if instrname in ('MOVZX', 'MOVSX'): if args[1][1].width == 4: return [] + if instrname == "TEST": + if (args[0] != args[1] and + isinstance(args[0][1], i386.REG) and + isinstance(args[1][1], i386.REG)): + return [] # TEST reg1, reg2 <=> TEST reg2, reg1 if instrname == 'o16' or instrname.endswith('cond'): return [] return [args] From arigo at codespeak.net Fri Jan 18 15:46:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 15:46:43 +0100 (CET) Subject: [pypy-svn] r50749 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080118144643.A1EE3169E1D@codespeak.net> Author: arigo Date: Fri Jan 18 15:46:41 2008 New Revision: 50749 Added: pypy/dist/pypy/jit/timeshifter/test/support.py (contents, props changed) pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (contents, props changed) Modified: pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py Log: (cfbolz, fijal, arigo) Another test. Amazing: 6 JIT tests that run in a small fraction of a second! Added: pypy/dist/pypy/jit/timeshifter/test/support.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/timeshifter/test/support.py Fri Jan 18 15:46:41 2008 @@ -0,0 +1,74 @@ +# Fake stuff for the tests. + +from pypy.jit.codegen.model import GenVar, GenConst + + +class FakeJITState(object): + def __init__(self): + self.curbuilder = FakeBuilder() + +class FakeRGenOp(object): + def genzeroconst(self, kind): + if kind == "dummy pointer": + return FakeGenConst("NULL") + return FakeGenConst(0) + + @staticmethod + def kindToken(TYPE): + return ("kind", TYPE) + + @staticmethod + def fieldToken(TYPE, name): + return ("field", TYPE, name) + + @staticmethod + def allocToken(TYPE): + return ("alloc", TYPE) + + @staticmethod + def constPrebuiltGlobal(value): + return FakeGenConst(value) + + +class FakeBuilder(object): + ops_with_no_retval = set(['setfield']) + + def __init__(self): + self.ops = [] + self.varcount = 1 + self.rgenop = FakeRGenOp() + + def __getattr__(self, name): + if name.startswith('genop_'): + opname = name[len('genop_'):] + def genop_(*args): + if opname in self.ops_with_no_retval: + v = None + else: + v = FakeGenVar(self.varcount) + self.varcount += 1 + self.ops.append((opname, args, v)) + return v + genop_.func_name = name + return genop_ + else: + raise AttributeError, name + + +class FakeHRTyper(object): + RGenOp = FakeRGenOp + +class FakeGenVar(GenVar): + def __init__(self, count=0): + self.count=count + + def __repr__(self): + return "V%d" % self.count + + def __eq__(self, other): + return self.count == other.count + + +class FakeGenConst(GenConst): + def __init__(self, _value=None): + self._value = _value Added: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Fri Jan 18 15:46:41 2008 @@ -0,0 +1,22 @@ +from pypy.rpython.lltypesystem import lltype +from pypy.jit.timeshifter import rvalue, rcontainer +from pypy.jit.timeshifter.test.support import * + + +def test_virtualstruct_get_set_field(): + jitstate = FakeJITState() + STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) + structdesc = rcontainer.StructTypeDesc(FakeHRTyper(), STRUCT) + desc = rcontainer.StructFieldDesc(FakeHRTyper(), lltype.Ptr(STRUCT), "foo", 0) + + box = structdesc.factory() + assert box.known_nonzero + + V42 = FakeGenVar(42) + valuebox = rvalue.IntRedBox("dummy kind", V42) + box.op_setfield(jitstate, desc, valuebox) + assert jitstate.curbuilder.ops == [] + + box2 = box.op_getfield(jitstate, desc) + assert box2.genvar is V42 + assert jitstate.curbuilder.ops == [] Modified: pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rvalue.py Fri Jan 18 15:46:41 2008 @@ -2,73 +2,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.timeshifter import rvalue from pypy.jit.timeshifter import rcontainer -from pypy.jit.codegen.model import GenVar, GenConst - -class FakeJITState(object): - def __init__(self): - self.curbuilder = FakeBuilder() - -class FakeRGenOp(object): - def genzeroconst(self, kind): - if kind == "dummy pointer": - return FakeGenConst("NULL") - return FakeGenConst(0) - - @staticmethod - def kindToken(TYPE): - return TYPE - - @staticmethod - def fieldToken(TYPE, name): - return TYPE, name - - @staticmethod - def constPrebuiltGlobal(value): - return FakeGenConst(value) - - -class FakeBuilder(object): - ops_with_no_retval = set(['setfield']) - - def __init__(self): - self.ops = [] - self.varcount = 1 - self.rgenop = FakeRGenOp() - - def __getattr__(self, name): - if name.startswith('genop_'): - opname = name[len('genop_'):] - def genop_(*args): - if opname in self.ops_with_no_retval: - v = None - else: - v = FakeGenVar(self.varcount) - self.varcount += 1 - self.ops.append((opname, args, v)) - return v - genop_.func_name = name - return genop_ - else: - raise AttributeError, name - - -class FakeHRTyper(object): - RGenOp = FakeRGenOp - -class FakeGenVar(GenVar): - def __init__(self, count=0): - self.count=count - - def __repr__(self): - return "V%d" % self.count - - def __eq__(self, other): - return self.count == other.count - - -class FakeGenConst(GenConst): - def __init__(self, _value=None): - self._value = _value +from pypy.jit.timeshifter.test.support import * def test_create_int_redbox_var(): @@ -130,10 +64,10 @@ box2 = box.op_getfield(jitstate, desc) V1 = box2.genvar assert box.known_nonzero - assert jitstate.curbuilder.ops == [('getfield', ((STRUCT, 'foo'), V0), V1)] + assert jitstate.curbuilder.ops == [('getfield', (('field', STRUCT, 'foo'), V0), V1)] jitstate.curbuilder.ops = [] V42 = FakeGenVar(42) valuebox = rvalue.IntRedBox("dummy kind", V42) box.op_setfield(jitstate, desc, valuebox) - assert jitstate.curbuilder.ops == [('setfield', ((STRUCT, 'foo'), V0, V42), None)] + assert jitstate.curbuilder.ops == [('setfield', (('field', STRUCT, 'foo'), V0, V42), None)] From arigo at codespeak.net Fri Jan 18 15:57:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 15:57:04 +0100 (CET) Subject: [pypy-svn] r50750 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080118145704.C19B6169E1D@codespeak.net> Author: arigo Date: Fri Jan 18 15:57:04 2008 New Revision: 50750 Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Log: (fijal, cfbolz, arigo) Forcing test. Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Fri Jan 18 15:57:04 2008 @@ -3,20 +3,38 @@ from pypy.jit.timeshifter.test.support import * -def test_virtualstruct_get_set_field(): - jitstate = FakeJITState() - STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) - structdesc = rcontainer.StructTypeDesc(FakeHRTyper(), STRUCT) - desc = rcontainer.StructFieldDesc(FakeHRTyper(), lltype.Ptr(STRUCT), "foo", 0) - - box = structdesc.factory() - assert box.known_nonzero - - V42 = FakeGenVar(42) - valuebox = rvalue.IntRedBox("dummy kind", V42) - box.op_setfield(jitstate, desc, valuebox) - assert jitstate.curbuilder.ops == [] - - box2 = box.op_getfield(jitstate, desc) - assert box2.genvar is V42 - assert jitstate.curbuilder.ops == [] +class TestVirtualStruct: + + def make_virtual_struct(self): + jitstate = FakeJITState() + STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) + structdesc = rcontainer.StructTypeDesc(FakeHRTyper(), STRUCT) + desc = rcontainer.StructFieldDesc(FakeHRTyper(), lltype.Ptr(STRUCT), "foo", 0) + + box = structdesc.factory() + assert box.known_nonzero + + V42 = FakeGenVar(42) + valuebox = rvalue.IntRedBox("dummy kind", V42) + box.op_setfield(jitstate, desc, valuebox) + assert jitstate.curbuilder.ops == [] + self.jitstate = jitstate + self.V42 = V42 + self.STRUCT = STRUCT + self.fielddesc = desc + return box + + def test_virtualstruct_get_set_field(self): + box = self.make_virtual_struct() + jitstate = self.jitstate + box2 = box.op_getfield(jitstate, self.fielddesc) + assert box2.genvar is self.V42 + assert jitstate.curbuilder.ops == [] + + def test_virtualstruct_escape(self): + box = self.make_virtual_struct() + jitstate = self.jitstate + V1 = box.getgenvar(jitstate) # forcing + assert jitstate.curbuilder.ops == [ + ('malloc_fixedsize', (('alloc', self.STRUCT),), V1), + ('setfield', (('field', self.STRUCT, 'foo'), V1, self.V42), None)] From arigo at codespeak.net Fri Jan 18 16:39:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 16:39:43 +0100 (CET) Subject: [pypy-svn] r50753 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080118153943.0EA16169E3D@codespeak.net> Author: arigo Date: Fri Jan 18 16:39:42 2008 New Revision: 50753 Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Log: (cfbolz, arigo) Simple test about merging virtual structures. Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Fri Jan 18 16:39:42 2008 @@ -5,23 +5,25 @@ class TestVirtualStruct: + def setup_class(cls): + cls.STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) + cls.structdesc = rcontainer.StructTypeDesc(FakeHRTyper(), cls.STRUCT) + cls.fielddesc = rcontainer.StructFieldDesc(FakeHRTyper(), + lltype.Ptr(cls.STRUCT), + "foo", 0) + def make_virtual_struct(self): jitstate = FakeJITState() - STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) - structdesc = rcontainer.StructTypeDesc(FakeHRTyper(), STRUCT) - desc = rcontainer.StructFieldDesc(FakeHRTyper(), lltype.Ptr(STRUCT), "foo", 0) - box = structdesc.factory() + box = self.structdesc.factory() assert box.known_nonzero V42 = FakeGenVar(42) valuebox = rvalue.IntRedBox("dummy kind", V42) - box.op_setfield(jitstate, desc, valuebox) + box.op_setfield(jitstate, self.fielddesc, valuebox) assert jitstate.curbuilder.ops == [] self.jitstate = jitstate self.V42 = V42 - self.STRUCT = STRUCT - self.fielddesc = desc return box def test_virtualstruct_get_set_field(self): @@ -38,3 +40,22 @@ assert jitstate.curbuilder.ops == [ ('malloc_fixedsize', (('alloc', self.STRUCT),), V1), ('setfield', (('field', self.STRUCT, 'foo'), V1, self.V42), None)] + + def test_simple_merge(self): + oldbox = self.make_virtual_struct() + frozenbox = oldbox.freeze(rvalue.freeze_memo()) + outgoingvarboxes = [] + res = frozenbox.exactmatch(oldbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + fieldbox = oldbox.content.op_getfield(self.jitstate, self.fielddesc) + assert outgoingvarboxes == [fieldbox] + + newbox = self.make_virtual_struct() + constbox = rvalue.IntRedBox("dummy kind", FakeGenConst(23)) + newbox.content.op_setfield(self.jitstate, self.fielddesc, constbox) + outgoingvarboxes = [] + res = frozenbox.exactmatch(newbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + assert outgoingvarboxes == [constbox] From arigo at codespeak.net Fri Jan 18 17:35:41 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 17:35:41 +0100 (CET) Subject: [pypy-svn] r50756 - pypy/dist/pypy/rpython/test Message-ID: <20080118163541.A7717169E47@codespeak.net> Author: arigo Date: Fri Jan 18 17:35:41 2008 New Revision: 50756 Modified: pypy/dist/pypy/rpython/test/test_rclass.py Log: Fix test for the way the JS backend runs it. Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Fri Jan 18 17:35:41 2008 @@ -602,16 +602,16 @@ # Although the code below is a bit strange, there are # subtle ways in which the same situation could occur. # One is shown by test_specialize_methods(). - if n < 0: + if n < 10: x = B() else: x = A() - if n < -3: + if n < 7: return x.foo() else: return 100 - assert self.interpret(fn, [-5]) == 42 - assert self.interpret(fn, [5]) == 100 + assert self.interpret(fn, [5]) == 42 + assert self.interpret(fn, [15]) == 100 def test_specialize_methods(self): from pypy.rlib.objectmodel import specialize From arigo at codespeak.net Fri Jan 18 18:31:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 18:31:37 +0100 (CET) Subject: [pypy-svn] r50758 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080118173137.51DD1169E2D@codespeak.net> Author: arigo Date: Fri Jan 18 18:31:35 2008 New Revision: 50758 Modified: pypy/dist/pypy/jit/timeshifter/test/support.py pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Log: (antocuni, cfbolz, arigo) A test where exactmatch() returns False. Modified: pypy/dist/pypy/jit/timeshifter/test/support.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/support.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/support.py Fri Jan 18 18:31:35 2008 @@ -72,3 +72,6 @@ class FakeGenConst(GenConst): def __init__(self, _value=None): self._value = _value + + def revealconst(self, T): + return self._value Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Fri Jan 18 18:31:35 2008 @@ -44,18 +44,71 @@ def test_simple_merge(self): oldbox = self.make_virtual_struct() frozenbox = oldbox.freeze(rvalue.freeze_memo()) + # check that frozenbox matches oldbox exactly outgoingvarboxes = [] res = frozenbox.exactmatch(oldbox, outgoingvarboxes, rvalue.exactmatch_memo()) assert res fieldbox = oldbox.content.op_getfield(self.jitstate, self.fielddesc) assert outgoingvarboxes == [fieldbox] + # ^^^ the live box corresponding to the FrozenVar newbox = self.make_virtual_struct() constbox = rvalue.IntRedBox("dummy kind", FakeGenConst(23)) newbox.content.op_setfield(self.jitstate, self.fielddesc, constbox) + # check that frozenbox also matches newbox exactly outgoingvarboxes = [] res = frozenbox.exactmatch(newbox, outgoingvarboxes, rvalue.exactmatch_memo()) assert res assert outgoingvarboxes == [constbox] + # ^^^ the live box corresponding to the FrozenVar + + def test_simple_merge_generalize(self): + oldbox = self.make_virtual_struct() + oldconstbox = rvalue.IntRedBox("dummy kind", FakeGenConst(20)) + oldbox.content.op_setfield(self.jitstate, self.fielddesc, oldconstbox) + frozenbox = oldbox.freeze(rvalue.freeze_memo()) + # check that frozenbox matches oldbox exactly + outgoingvarboxes = [] + res = frozenbox.exactmatch(oldbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + assert outgoingvarboxes == [] # there is no FrozenVar + + newbox = self.make_virtual_struct() + C23 = FakeGenConst(23) + constbox = rvalue.IntRedBox("dummy kind", C23) + newbox.content.op_setfield(self.jitstate, self.fielddesc, constbox) + # non-exact match: a different constant box in the virtual struct field + outgoingvarboxes = [] + res = frozenbox.exactmatch(newbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert not res + assert outgoingvarboxes == [constbox] + # ^^^ the constbox is what should be generalized with forcevar() + # in order to get something that is at least as general as + # both oldbox and newbox + + assert self.jitstate.curbuilder.ops == [] + replace_memo = rvalue.copy_memo() + forcedbox = constbox.forcevar(self.jitstate, replace_memo, False) + assert not forcedbox.is_constant() + assert self.jitstate.curbuilder.ops == [ + ('same_as', ("dummy kind", C23), forcedbox.genvar)] + assert replace_memo.boxes == {constbox: forcedbox} + + # change constbox to forcedbox inside newbox + newbox.replace(replace_memo) + assert (newbox.content.op_getfield(self.jitstate, self.fielddesc) is + forcedbox) + + # check that now newbox really generalizes oldbox + newfrozenbox = newbox.freeze(rvalue.freeze_memo()) + outgoingvarboxes = [] + res = newfrozenbox.exactmatch(oldbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + assert outgoingvarboxes == [oldconstbox] + # ^^^ the FrozenVar() in newfrozenbox corresponds to + # oldconstbox in oldbox. From arigo at codespeak.net Fri Jan 18 19:06:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 19:06:27 +0100 (CET) Subject: [pypy-svn] r50759 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080118180627.69551169E3D@codespeak.net> Author: arigo Date: Fri Jan 18 19:06:26 2008 New Revision: 50759 Modified: pypy/dist/pypy/jit/timeshifter/test/support.py pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Log: (fijal, antocuni, arigo) Make the tests look a bit nicer, using helpers from support.py. Modified: pypy/dist/pypy/jit/timeshifter/test/support.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/support.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/support.py Fri Jan 18 19:06:26 2008 @@ -1,6 +1,8 @@ # Fake stuff for the tests. -from pypy.jit.codegen.model import GenVar, GenConst +from pypy.jit.codegen.model import GenVarOrConst, GenVar, GenConst +from pypy.rpython.lltypesystem import lltype +from pypy.jit.timeshifter import rvalue, rcontainer class FakeJITState(object): @@ -58,6 +60,8 @@ class FakeHRTyper(object): RGenOp = FakeRGenOp +fakehrtyper = FakeHRTyper() + class FakeGenVar(GenVar): def __init__(self, count=0): self.count=count @@ -75,3 +79,28 @@ def revealconst(self, T): return self._value + +# ____________________________________________________________ + +signed_kind = FakeRGenOp.kindToken(lltype.Signed) + +def vmalloc(TYPE, *boxes): + jitstate = FakeJITState() + assert isinstance(TYPE, lltype.Struct) # for now + structdesc = rcontainer.StructTypeDesc(fakehrtyper, TYPE) + box = structdesc.factory() + for fielddesc, valuebox in zip(structdesc.fielddescs, boxes): + box.op_setfield(jitstate, fielddesc, valuebox) + assert jitstate.curbuilder.ops == [] + return box + +def makebox(value): + if not isinstance(value, GenVarOrConst): + assert isinstance(value, int) # for now + value = FakeGenConst(value) + return rvalue.IntRedBox(signed_kind, value) + +def getfielddesc(STRUCT, name): + assert isinstance(STRUCT, lltype.Struct) + structdesc = rcontainer.StructTypeDesc(fakehrtyper, STRUCT) + return structdesc.fielddesc_by_name[name] Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Fri Jan 18 19:06:26 2008 @@ -1,73 +1,64 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.timeshifter import rvalue, rcontainer -from pypy.jit.timeshifter.test.support import * +from pypy.jit.timeshifter.test.support import FakeJITState, FakeGenVar +from pypy.jit.timeshifter.test.support import FakeGenConst +from pypy.jit.timeshifter.test.support import fakehrtyper, signed_kind +from pypy.jit.timeshifter.test.support import vmalloc, makebox +from pypy.jit.timeshifter.test.support import getfielddesc class TestVirtualStruct: def setup_class(cls): cls.STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) - cls.structdesc = rcontainer.StructTypeDesc(FakeHRTyper(), cls.STRUCT) - cls.fielddesc = rcontainer.StructFieldDesc(FakeHRTyper(), - lltype.Ptr(cls.STRUCT), - "foo", 0) - - def make_virtual_struct(self): - jitstate = FakeJITState() - - box = self.structdesc.factory() - assert box.known_nonzero - - V42 = FakeGenVar(42) - valuebox = rvalue.IntRedBox("dummy kind", V42) - box.op_setfield(jitstate, self.fielddesc, valuebox) - assert jitstate.curbuilder.ops == [] - self.jitstate = jitstate - self.V42 = V42 - return box + cls.fielddesc = getfielddesc(cls.STRUCT, "foo") def test_virtualstruct_get_set_field(self): - box = self.make_virtual_struct() - jitstate = self.jitstate + V42 = FakeGenVar(42) + box = vmalloc(self.STRUCT, makebox(V42)) + assert box.known_nonzero + jitstate = FakeJITState() box2 = box.op_getfield(jitstate, self.fielddesc) - assert box2.genvar is self.V42 + assert box2.genvar is V42 assert jitstate.curbuilder.ops == [] def test_virtualstruct_escape(self): - box = self.make_virtual_struct() - jitstate = self.jitstate + V42 = FakeGenVar(42) + box = vmalloc(self.STRUCT, makebox(V42)) + jitstate = FakeJITState() V1 = box.getgenvar(jitstate) # forcing assert jitstate.curbuilder.ops == [ ('malloc_fixedsize', (('alloc', self.STRUCT),), V1), - ('setfield', (('field', self.STRUCT, 'foo'), V1, self.V42), None)] + ('setfield', (('field', self.STRUCT, 'foo'), V1, V42), None)] def test_simple_merge(self): - oldbox = self.make_virtual_struct() + V42 = FakeGenVar(42) + oldbox = vmalloc(self.STRUCT, makebox(V42)) frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that frozenbox matches oldbox exactly outgoingvarboxes = [] res = frozenbox.exactmatch(oldbox, outgoingvarboxes, rvalue.exactmatch_memo()) assert res - fieldbox = oldbox.content.op_getfield(self.jitstate, self.fielddesc) + jitstate = FakeJITState() + fieldbox = oldbox.content.op_getfield(jitstate, self.fielddesc) assert outgoingvarboxes == [fieldbox] # ^^^ the live box corresponding to the FrozenVar - newbox = self.make_virtual_struct() - constbox = rvalue.IntRedBox("dummy kind", FakeGenConst(23)) - newbox.content.op_setfield(self.jitstate, self.fielddesc, constbox) + constbox23 = makebox(23) + newbox = vmalloc(self.STRUCT, constbox23) # check that frozenbox also matches newbox exactly outgoingvarboxes = [] res = frozenbox.exactmatch(newbox, outgoingvarboxes, rvalue.exactmatch_memo()) assert res - assert outgoingvarboxes == [constbox] + assert outgoingvarboxes == [constbox23] # ^^^ the live box corresponding to the FrozenVar def test_simple_merge_generalize(self): - oldbox = self.make_virtual_struct() - oldconstbox = rvalue.IntRedBox("dummy kind", FakeGenConst(20)) - oldbox.content.op_setfield(self.jitstate, self.fielddesc, oldconstbox) + S = self.STRUCT + constbox20 = makebox(20) + oldbox = vmalloc(S, constbox20) frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that frozenbox matches oldbox exactly outgoingvarboxes = [] @@ -76,31 +67,29 @@ assert res assert outgoingvarboxes == [] # there is no FrozenVar - newbox = self.make_virtual_struct() - C23 = FakeGenConst(23) - constbox = rvalue.IntRedBox("dummy kind", C23) - newbox.content.op_setfield(self.jitstate, self.fielddesc, constbox) + constbox23 = makebox(23) + newbox = vmalloc(S, constbox23) # non-exact match: a different constant box in the virtual struct field outgoingvarboxes = [] res = frozenbox.exactmatch(newbox, outgoingvarboxes, rvalue.exactmatch_memo()) assert not res - assert outgoingvarboxes == [constbox] - # ^^^ the constbox is what should be generalized with forcevar() + assert outgoingvarboxes == [constbox23] + # ^^^ constbox23 is what should be generalized with forcevar() # in order to get something that is at least as general as # both oldbox and newbox - assert self.jitstate.curbuilder.ops == [] + jitstate = FakeJITState() replace_memo = rvalue.copy_memo() - forcedbox = constbox.forcevar(self.jitstate, replace_memo, False) + forcedbox = constbox23.forcevar(jitstate, replace_memo, False) assert not forcedbox.is_constant() - assert self.jitstate.curbuilder.ops == [ - ('same_as', ("dummy kind", C23), forcedbox.genvar)] - assert replace_memo.boxes == {constbox: forcedbox} + assert jitstate.curbuilder.ops == [ + ('same_as', (signed_kind, constbox23.genvar), forcedbox.genvar)] + assert replace_memo.boxes == {constbox23: forcedbox} # change constbox to forcedbox inside newbox newbox.replace(replace_memo) - assert (newbox.content.op_getfield(self.jitstate, self.fielddesc) is + assert (newbox.content.op_getfield(jitstate, self.fielddesc) is forcedbox) # check that now newbox really generalizes oldbox @@ -109,6 +98,6 @@ res = newfrozenbox.exactmatch(oldbox, outgoingvarboxes, rvalue.exactmatch_memo()) assert res - assert outgoingvarboxes == [oldconstbox] + assert outgoingvarboxes == [constbox20] # ^^^ the FrozenVar() in newfrozenbox corresponds to - # oldconstbox in oldbox. + # constbox20 in oldbox. From arigo at codespeak.net Fri Jan 18 19:52:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 18 Jan 2008 19:52:09 +0100 (CET) Subject: [pypy-svn] r50760 - in pypy/dist/pypy: . lib/ctypes/test Message-ID: <20080118185209.5C18916841A@codespeak.net> Author: arigo Date: Fri Jan 18 19:52:08 2008 New Revision: 50760 Removed: pypy/dist/pypy/lib/ctypes/test/conftest.py Modified: pypy/dist/pypy/conftest.py Log: (fijal, arigo) Move the hack to skip lib/ctypes from py.test out of lib/ctypes itself, because if you have a non-matching ctypes version installed with CPython, the lib/ctypes/__init__.py will explode at import time. :-( Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Fri Jan 18 19:52:08 2008 @@ -470,3 +470,12 @@ import pexpect except ImportError: py.test.skip("pexpect not found") + + +class Directory(py.test.collect.Directory): + def run(self): + # hack to exclude lib/ctypes/ + if self.fspath == rootdir.join('lib', 'ctypes', 'test'): + py.test.skip("These are the original ctypes tests.\n" + "You can try to run them with 'pypy-c runtests.py'.") + return py.test.collect.Directory.run(self) From antocuni at codespeak.net Fri Jan 18 21:47:22 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Jan 2008 21:47:22 +0100 (CET) Subject: [pypy-svn] r50762 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test Message-ID: <20080118204722.96433168515@codespeak.net> Author: antocuni Date: Fri Jan 18 21:47:21 2008 New Revision: 50762 Added: pypy/branch/clr-module-improvements/pypy/module/clr/assemblyname.py (contents, props changed) Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Log: support for external assemblies Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py Fri Jan 18 21:47:21 2008 @@ -15,7 +15,7 @@ 'call_staticmethod': 'interp_clr.call_staticmethod', 'load_cli_class': 'interp_clr.load_cli_class', 'get_assemblies_info': 'interp_clr.get_assemblies_info', - 'isDotNetType': 'interp_clr.isDotNetType', + 'AddReferenceByPartialName': 'interp_clr.AddReferenceByPartialName', } def startup(self, space): Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py Fri Jan 18 21:47:21 2008 @@ -79,7 +79,8 @@ return self.fget() def _qualify(t): - return '%s, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' % t + mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' + return '%s, %s' % (t, mscorlib) class MetaGenericCliClassWrapper(type): _cli_types = { @@ -113,7 +114,7 @@ generic_params = [cls._cli_name(t) for t in types] instance_class = '%s[%s]' % (generic_class, ','.join(generic_params)) try: - return clr.load_cli_class(namespace, instance_class) + return clr.load_cli_class(cls.__assemblyname__, namespace, instance_class) except ImportError: raise TypeError, "Cannot load type %s.%s" % (namespace, instance_class) @@ -154,12 +155,14 @@ obj.__cliobj__ = cliobj return obj -def build_wrapper(namespace, classname, assembly_qualified_name, +def build_wrapper(namespace, classname, assemblyname, staticmethods, methods, properties, indexers, hasIEnumerable, isClassGeneric): fullname = '%s.%s' % (namespace, classname) + assembly_qualified_name = '%s, %s' % (fullname, assemblyname) d = {'__cliclass__': fullname, '__fullyqualifiedname__': assembly_qualified_name, + '__assemblyname__': assemblyname, '__module__': namespace} for name in staticmethods: d[name] = StaticMethodWrapper(fullname, name) Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py Fri Jan 18 21:47:21 2008 @@ -22,9 +22,9 @@ def find_module(self, fullname, path=None): import clr - namespaces, generic_map = clr.get_assemblies_info() + namespaces, classes, generics = clr.get_assemblies_info() - if fullname in namespaces or fullname in generic_map or clr.isDotNetType(fullname): + if fullname in namespaces or fullname in classes: return self # fullname is a .NET Module else: return None # fullname is not a .NET Module @@ -54,18 +54,13 @@ ''' # If it is a call for a Class then return with the Class reference import clr - namespaces, generic_map = clr.get_assemblies_info() + namespaces, classes, generics = clr.get_assemblies_info() - if clr.isDotNetType(fullname) or fullname in generic_map: - ''' Task is to breakup System.Collections.ArrayList and call - clr.load_cli_class('System.Collections','ArrayList') - ''' - fullname = generic_map.get(fullname, fullname) - rindex = fullname.rfind('.') - if rindex != -1: - leftStr = fullname[:rindex] - rightStr = fullname[rindex+1:] - sys.modules[fullname] = clr.load_cli_class(leftStr, rightStr) + if fullname in classes: + assemblyname = classes[fullname] + fullname = generics.get(fullname, fullname) + ns, classname = fullname.rsplit('.', 1) + sys.modules[fullname] = clr.load_cli_class(assemblyname, ns, classname) else: # if not a call for actual class (say for namespaces) assign an empty module if fullname not in sys.modules: mod = CLRModule(fullname) Added: pypy/branch/clr-module-improvements/pypy/module/clr/assemblyname.py ============================================================================== --- (empty file) +++ pypy/branch/clr-module-improvements/pypy/module/clr/assemblyname.py Fri Jan 18 21:47:21 2008 @@ -0,0 +1,2 @@ +mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +System = 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Fri Jan 18 21:47:21 2008 @@ -1,4 +1,5 @@ import os.path +from pypy.module.clr import assemblyname from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import interp2app, ApplevelClass @@ -8,6 +9,7 @@ new_array, init_array, typeof System = CLR.System +Assembly = CLR.System.Reflection.Assembly TargetInvocationException = NativeException(CLR.System.Reflection.TargetInvocationException) AmbiguousMatchException = NativeException(CLR.System.Reflection.AmbiguousMatchException) @@ -111,7 +113,8 @@ return space.wrap(strval) else: namespace, classname = split_fullname(b_type.ToString()) - w_cls = load_cli_class(space, namespace, classname) + assemblyname = b_type.get_Assembly().get_FullName() + w_cls = load_cli_class(space, assemblyname, namespace, classname) cliobj = W_CliObject(space, b_obj) return wrapper_from_cliobj(space, w_cls, cliobj) @@ -177,6 +180,8 @@ properties.append((b_prop.get_Name(), get_name, set_name, is_static)) else: indexers.append((b_prop.get_Name(), get_name, set_name, is_static)) + if len(indexers) > 1: + import pdb;pdb.set_trace() w_properties = wrap_list_of_tuples(space, properties) w_indexers = wrap_list_of_tuples(space, indexers) return w_properties, w_indexers @@ -195,16 +200,22 @@ class _AssembliesInfo: w_namespaces = None - w_generic_map = None - w_info = None # a tuple containing (w_namespaces, w_generic_map) + w_classes = None + w_generics = None + w_info = None # a tuple containing (w_namespaces, w_classes, w_generics) AssembliesInfo = _AssembliesInfo() def save_info_for_assembly(space, b_assembly): info = AssembliesInfo b_types = b_assembly.GetTypes() + w_assemblyName = space.wrap(b_assembly.get_FullName()) for i in range(len(b_types)): b_type = b_types[i] - namespace = b_type.get_Namespace() + namespace = str(b_type.get_Namespace()) + fullname = str(b_type.get_FullName()) + if '+' in fullname: + # it's an internal type, skip it + continue if namespace is not None: # builds all possible sub-namespaces # (e.g. 'System', 'System.Windows', 'System.Windows.Forms') @@ -215,41 +226,47 @@ temp_name += "."+chunk space.setitem(info.w_namespaces, space.wrap(temp_name), space.w_None) if b_type.get_IsGenericType(): - fullname = b_type.get_FullName() - if '+' not in fullname: - index = fullname.rfind("`") - assert index >= 0 - pyName = fullname[0:index] - space.setitem(info.w_generic_map, space.wrap(pyName), space.wrap(fullname)) + index = fullname.rfind("`") + assert index >= 0 + pyName = fullname[0:index] + space.setitem(info.w_classes, space.wrap(pyName), w_assemblyName) + space.setitem(info.w_generics, space.wrap(pyName), space.wrap(fullname)) + else: + space.setitem(info.w_classes, space.wrap(fullname), w_assemblyName) + -def save_info_for_all_assemblies(space): - b_currentDomain = System.AppDomain.get_CurrentDomain() - b_assems = b_currentDomain.GetAssemblies() - for i in range(len(b_assems)): - save_info_for_assembly(space, b_assems[i]) +def save_info_for_std_assemblies(space): + # in theory we should use Assembly.Load, but it doesn't work with + # pythonnet because it thinks it should use the Load(byte[]) overload + b_mscorlib = Assembly.LoadWithPartialName(assemblyname.mscorlib) + b_System = Assembly.LoadWithPartialName(assemblyname.System) + save_info_for_assembly(space, b_mscorlib) + save_info_for_assembly(space, b_System) def get_assemblies_info(space): info = AssembliesInfo if info.w_info is None: info.w_namespaces = space.newdict() - info.w_generic_map = space.newdict() - info.w_info = space.newtuple([info.w_namespaces, info.w_generic_map]) - save_info_for_all_assemblies(space) # cache info for all standard assemblies + info.w_classes = space.newdict() + info.w_generics = space.newdict() + info.w_info = space.newtuple([info.w_namespaces, info.w_classes, info.w_generics]) + save_info_for_std_assemblies(space) return info.w_info get_assemblies_info.unwrap_spec = [ObjSpace] -def isDotNetType(space, nameFromImporter): - """ - determines if the string input is a DotNetType +#_______________________________________________________________________________ +# AddReference* methods - Return: - Boolean - """ - return space.wrap(System.Type.GetType(nameFromImporter) is not None) -isDotNetType.unwrap_spec = [ObjSpace, str] +# AddReference', 'AddReferenceByName', 'AddReferenceByPartialName', 'AddReferenceToFile', 'AddReferenceToFileAndPath' + +def AddReferenceByPartialName(space, name): + b_assembly = Assembly.LoadWithPartialName(name) + if b_assembly is not None: + save_info_for_assembly(space, b_assembly) +AddReferenceByPartialName.unwrap_spec = [ObjSpace, str] -def load_cli_class(space, namespace, classname): +def load_cli_class(space, assemblyname, namespace, classname): """ Load the given .NET class into the PyPy interpreter and return a Python class referencing to it. @@ -264,13 +281,14 @@ fullname = '%s.%s' % (namespace, classname) w_cls = CliClassCache.get(fullname) if w_cls is None: - w_cls = build_cli_class(space, namespace, classname, fullname) + w_cls = build_cli_class(space, namespace, classname, fullname, assemblyname) CliClassCache.put(fullname, w_cls) return w_cls -load_cli_class.unwrap_spec = [ObjSpace, str, str] +load_cli_class.unwrap_spec = [ObjSpace, str, str, str] -def build_cli_class(space, namespace, classname, fullname): - b_type = System.Type.GetType(fullname) +def build_cli_class(space, namespace, classname, fullname, assemblyname): + assembly_qualified_name = '%s, %s' % (fullname, assemblyname) + b_type = System.Type.GetType(assembly_qualified_name) if b_type is None: raise OperationError(space.w_ImportError, space.wrap("Cannot load .NET type: %s" % fullname)) @@ -278,19 +296,18 @@ # set the flag hasIEnumerable if IEnumerable interface has been by the class hasIEnumerable = b_type.GetInterface("System.Collections.IEnumerable") is not None - # this is where we test if the class is Generic + # this is where we test if the class is Generic # set the flag isClassGeneric isClassGeneric = False if b_type.get_IsGenericType(): isClassGeneric = True - assembly_qualified_name = b_type.get_AssemblyQualifiedName() w_staticmethods, w_methods = get_methods(space, b_type) w_properties, w_indexers = get_properties(space, b_type) return build_wrapper(space, space.wrap(namespace), space.wrap(classname), - space.wrap(assembly_qualified_name), + space.wrap(assemblyname), w_staticmethods, w_methods, w_properties, Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py Fri Jan 18 21:47:21 2008 @@ -1,10 +1,13 @@ from pypy.conftest import gettestobjspace +mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' + class AppTestDotnet: def setup_class(cls): space = gettestobjspace(usemodules=('clr',)) cls.space = space - + cls.w_mscorlib = space.wrap(mscorlib) + def test_cliobject(self): import clr obj = clr._CliObject_internal('System.Collections.ArrayList', []) @@ -13,17 +16,17 @@ def test_cache(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') - ArrayList2 = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') + ArrayList2 = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') assert ArrayList is ArrayList2 def test_load_fail(self): import clr - raises(ImportError, clr.load_cli_class, 'Foo', 'Bar') + raises(ImportError, clr.load_cli_class, self.mscorlib, 'Foo', 'Bar') def test_ArrayList(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() obj.Add(42) obj.Add(43) @@ -32,13 +35,13 @@ def test_ArrayList_error(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() raises(StandardError, obj.get_Item, 0) def test_float_conversion(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() obj.Add(42.0) item = obj.get_Item(0) @@ -46,7 +49,7 @@ def test_bool_conversion(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() obj.Add(True) obj.Add(False) @@ -59,14 +62,14 @@ def test_getitem(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() obj.Add(42) assert obj[0] == 42 def test_property(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() obj.Add(42) assert obj.Count == 1 @@ -75,20 +78,20 @@ def test_unboundmethod(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() ArrayList.Add(obj, 42) assert obj.get_Item(0) == 42 def test_unboundmethod_typeerror(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') raises(TypeError, ArrayList.Add) raises(TypeError, ArrayList.Add, 0) def test_overload(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList() for i in range(10): obj.Add(i) @@ -97,12 +100,12 @@ def test_wrong_overload(self): import clr - Math = clr.load_cli_class('System', 'Math') + Math = clr.load_cli_class(self.mscorlib, 'System', 'Math') raises(TypeError, Math.Abs, "foo") def test_staticmethod(self): import clr - Math = clr.load_cli_class('System', 'Math') + Math = clr.load_cli_class(self.mscorlib, 'System', 'Math') res = Math.Abs(-42) assert res == 42 assert type(res) is int @@ -112,14 +115,14 @@ def test_constructor_args(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') obj = ArrayList(42) assert obj.Capacity == 42 def test_None_as_null(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') - Hashtable = clr.load_cli_class('System.Collections', 'Hashtable') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') + Hashtable = clr.load_cli_class(self.mscorlib, 'System.Collections', 'Hashtable') x = ArrayList() x.Add(None) assert x[0] is None @@ -128,7 +131,7 @@ def test_pass_opaque_arguments(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') class Foo: pass obj = Foo() @@ -139,7 +142,7 @@ def test_string_wrapping(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') x = ArrayList() x.Add("bar") s = x[0] @@ -148,21 +151,21 @@ def test_static_property(self): import clr import os - Environment = clr.load_cli_class('System', 'Environment') + Environment = clr.load_cli_class(self.mscorlib, 'System', 'Environment') assert Environment.CurrentDirectory == os.getcwd() Environment.CurrentDirectory == '/' assert Environment.CurrentDirectory == os.getcwd() def test_GetEnumerator(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') x = ArrayList() enum = x.GetEnumerator() assert enum.MoveNext() is False def test_iteration_arrayList(self): import clr - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(self.mscorlib, 'System.Collections', 'ArrayList') x = ArrayList() x.Add(1) x.Add(2) @@ -175,7 +178,7 @@ def test_iteration_stack(self): import clr - Stack = clr.load_cli_class('System.Collections', 'Stack') + Stack = clr.load_cli_class(self.mscorlib, 'System.Collections', 'Stack') obj = Stack() obj.Push(1) obj.Push(54) @@ -187,7 +190,7 @@ def test_load_generic_class(self): import clr - ListInt = clr.load_cli_class("System.Collections.Generic", "List`1[System.Int32]") + ListInt = clr.load_cli_class(self.mscorlib, "System.Collections.Generic", "List`1[System.Int32]") x = ListInt() x.Add(42) x.Add(4) @@ -199,13 +202,15 @@ def test_generic_class_typeerror(self): import clr - ListInt = clr.load_cli_class("System.Collections.Generic", "List`1[System.Int32]") + ListInt = clr.load_cli_class(self.mscorlib, "System.Collections.Generic", "List`1[System.Int32]") x = ListInt() raises(TypeError, x.Add, "test") def test_generic_dict(self): import clr - genDictIntStr = clr.load_cli_class("System.Collections.Generic","Dictionary`2[System.Int32,System.String]") + genDictIntStr = clr.load_cli_class(self.mscorlib, + "System.Collections.Generic", + "Dictionary`2[System.Int32,System.String]") x = genDictIntStr() x[1] = "test" x[2] = "rest" Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_importer.py Fri Jan 18 21:47:21 2008 @@ -5,23 +5,31 @@ space = gettestobjspace(usemodules=('clr', )) cls.space = space - def test_list_of_valid_namespaces(self): + def test_list_of_namespaces_and_classes(self): import clr - ns, gen = clr.get_assemblies_info() + ns, classes, generics = clr.get_assemblies_info() assert 'System' in ns assert 'System.Collections' in ns assert 'System.Runtime' in ns assert 'System.Runtime.InteropServices' in ns + assert 'System' not in classes + assert 'System.Math' in classes + assert 'System.Collections.ArrayList' in classes + + assert 'System.Collections.Generic.List' in classes + assert generics['System.Collections.Generic.List'] == 'System.Collections.Generic.List`1' + def test_import_hook_simple(self): + mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' import clr import System.Math assert System.Math.Abs(-5) == 5 assert System.Math.Pow(2, 5) == 2**5 - Math = clr.load_cli_class('System', 'Math') + Math = clr.load_cli_class(mscorlib, 'System', 'Math') assert Math is System.Math import System @@ -34,7 +42,7 @@ assert sum == 3+44 import System.Collections.ArrayList - ArrayList = clr.load_cli_class('System.Collections', 'ArrayList') + ArrayList = clr.load_cli_class(mscorlib, 'System.Collections', 'ArrayList') assert ArrayList is System.Collections.ArrayList def test_ImportError(self): @@ -55,3 +63,13 @@ def test_generic_class_import(self): import System.Collections.Generic.List + def test_import_from(self): + from System.Collections import ArrayList + + def test_AddReferenceByPartialName(self): + import clr + def fn(): + import System.Xml.XmlWriter + raises(ImportError, fn) + clr.AddReferenceByPartialName('System.Xml') + fn() # does not raise From antocuni at codespeak.net Fri Jan 18 21:50:33 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Jan 2008 21:50:33 +0100 (CET) Subject: [pypy-svn] r50763 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080118205033.BA17A1684C8@codespeak.net> Author: antocuni Date: Fri Jan 18 21:50:33 2008 New Revision: 50763 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Log: oups! Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Fri Jan 18 21:50:33 2008 @@ -180,8 +180,6 @@ properties.append((b_prop.get_Name(), get_name, set_name, is_static)) else: indexers.append((b_prop.get_Name(), get_name, set_name, is_static)) - if len(indexers) > 1: - import pdb;pdb.set_trace() w_properties = wrap_list_of_tuples(space, properties) w_indexers = wrap_list_of_tuples(space, indexers) return w_properties, w_indexers From pdg at codespeak.net Fri Jan 18 22:11:21 2008 From: pdg at codespeak.net (pdg at codespeak.net) Date: Fri, 18 Jan 2008 22:11:21 +0100 (CET) Subject: [pypy-svn] r50764 - in pypy/dist/pypy/rlib: . test Message-ID: <20080118211121.428D71684FC@codespeak.net> Author: pdg Date: Fri Jan 18 22:11:20 2008 New Revision: 50764 Added: pypy/dist/pypy/rlib/rjvm.py pypy/dist/pypy/rlib/test/test_rjvm.py Log: Jpype wrapper classes processing JVM for RPython (antocuni, pdg) Added: pypy/dist/pypy/rlib/rjvm.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rjvm.py Fri Jan 18 22:11:20 2008 @@ -0,0 +1,79 @@ + +import jpype +import atexit + + +class CallWrapper(object): + + def wrap_item(self, item): + if isinstance(item, jpype.java.lang.Object): + return JavaInstanceWrapper(item) + elif isinstance(item, jpype._jclass._JavaClass): + return JavaInstanceWrapper(item.__javaclass__) + elif isinstance(item, tuple) or isinstance(item, list): + return self.wrap_list(item) + return item + + def wrap_list(self, lst): + return [self.wrap_item(x) for x in lst] + + def __call__(self, *args, **kwargs): + result = self.__wrapped__(*args, **kwargs) + return self.wrap_item(result) + + +class JavaWrapper(CallWrapper): + def __init__(self, name): + self.__javaname__ = name + all_names = name.split(".") + temp_module = jpype + for n in all_names: + temp_module = getattr(temp_module, n) + self.__wrapped__ = temp_module + def __getattr__(self, attr): + if isinstance(getattr(self.__wrapped__, attr), type): + return JavaClassWrapper(getattr(self.__wrapped__, attr)) + elif isinstance(getattr(self.__wrapped__, attr), jpype.JPackage): + return JavaWrapper(self.__javaname__ + '.' + attr) + +class JavaInstanceWrapper(object): + def __init__(self, obj): + self.__wrapped__ = obj + + def __getattr__(self, attr): + return JavaMethodWrapper(getattr(self.__wrapped__, attr)) + +class JavaClassWrapper(CallWrapper): + def __init__(self, cls): + self.__wrapped__ = cls + + def __getattr__(self, attr): + result = None + try: + result = JavaStaticMethodWrapper(getattr(self.__wrapped__, attr)) + except AttributeError: + result = JavaStaticMethodWrapper(getattr(self.__wrapped__.__javaclass__, attr)) + return result + +class JavaMethodWrapper(CallWrapper): + + def __init__(self, meth): + self.__wrapped__ = meth + +class JavaStaticMethodWrapper(CallWrapper): + def __init__(self, static_meth): + self.__wrapped__ = static_meth + + + +jpype.startJVM(jpype.getDefaultJVMPath(), "-ea") +java = JavaWrapper("java") +JavaMethod = type(jpype.java.lang.Math.abs) + + +def cleanup(): + jpype.shutdownJVM() + +atexit.register(cleanup) + + Added: pypy/dist/pypy/rlib/test/test_rjvm.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/test/test_rjvm.py Fri Jan 18 22:11:20 2008 @@ -0,0 +1,39 @@ +from pypy.rlib.rjvm import java, JavaWrapper, JavaClassWrapper, JavaInstanceWrapper, JavaMethodWrapper, JavaStaticMethodWrapper +import py +py.test.skip("In Progress...") +def test_static_method(): + assert isinstance(java.lang, JavaWrapper) + assert isinstance(java.lang.Math, JavaClassWrapper) + assert isinstance(java.lang.Math.abs, JavaStaticMethodWrapper) + result = java.lang.Math.abs(-42) + assert isinstance(result, int) + assert result == 42 + +def test_class_instantiate(): + al = java.util.ArrayList() + assert isinstance(al, JavaInstanceWrapper) + assert isinstance(al.add, JavaMethodWrapper) + al.add("test") + assert al.get(0) == "test" + +def test_reflection(): + al_class = java.lang.Class.forName("java.util.ArrayList") + assert isinstance(al_class, JavaInstanceWrapper) + #meths = al_class.__javaclass__.getDeclaredMethods() + constructors = al_class.getDeclaredConstructors() + meths = al_class.getDeclaredMethods() + al = constructors[0].newInstance([]) + al_org = java.util.ArrayList() + assert isinstance(al, JavaInstanceWrapper) + assert isinstance(al.add, JavaMethodWrapper) + al_add = meths[2] + assert isinstance(al_add, JavaInstanceWrapper) + assert isinstance(al_add.invoke, JavaMethodWrapper) + # This fail, but work on the command line + al_add.invoke(al_org, ["Hello"]) + assert al_org[0] == "Hello" + al_add.invoke(al, ["Hello"]) + assert al[0] == "Hello" + + + From antocuni at codespeak.net Fri Jan 18 22:32:51 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 18 Jan 2008 22:32:51 +0100 (CET) Subject: [pypy-svn] r50765 - pypy/branch/clr-module-improvements/pypy/module/clr Message-ID: <20080118213251.F373D168533@codespeak.net> Author: antocuni Date: Fri Jan 18 22:32:50 2008 New Revision: 50765 Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Log: these str are not needed, and moreover they confuses the annotator Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py (original) +++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py Fri Jan 18 22:32:50 2008 @@ -209,8 +209,8 @@ w_assemblyName = space.wrap(b_assembly.get_FullName()) for i in range(len(b_types)): b_type = b_types[i] - namespace = str(b_type.get_Namespace()) - fullname = str(b_type.get_FullName()) + namespace = b_type.get_Namespace() + fullname = b_type.get_FullName() if '+' in fullname: # it's an internal type, skip it continue From exarkun at codespeak.net Fri Jan 18 23:15:17 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Fri, 18 Jan 2008 23:15:17 +0100 (CET) Subject: [pypy-svn] r50766 - pypy/build/buildbot Message-ID: <20080118221517.6087516855F@codespeak.net> Author: exarkun Date: Fri Jan 18 23:15:17 2008 New Revision: 50766 Modified: pypy/build/buildbot/pypybuilders.py Log: don't use --boxed with -A Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Fri Jan 18 23:15:17 2008 @@ -129,7 +129,9 @@ PyTest, python="pypy/translator/goal/pypy-c", testPackage="pypy", - testArguments=["-A"] + pytestArguments, + # Exclude --boxed if it was specified, because -A shouldn't + # really use much memory. + testArguments=["-A"] + list(arg for arg in pytestArguments if arg != "--boxed"), timeout=60 * 60) # self.addStep(FileUpload, From xoraxax at codespeak.net Sat Jan 19 00:34:28 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sat, 19 Jan 2008 00:34:28 +0100 (CET) Subject: [pypy-svn] r50768 - pypy/dist/pypy/translator/c Message-ID: <20080118233428.E357716853F@codespeak.net> Author: xoraxax Date: Sat Jan 19 00:34:27 2008 New Revision: 50768 Modified: pypy/dist/pypy/translator/c/database.py Log: Do not only sort the struct def nodes topologically, but also by name. Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sat Jan 19 00:34:27 2008 @@ -363,11 +363,15 @@ seen = {} def produce(node): if node not in seen: - for othernode in node.dependencies: + deps = node.dependencies.keys() + deps.sort(key=lambda x: x.name) + for othernode in deps: produce(othernode) result.append(node) seen[node] = True - for node in self.structdefnodes.values(): + nodes = self.structdefnodes.values() + nodes.sort(key=lambda x: x.name) + for node in nodes: produce(node) return result From cfbolz at codespeak.net Sat Jan 19 11:21:09 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 11:21:09 +0100 (CET) Subject: [pypy-svn] r50770 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080119102109.62787168576@codespeak.net> Author: cfbolz Date: Sat Jan 19 11:21:08 2008 New Revision: 50770 Modified: pypy/dist/pypy/jit/timeshifter/test/support.py pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Log: some merging tests for virtual nested structures Modified: pypy/dist/pypy/jit/timeshifter/test/support.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/support.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/support.py Sat Jan 19 11:21:08 2008 @@ -90,6 +90,8 @@ structdesc = rcontainer.StructTypeDesc(fakehrtyper, TYPE) box = structdesc.factory() for fielddesc, valuebox in zip(structdesc.fielddescs, boxes): + if valuebox is None: + break box.op_setfield(jitstate, fielddesc, valuebox) assert jitstate.curbuilder.ops == [] return box Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Sat Jan 19 11:21:08 2008 @@ -10,8 +10,12 @@ class TestVirtualStruct: def setup_class(cls): - cls.STRUCT = lltype.Struct("dummy", ("foo", lltype.Signed)) + cls.STRUCT = lltype.GcStruct("dummy", ("foo", lltype.Signed)) cls.fielddesc = getfielddesc(cls.STRUCT, "foo") + FORWARD = lltype.GcForwardReference() + cls.NESTEDSTRUCT = lltype.GcStruct('dummy', ("foo", lltype.Signed), + ('x', lltype.Ptr(FORWARD))) + FORWARD.become(cls.NESTEDSTRUCT) def test_virtualstruct_get_set_field(self): V42 = FakeGenVar(42) @@ -101,3 +105,43 @@ assert outgoingvarboxes == [constbox20] # ^^^ the FrozenVar() in newfrozenbox corresponds to # constbox20 in oldbox. + + def test_nested_structure_no_vars(self): + NESTED = self.NESTEDSTRUCT + constbox30 = makebox(30) + constbox20 = makebox(20) + oldbox = vmalloc(NESTED, constbox20, vmalloc(NESTED, constbox30)) + + jitstate = FakeJITState() + frozenbox = oldbox.freeze(rvalue.freeze_memo()) + # check that frozenbox matches oldbox exactly + outgoingvarboxes = [] + res = frozenbox.exactmatch(oldbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + assert outgoingvarboxes == [] # there is no FrozenVar + + + def test_nested_structures_variables(self): + NESTED = self.NESTEDSTRUCT + V42 = FakeGenVar(42) + constbox20 = makebox(20) + oldbox = vmalloc(NESTED, constbox20, vmalloc(NESTED, makebox(V42))) + jitstate = FakeJITState() + frozenbox = oldbox.freeze(rvalue.freeze_memo()) + # check that frozenbox matches oldbox exactly + outgoingvarboxes = [] + res = frozenbox.exactmatch(oldbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + assert len(outgoingvarboxes) == 1 and outgoingvarboxes[0].genvar is V42 + + constbox30 = makebox(30) + newbox = vmalloc(NESTED, constbox20, vmalloc(NESTED, constbox30)) + # check that frozenbox also matches newbox exactly + outgoingvarboxes = [] + res = frozenbox.exactmatch(newbox, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert res + assert outgoingvarboxes == [constbox30] + # ^^^ the live box corresponding to the FrozenVar From arigo at codespeak.net Sat Jan 19 11:50:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 11:50:58 +0100 (CET) Subject: [pypy-svn] r50771 - pypy/dist/pypy/module/__builtin__ Message-ID: <20080119105058.B0B3A168466@codespeak.net> Author: arigo Date: Sat Jan 19 11:50:56 2008 New Revision: 50771 Added: pypy/dist/pypy/module/__builtin__/__init__.py.merge.tmp - copied, changed from r50770, pypy/dist/pypy/module/__builtin__/__init__.py Log: (cfbolz) merging of svn+ssh://codespeak.net/svn/pypy/branch/clr-module-improvements/pypy/module/__builtin__/__init__.py: only install the zipimport hook when the zipimport module is requested From arigo at codespeak.net Sat Jan 19 11:51:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 11:51:02 +0100 (CET) Subject: [pypy-svn] r50772 - pypy/dist/pypy/translator/cli Message-ID: <20080119105102.58522168528@codespeak.net> Author: arigo Date: Sat Jan 19 11:51:00 2008 New Revision: 50772 Added: pypy/dist/pypy/translator/cli/dotnet.py.merge.tmp - copied, changed from r50770, pypy/dist/pypy/translator/cli/dotnet.py Log: (antocuni) merging of svn+ssh://codespeak.net/svn/pypy/branch/clr-module-improvements/pypy/translator/cli/dotnet.py fix annotations of strings. Thanks cfbolz fix for pythonnet 2.0 From arigo at codespeak.net Sat Jan 19 11:51:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 11:51:59 +0100 (CET) Subject: [pypy-svn] r50773 - in pypy/dist/pypy: module/__builtin__ module/clr translator/cli translator/cli/test Message-ID: <20080119105159.99982168467@codespeak.net> Author: arigo Date: Sat Jan 19 11:51:59 2008 New Revision: 50773 Added: pypy/dist/pypy/module/__builtin__/__init__.py - copied unchanged from r50772, pypy/dist/pypy/module/__builtin__/__init__.py.merge.tmp pypy/dist/pypy/module/clr/ - copied from r50772, pypy/branch/clr-module-improvements/pypy/module/clr/ pypy/dist/pypy/translator/cli/dotnet.py - copied unchanged from r50772, pypy/dist/pypy/translator/cli/dotnet.py.merge.tmp pypy/dist/pypy/translator/cli/support.py - copied unchanged from r50772, pypy/branch/clr-module-improvements/pypy/translator/cli/support.py pypy/dist/pypy/translator/cli/test/test_dotnet.py - copied unchanged from r50772, pypy/branch/clr-module-improvements/pypy/translator/cli/test/test_dotnet.py Removed: pypy/dist/pypy/module/__builtin__/__init__.py.merge.tmp pypy/dist/pypy/translator/cli/dotnet.py.merge.tmp Log: Merge of the clr-module-improvements branch. From arigo at codespeak.net Sat Jan 19 11:52:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 11:52:34 +0100 (CET) Subject: [pypy-svn] r50774 - pypy/branch/clr-module-improvements Message-ID: <20080119105234.6B5B4168467@codespeak.net> Author: arigo Date: Sat Jan 19 11:52:34 2008 New Revision: 50774 Removed: pypy/branch/clr-module-improvements/ Log: Kill the merged branch. From arigo at codespeak.net Sat Jan 19 11:55:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 11:55:18 +0100 (CET) Subject: [pypy-svn] r50775 - pypy/dist/pypy/rlib/test Message-ID: <20080119105518.69F91168466@codespeak.net> Author: arigo Date: Sat Jan 19 11:55:17 2008 New Revision: 50775 Modified: pypy/dist/pypy/rlib/test/test_rjvm.py Log: Move the skip before the 'import jpype' which fails if this is not installed. Modified: pypy/dist/pypy/rlib/test/test_rjvm.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rjvm.py (original) +++ pypy/dist/pypy/rlib/test/test_rjvm.py Sat Jan 19 11:55:17 2008 @@ -1,6 +1,6 @@ -from pypy.rlib.rjvm import java, JavaWrapper, JavaClassWrapper, JavaInstanceWrapper, JavaMethodWrapper, JavaStaticMethodWrapper import py py.test.skip("In Progress...") +from pypy.rlib.rjvm import java, JavaWrapper, JavaClassWrapper, JavaInstanceWrapper, JavaMethodWrapper, JavaStaticMethodWrapper def test_static_method(): assert isinstance(java.lang, JavaWrapper) assert isinstance(java.lang.Math, JavaClassWrapper) From antocuni at codespeak.net Sat Jan 19 11:58:40 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 19 Jan 2008 11:58:40 +0100 (CET) Subject: [pypy-svn] r50776 - pypy/dist/pypy/rlib/test Message-ID: <20080119105840.96379168467@codespeak.net> Author: antocuni Date: Sat Jan 19 11:58:40 2008 New Revision: 50776 Modified: pypy/dist/pypy/rlib/test/test_rjvm.py Log: skip only if jpype is not found Modified: pypy/dist/pypy/rlib/test/test_rjvm.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rjvm.py (original) +++ pypy/dist/pypy/rlib/test/test_rjvm.py Sat Jan 19 11:58:40 2008 @@ -1,6 +1,11 @@ import py -py.test.skip("In Progress...") +try: + import jpype +except ImportError: + py.test.skip("In Progress...") + from pypy.rlib.rjvm import java, JavaWrapper, JavaClassWrapper, JavaInstanceWrapper, JavaMethodWrapper, JavaStaticMethodWrapper + def test_static_method(): assert isinstance(java.lang, JavaWrapper) assert isinstance(java.lang.Math, JavaClassWrapper) @@ -17,6 +22,7 @@ assert al.get(0) == "test" def test_reflection(): + py.test.skip('in progress') al_class = java.lang.Class.forName("java.util.ArrayList") assert isinstance(al_class, JavaInstanceWrapper) #meths = al_class.__javaclass__.getDeclaredMethods() @@ -34,6 +40,3 @@ assert al_org[0] == "Hello" al_add.invoke(al, ["Hello"]) assert al[0] == "Hello" - - - From arigo at codespeak.net Sat Jan 19 12:24:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 12:24:33 +0100 (CET) Subject: [pypy-svn] r50777 - pypy/dist/pypy/jit/timeshifter/test Message-ID: <20080119112433.1D476168520@codespeak.net> Author: arigo Date: Sat Jan 19 12:24:32 2008 New Revision: 50777 Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Log: (cfbolz, antocuni not much, arigo) Extract common logic into a helper method. Modified: pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py (original) +++ pypy/dist/pypy/jit/timeshifter/test/test_rcontainer.py Sat Jan 19 12:24:32 2008 @@ -35,29 +35,31 @@ ('malloc_fixedsize', (('alloc', self.STRUCT),), V1), ('setfield', (('field', self.STRUCT, 'foo'), V1, V42), None)] + def match(self, frozenbox, box, expected_outgoing): + # In case of exact match, expected_outgoing is the list of subboxes + # of 'box' that correspond to FrozenVar placeholders in frozenbox. + # Otherwise, it is the list of subboxes of 'box' that should be + # generalized to become variables. + outgoingvarboxes = [] + res = frozenbox.exactmatch(box, outgoingvarboxes, + rvalue.exactmatch_memo()) + assert outgoingvarboxes == expected_outgoing + return res + def test_simple_merge(self): V42 = FakeGenVar(42) oldbox = vmalloc(self.STRUCT, makebox(V42)) frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that frozenbox matches oldbox exactly - outgoingvarboxes = [] - res = frozenbox.exactmatch(oldbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res jitstate = FakeJITState() fieldbox = oldbox.content.op_getfield(jitstate, self.fielddesc) - assert outgoingvarboxes == [fieldbox] - # ^^^ the live box corresponding to the FrozenVar + assert self.match(frozenbox, oldbox, [fieldbox]) constbox23 = makebox(23) newbox = vmalloc(self.STRUCT, constbox23) # check that frozenbox also matches newbox exactly - outgoingvarboxes = [] - res = frozenbox.exactmatch(newbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res - assert outgoingvarboxes == [constbox23] - # ^^^ the live box corresponding to the FrozenVar + assert self.match(frozenbox, newbox, [constbox23]) + def test_simple_merge_generalize(self): S = self.STRUCT @@ -65,23 +67,15 @@ oldbox = vmalloc(S, constbox20) frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that frozenbox matches oldbox exactly - outgoingvarboxes = [] - res = frozenbox.exactmatch(oldbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res - assert outgoingvarboxes == [] # there is no FrozenVar + assert self.match(frozenbox, oldbox, []) # there is no FrozenVar constbox23 = makebox(23) newbox = vmalloc(S, constbox23) # non-exact match: a different constant box in the virtual struct field - outgoingvarboxes = [] - res = frozenbox.exactmatch(newbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert not res - assert outgoingvarboxes == [constbox23] - # ^^^ constbox23 is what should be generalized with forcevar() - # in order to get something that is at least as general as - # both oldbox and newbox + assert not self.match(frozenbox, newbox, [constbox23]) + # constbox23 is what should be generalized with forcevar() + # in order to get something that is at least as general as + # both oldbox and newbox jitstate = FakeJITState() replace_memo = rvalue.copy_memo() @@ -98,14 +92,11 @@ # check that now newbox really generalizes oldbox newfrozenbox = newbox.freeze(rvalue.freeze_memo()) - outgoingvarboxes = [] - res = newfrozenbox.exactmatch(oldbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res - assert outgoingvarboxes == [constbox20] + assert self.match(newfrozenbox, oldbox, [constbox20]) # ^^^ the FrozenVar() in newfrozenbox corresponds to # constbox20 in oldbox. + def test_nested_structure_no_vars(self): NESTED = self.NESTEDSTRUCT constbox30 = makebox(30) @@ -115,33 +106,20 @@ jitstate = FakeJITState() frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that frozenbox matches oldbox exactly - outgoingvarboxes = [] - res = frozenbox.exactmatch(oldbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res - assert outgoingvarboxes == [] # there is no FrozenVar + assert self.match(frozenbox, oldbox, []) # there is no FrozenVar def test_nested_structures_variables(self): NESTED = self.NESTEDSTRUCT - V42 = FakeGenVar(42) + varbox42 = makebox(FakeGenVar(42)) constbox20 = makebox(20) - oldbox = vmalloc(NESTED, constbox20, vmalloc(NESTED, makebox(V42))) + oldbox = vmalloc(NESTED, constbox20, vmalloc(NESTED, varbox42)) jitstate = FakeJITState() frozenbox = oldbox.freeze(rvalue.freeze_memo()) # check that frozenbox matches oldbox exactly - outgoingvarboxes = [] - res = frozenbox.exactmatch(oldbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res - assert len(outgoingvarboxes) == 1 and outgoingvarboxes[0].genvar is V42 + assert self.match(frozenbox, oldbox, [varbox42]) constbox30 = makebox(30) newbox = vmalloc(NESTED, constbox20, vmalloc(NESTED, constbox30)) # check that frozenbox also matches newbox exactly - outgoingvarboxes = [] - res = frozenbox.exactmatch(newbox, outgoingvarboxes, - rvalue.exactmatch_memo()) - assert res - assert outgoingvarboxes == [constbox30] - # ^^^ the live box corresponding to the FrozenVar + assert self.match(frozenbox, newbox, [constbox30]) From antocuni at codespeak.net Sat Jan 19 16:28:57 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 19 Jan 2008 16:28:57 +0100 (CET) Subject: [pypy-svn] r50780 - in pypy/dist/pypy/module/clr: . test Message-ID: <20080119152857.214031684FD@codespeak.net> Author: antocuni Date: Sat Jan 19 16:28:56 2008 New Revision: 50780 Modified: pypy/dist/pypy/module/clr/interp_clr.py pypy/dist/pypy/module/clr/test/test_importer.py Log: don't fail if the indexer method is overloaded Modified: pypy/dist/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/dist/pypy/module/clr/interp_clr.py (original) +++ pypy/dist/pypy/module/clr/interp_clr.py Sat Jan 19 16:28:56 2008 @@ -159,7 +159,7 @@ def get_properties(space, b_type): properties = [] - indexers = [] + indexers = {} b_propertyinfos = b_type.GetProperties() for i in range(len(b_propertyinfos)): b_prop = b_propertyinfos[i] @@ -179,9 +179,9 @@ if len(b_indexparams) == 0: properties.append((b_prop.get_Name(), get_name, set_name, is_static)) else: - indexers.append((b_prop.get_Name(), get_name, set_name, is_static)) + indexers[b_prop.get_Name(), get_name, set_name, is_static] = None w_properties = wrap_list_of_tuples(space, properties) - w_indexers = wrap_list_of_tuples(space, indexers) + w_indexers = wrap_list_of_tuples(space, indexers.keys()) return w_properties, w_indexers class _CliClassCache: Modified: pypy/dist/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/dist/pypy/module/clr/test/test_importer.py (original) +++ pypy/dist/pypy/module/clr/test/test_importer.py Sat Jan 19 16:28:56 2008 @@ -69,7 +69,7 @@ def test_AddReferenceByPartialName(self): import clr def fn(): - import System.Xml.XmlWriter + import System.Xml.XmlReader raises(ImportError, fn) clr.AddReferenceByPartialName('System.Xml') fn() # does not raise From cfbolz at codespeak.net Sat Jan 19 17:03:07 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 17:03:07 +0100 (CET) Subject: [pypy-svn] r50781 - pypy/dist/pypy/doc/discussion Message-ID: <20080119160307.A4B92168502@codespeak.net> Author: cfbolz Date: Sat Jan 19 17:03:06 2008 New Revision: 50781 Added: pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt (contents, props changed) Log: (arigo, antocuni, cfbolz): some notes about the upcoming JIT refactoring Added: pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt Sat Jan 19 17:03:06 2008 @@ -0,0 +1,26 @@ +Rainbow Interpreter +=================== + + - bytecode: linearize hintannotated low-level exceptionstransformed graphs + into strings + + - opcodes: + + - all basics operations in red and green variants + + - additional operations for JIT housekeeping like split, merge, + promote, calls?, return + + - special ops: box green, clear vars + + - special care needed (later) for implicit promotes (e.g. for exception + paths and virtualizables) + + - red variables are boxes, already stored on the VirtualFrame + + - green variables are GenConsts, should be stored on the VirtualFrame as + well + + - interpreter is manually written in a stackless style: jitstates have + linked lists of frames anyway already + From cfbolz at codespeak.net Sat Jan 19 17:08:58 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 17:08:58 +0100 (CET) Subject: [pypy-svn] r50782 - pypy/dist/pypy/doc/discussion Message-ID: <20080119160858.53C40168501@codespeak.net> Author: cfbolz Date: Sat Jan 19 17:08:57 2008 New Revision: 50782 Modified: pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt Log: (antocuni, arigo): try to be less confusing Modified: pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt (original) +++ pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt Sat Jan 19 17:08:57 2008 @@ -2,7 +2,8 @@ =================== - bytecode: linearize hintannotated low-level exceptionstransformed graphs - into strings + into a datastructure containing a bytecode string (the opcodes) and + constants - opcodes: From cfbolz at codespeak.net Sat Jan 19 17:22:07 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 17:22:07 +0100 (CET) Subject: [pypy-svn] r50783 - pypy/dist/pypy/doc/discussion Message-ID: <20080119162207.E1D0B168502@codespeak.net> Author: cfbolz Date: Sat Jan 19 17:22:07 2008 New Revision: 50783 Modified: pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt Log: clarification concerning local variables Modified: pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt (original) +++ pypy/dist/pypy/doc/discussion/jit-refactoring-plan.txt Sat Jan 19 17:22:07 2008 @@ -10,9 +10,7 @@ - all basics operations in red and green variants - additional operations for JIT housekeeping like split, merge, - promote, calls?, return - - - special ops: box green, clear vars + promote, calls?, return, box_green_var - special care needed (later) for implicit promotes (e.g. for exception paths and virtualizables) @@ -21,6 +19,9 @@ - green variables are GenConsts, should be stored on the VirtualFrame as well + + - variables are valid for one block, renaming op (with variable number of + args) - interpreter is manually written in a stackless style: jitstates have linked lists of frames anyway already From cfbolz at codespeak.net Sat Jan 19 17:45:54 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 17:45:54 +0100 (CET) Subject: [pypy-svn] r50784 - pypy/dist/pypy/doc/image Message-ID: <20080119164554.B38481683DB@codespeak.net> Author: cfbolz Date: Sat Jan 19 17:45:53 2008 New Revision: 50784 Added: pypy/dist/pypy/doc/image/jitdata-interpreter.dot pypy/dist/pypy/doc/image/merge-split.dot Log: (cfbolz, arigo around) two graphs about the JIT Added: pypy/dist/pypy/doc/image/jitdata-interpreter.dot ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/image/jitdata-interpreter.dot Sat Jan 19 17:45:53 2008 @@ -0,0 +1,46 @@ +digraph jitdata { + shape=box; + + interpreter [label = "Interpreter", shape=box] + jitstate [label = "JITState", shape=box] + subgraph frames { + rank=same + frame0 [label = " PC\nVirtualFrame 1", shape=box] + frame1 [label = "\nVirtualFrame 2", shape=box] + frame0 -> frame1 [label="back"] + frame2 [label = "\nVirtualFrame 3", shape=box] + frame1 -> frame2 [label="back"] + frame3 [label = "...", color=white, shape=BUH] + frame3 -> frame2 [label="back"] + } + gvars [label = "list of green vars\n(GenConsts)", shape=box] + rvars [label = "list of red vars\n(RedBox)", shape=box] + bc [label = "bytecode", shape=box] + interpreter -> jitstate + jitstate -> frame0 + frame0 -> gvars + frame0 -> rvars + frame0 -> bc + + rvars -> ptrbox [label = "contains"] + ptrbox [label = "PtrBox", shape=box] + rvars -> intbox [label = "contains"] + intbox [label = "IntBox", shape=box] + container [label = "VirtualContainer", shape=box] + ptrbox -> container [label = "content"] + ptrbox -> genvarorconst0 [label= "genvar"]; + intbox -> genvarorconst1 [label= "genvar"]; + genvarorconst0 [label = "GenVarOrConst", shape=box] + genvarorconst1 [label = "GenVarOrConst", shape=box] + container -> ptrbox [label = "ownbox"] + contentboxes [label = "list of content\n(boxes)", shape=box] + container -> contentboxes [label = "contentboxes"] + contentboxes -> box0 [label = "contains"] + contentboxes -> box1 [label = "contains"] + contentboxes -> box2 [label = "contains"] + contentboxes -> box3 [label = "contains"] + box0 [label = "RedBox", shape=box] + box1 [label = "RedBox", shape=box] + box2 [label = "RedBox", shape=box] + box3 [label = "RedBox", shape=box] +} Added: pypy/dist/pypy/doc/image/merge-split.dot ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/image/merge-split.dot Sat Jan 19 17:45:53 2008 @@ -0,0 +1,14 @@ +digraph JIT { + + block0 [label = "...\nsplit", shape=octagon] + block0 -> block1 [label="False"] + block0 -> block2 [label="True"] + + block1 [label = "...", shape=box] + block2 [label = "...", shape=box] + block3 [label = "merge\n...", shape=box] + + block1 -> block3; + block2 -> block3; + +} From antocuni at codespeak.net Sat Jan 19 17:56:59 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 19 Jan 2008 17:56:59 +0100 (CET) Subject: [pypy-svn] r50785 - in pypy/dist/pypy/module/clr: . test Message-ID: <20080119165659.8512A16851A@codespeak.net> Author: antocuni Date: Sat Jan 19 17:56:59 2008 New Revision: 50785 Modified: pypy/dist/pypy/module/clr/__init__.py pypy/dist/pypy/module/clr/app_clr.py pypy/dist/pypy/module/clr/interp_clr.py pypy/dist/pypy/module/clr/test/test_clr.py pypy/dist/pypy/module/clr/test/test_importer.py Log: classes loaded from external assemblies finally work! :-) To do that I had to yak shave a lot, as confirmed by the lot of new tests :-) Modified: pypy/dist/pypy/module/clr/__init__.py ============================================================================== --- pypy/dist/pypy/module/clr/__init__.py (original) +++ pypy/dist/pypy/module/clr/__init__.py Sat Jan 19 17:56:59 2008 @@ -21,5 +21,6 @@ def startup(self, space): self.space.appexec([self], """(clr_module): import sys + clr_module.get_assemblies_info() # load info for std assemblies sys.meta_path.append(clr_module.dotnetimporter()) """) Modified: pypy/dist/pypy/module/clr/app_clr.py ============================================================================== --- pypy/dist/pypy/module/clr/app_clr.py (original) +++ pypy/dist/pypy/module/clr/app_clr.py Sat Jan 19 17:56:59 2008 @@ -131,7 +131,7 @@ def __init__(self, *args): import clr - self.__cliobj__ = clr._CliObject_internal(self.__cliclass__, args) + self.__cliobj__ = clr._CliObject_internal(self.__fullyqualifiedname__, args) class IEnumeratorWrapper(object): @@ -165,7 +165,7 @@ '__assemblyname__': assemblyname, '__module__': namespace} for name in staticmethods: - d[name] = StaticMethodWrapper(fullname, name) + d[name] = StaticMethodWrapper(assembly_qualified_name, name) for name in methods: d[name] = MethodWrapper(name) Modified: pypy/dist/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/dist/pypy/module/clr/interp_clr.py (original) +++ pypy/dist/pypy/module/clr/interp_clr.py Sat Jan 19 17:56:59 2008 @@ -30,10 +30,14 @@ def get_constructor(space, b_type, b_paramtypes): try: - return b_type.GetConstructor(b_paramtypes) + ctor = b_type.GetConstructor(b_paramtypes) except AmbiguousMatchException: msg = 'Multiple constructors could match' raise OperationError(space.w_TypeError, space.wrap(msg)) + if ctor is None: + msg = 'No overloads for constructor could match' + raise OperationError(space.w_TypeError, space.wrap(msg)) + return ctor def rewrap_args(space, w_args, startfrom): args = space.unpackiterable(w_args) @@ -86,7 +90,20 @@ call_staticmethod.unwrap_spec = [ObjSpace, str, str, W_Root] def py2cli(space, w_obj): - return w_obj.tocli() + try: + cliobj = space.getattr(w_obj, space.wrap('__cliobj__')) + except OperationError, e: + if e.match(space, space.w_AttributeError): + # it hasn't got a __cloobj__ + return w_obj.tocli() + else: + raise + else: + if isinstance(cliobj, W_CliObject): + return cliobj.b_obj # unwrap it! + else: + # this shouldn't happen! Fallback to the default impl + return w_obj.tocli() def cli2py(space, b_obj): # TODO: support other types and find the most efficient way to Modified: pypy/dist/pypy/module/clr/test/test_clr.py ============================================================================== --- pypy/dist/pypy/module/clr/test/test_clr.py (original) +++ pypy/dist/pypy/module/clr/test/test_clr.py Sat Jan 19 17:56:59 2008 @@ -103,6 +103,10 @@ Math = clr.load_cli_class(self.mscorlib, 'System', 'Math') raises(TypeError, Math.Abs, "foo") + def test_wrong_overload_ctor(self): + from System.Collections import ArrayList + raises(TypeError, ArrayList, "foo") + def test_staticmethod(self): import clr Math = clr.load_cli_class(self.mscorlib, 'System', 'Math') @@ -263,3 +267,19 @@ import clr from System.Collections.Generic import List raises(TypeError, "List[int, int]") + + def test_py2cli_cliobjects(self): + from System.IO import StreamReader, MemoryStream + mem = MemoryStream(100) + sr = StreamReader(mem) # does not raise + + def test_external_assemblies(self): + import clr + clr.AddReferenceByPartialName('System.Xml') + from System.IO import StringReader + from System.Xml import XmlReader + buffer = StringReader("test") + xml = XmlReader.Create(buffer) + xml.ReadStartElement("foo") + assert xml.ReadString() == 'test' + xml.ReadEndElement() Modified: pypy/dist/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/dist/pypy/module/clr/test/test_importer.py (original) +++ pypy/dist/pypy/module/clr/test/test_importer.py Sat Jan 19 17:56:59 2008 @@ -68,8 +68,9 @@ def test_AddReferenceByPartialName(self): import clr - def fn(): - import System.Xml.XmlReader - raises(ImportError, fn) clr.AddReferenceByPartialName('System.Xml') - fn() # does not raise + import System.Xml.XmlReader # does not raise + + def test_AddReference_early(self): + import clr + clr.AddReferenceByPartialName('System.Xml') From cfbolz at codespeak.net Sat Jan 19 18:21:46 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 18:21:46 +0100 (CET) Subject: [pypy-svn] r50786 - pypy/dist/pypy/module/__builtin__/test Message-ID: <20080119172146.403FF168522@codespeak.net> Author: cfbolz Date: Sat Jan 19 18:21:45 2008 New Revision: 50786 Modified: pypy/dist/pypy/module/__builtin__/test/test_classobj.py Log: make test more precise Modified: pypy/dist/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_classobj.py Sat Jan 19 18:21:45 2008 @@ -659,5 +659,5 @@ return 3 for i in X(): - print i, + assert i == 3 break From cfbolz at codespeak.net Sat Jan 19 18:30:09 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 19 Jan 2008 18:30:09 +0100 (CET) Subject: [pypy-svn] r50787 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20080119173009.A0812168522@codespeak.net> Author: cfbolz Date: Sat Jan 19 18:30:09 2008 New Revision: 50787 Modified: pypy/dist/pypy/module/__builtin__/interp_classobj.py pypy/dist/pypy/module/__builtin__/test/test_classobj.py Log: issue352 resolved allow to return NotImplemented from the __cmp__ of oldstyle classes Modified: pypy/dist/pypy/module/__builtin__/interp_classobj.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/interp_classobj.py (original) +++ pypy/dist/pypy/module/__builtin__/interp_classobj.py Sat Jan 19 18:30:09 2008 @@ -476,6 +476,8 @@ w_func = w_a.getattr(space, space.wrap('__cmp__'), False) if w_func is not None: w_res = space.call_function(w_func, w_b) + if space.is_w(w_res, space.w_NotImplemented): + return w_res try: res = space.int_w(w_res) except OperationError, e: @@ -493,6 +495,8 @@ w_func = w_b.getattr(space, space.wrap('__cmp__'), False) if w_func is not None: w_res = space.call_function(w_func, w_a) + if space.is_w(w_res, space.w_NotImplemented): + return w_res try: res = space.int_w(w_res) except OperationError, e: Modified: pypy/dist/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_classobj.py Sat Jan 19 18:30:09 2008 @@ -661,3 +661,14 @@ for i in X(): assert i == 3 break + + def test_cmp_returning_notimplemented(self): + class X: + def __cmp__(self, other): + return NotImplemented + + class Y: + pass + + assert X() != 5 + assert Y() != X() From arigo at codespeak.net Sat Jan 19 18:42:46 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 19 Jan 2008 18:42:46 +0100 (CET) Subject: [pypy-svn] r50788 - in pypy/dist/pypy: . module/__builtin__/test Message-ID: <20080119174246.36EB1168503@codespeak.net> Author: arigo Date: Sat Jan 19 18:42:43 2008 New Revision: 50788 Modified: pypy/dist/pypy/conftest.py pypy/dist/pypy/module/__builtin__/test/test_classobj.py Log: For comparison purposes, make test_classobj.py runnable with "py.test -A". Two tests fail on CPython for unclear reasons -> skip them there. Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Sat Jan 19 18:42:43 2008 @@ -90,6 +90,8 @@ "module %r required" % (modname,)) continue if info is None: + if key == 'objspace.std.oldstyle' and value: + continue # fine on CPython py.test.skip("cannot runappdirect this test on top of CPython") has = info.get(key, None) if has != value: Modified: pypy/dist/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_classobj.py Sat Jan 19 18:42:43 2008 @@ -47,8 +47,9 @@ assert C.c == 19 def test_class_repr(self): - class A: - pass + d = {} + exec "class A: pass" in d # to have no __module__ + A = d['A'] assert repr(A).startswith(" Author: cfbolz Date: Sat Jan 19 23:06:05 2008 New Revision: 50789 Modified: pypy/dist/pypy/module/__builtin__/test/test_classobj.py Log: this works fine with CPython, but obviously only from version 2.5 on :-) Modified: pypy/dist/pypy/module/__builtin__/test/test_classobj.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_classobj.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_classobj.py Sat Jan 19 23:06:05 2008 @@ -487,8 +487,8 @@ def test_index(self): import sys - if not hasattr(sys, 'pypy_objspaceclass'): - skip("this is not supported by CPython") + if sys.version_info < (2, 5): + skip("this is not supported by CPython before version 2.4") class A: def __index__(self): return 1 From antocuni at codespeak.net Sat Jan 19 23:13:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 19 Jan 2008 23:13:56 +0100 (CET) Subject: [pypy-svn] r50790 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20080119221356.05247168544@codespeak.net> Author: antocuni Date: Sat Jan 19 23:13:56 2008 New Revision: 50790 Modified: pypy/dist/pypy/translator/cli/dotnet.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/test/test_dotnet.py Log: a hack to be able to construct delegates of type EventHandler from RPython Modified: pypy/dist/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/dotnet.py (original) +++ pypy/dist/pypy/translator/cli/dotnet.py Sat Jan 19 23:13:56 2008 @@ -519,3 +519,21 @@ def specialize_call(self, hop): v_type, = hop.inputargs(*hop.args_r) return hop.genop('cli_typeof', [v_type], hop.r_result.lowleveltype) + + +def eventhandler(obj): + return CLR.System.EventHandler(obj) + +class Entry(ExtRegistryEntry): + _about_ = eventhandler + + def compute_result_annotation(self, s_value): + from pypy.translator.cli.query import load_class_maybe + cliType = load_class_maybe('System.EventHandler') + return SomeOOInstance(cliType._INSTANCE) + + def specialize_call(self, hop): + v_obj, = hop.inputargs(*hop.args_r) + methodname = hop.args_r[0].methodname + c_methodname = hop.inputconst(ootype.Void, methodname) + return hop.genop('cli_eventhandler', [v_obj, c_methodname], hop.r_result.lowleveltype) Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Sat Jan 19 23:13:56 2008 @@ -9,6 +9,13 @@ STRING_HELPER_CLASS = '[pypylib]pypy.runtime.String' +def functype_to_cts(cts, FUNC): + ret_type = cts.lltype_to_cts(FUNC.RESULT) + arg_types = [cts.lltype_to_cts(arg).typename() + for arg in FUNC.ARGS + if arg is not ootype.Void] + return ret_type, arg_types + class _Call(_OOCall): def render(self, generator, op): @@ -22,10 +29,7 @@ for func_arg in args[1:]: # push parameters self._load_arg_or_null(generator, func_arg) cts = generator.cts - ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT) - arg_types = [cts.lltype_to_cts(arg).typename() - for arg in funcdesc._TYPE.ARGS - if arg is not ootype.Void] + ret_type, arg_types = functype_to_cts(cts, funcdesc._TYPE) arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list) generator.call_signature(signature) @@ -59,10 +63,7 @@ # special case for string: don't use methods, but plain functions METH = this.concretetype._METHODS[method_name] cts = generator.cts - ret_type = cts.lltype_to_cts(METH.RESULT) - arg_types = [cts.lltype_to_cts(arg).typename() - for arg in METH.ARGS - if arg is not ootype.Void] + ret_type, arg_types = functype_to_cts(cts, METH) arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename()) arg_list = ', '.join(arg_types) signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list) @@ -197,6 +198,25 @@ generator.ilasm.opcode('ldtoken', fullname) generator.ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)') +class _EventHandler(MicroInstruction): + def render(self, generator, op): + cts = generator.cts + v_obj, c_methname = op.args + assert c_methname.concretetype is ootype.Void + TYPE = v_obj.concretetype + classname = TYPE._name + methname = 'o' + c_methname.value # XXX: do proper mangling + _, meth = TYPE._lookup(methname) + METH = ootype.typeOf(meth) + ret_type, arg_types = functype_to_cts(cts, METH) + arg_list = ', '.join(arg_types) + generator.load(v_obj) + desc = '%s class %s::%s(%s)' % (ret_type, classname, methname, arg_list) + generator.ilasm.opcode('ldftn instance', desc) + generator.ilasm.opcode('newobj', 'instance void class [mscorlib]System.EventHandler::.ctor(object, native int)') + + + OOTYPE_TO_MNEMONIC = { ootype.Signed: 'i4', ootype.SignedLongLong: 'i8', @@ -222,4 +242,5 @@ GetArrayElem = _GetArrayElem() SetArrayElem = _SetArrayElem() TypeOf = _TypeOf() +EventHandler = _EventHandler() CastPrimitive = _CastPrimitive() Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Sat Jan 19 23:13:56 2008 @@ -1,7 +1,7 @@ from pypy.translator.cli.metavm import Call, CallMethod, \ IndirectCall, GetField, SetField, DownCast, NewCustomDict,\ MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\ - TypeOf, CastPrimitive + TypeOf, CastPrimitive, EventHandler from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode from pypy.translator.cli.cts import WEAKREF @@ -43,6 +43,7 @@ 'cli_setelem': [SetArrayElem], 'cli_typeof': [TypeOf], 'cli_arraylength': 'ldlen', + 'cli_eventhandler': [EventHandler], 'oois': 'ceq', 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not, 'instanceof': [CastTo, 'ldnull', 'cgt.un'], Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Sat Jan 19 23:13:56 2008 @@ -7,7 +7,7 @@ from pypy.translator.cli.test.runtest import CliTest from pypy.translator.cli.dotnet import SomeCliClass, SomeCliStaticMethod,\ NativeInstance, CLR, box, unbox, OverloadingResolver, NativeException,\ - native_exc, new_array, init_array, typeof + native_exc, new_array, init_array, typeof, eventhandler System = CLR.System Math = CLR.System.Math @@ -417,6 +417,23 @@ res = self.interpret(fn, [], backendopt=False) assert res is True + def test_delegate(self): + class Foo: + def __init__(self): + self.x = 0 + def m(self, sender, args): + self.x = 42 + + def fn(flag): + f = Foo() + if flag: + f.m(None, None) + delegate = eventhandler(f.m) + delegate.Invoke(None, None) + return f.x + res = self.interpret(fn, [False]) + assert res == 42 + class TestPythonnet(TestDotnetRtyping): # don't interpreter functions but execute them directly through pythonnet def interpret(self, f, args, backendopt='ignored'): From arigo at codespeak.net Sun Jan 20 17:01:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 20 Jan 2008 17:01:49 +0100 (CET) Subject: [pypy-svn] r50802 - in pypy/branch/asmgcroot/pypy/translator/c: . test Message-ID: <20080120160149.8201A168510@codespeak.net> Author: arigo Date: Sun Jan 20 17:01:48 2008 New Revision: 50802 Added: pypy/branch/asmgcroot/pypy/translator/c/test/test_trackgcroot.py (contents, props changed) Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Starting unittests for trackgcroot.py. Added: pypy/branch/asmgcroot/pypy/translator/c/test/test_trackgcroot.py ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/test/test_trackgcroot.py Sun Jan 20 17:01:48 2008 @@ -0,0 +1,29 @@ +import py +import sys +from pypy.translator.c.trackgcroot import GcRootTracker, FunctionGcRootTracker +from StringIO import StringIO + + +def test_find_functions(): + source = """\ +\t.p2align 4,,15 +.globl pypy_g_make_tree +\t.type\tpypy_g_make_tree, @function +\tFOO +\t.size\tpypy_g_make_tree, .-pypy_g_make_tree + +\t.p2align 4,,15 +.globl pypy_fn2 +\t.type\tpypy_fn2, @function +\tBAR +\t.size\tpypy_fn2, .-pypy_fn2 +\tMORE STUFF +""" + lines = source.splitlines(True) + parts = list(GcRootTracker().find_functions(iter(lines))) + assert len(parts) == 5 + assert parts[0] == (False, lines[:2]) + assert parts[1] == (True, lines[2:5]) + assert parts[2] == (False, lines[5:8]) + assert parts[3] == (True, lines[8:11]) + assert parts[4] == (False, lines[11:]) Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Sun Jan 20 17:01:48 2008 @@ -87,23 +87,34 @@ for p in state[FIXED:]: print >> output, '\t.long\t%d' % (p,) # gcroots - def process(self, iterlines, newfile, entrypoint='main', filename='?'): - functionlines = None + def find_functions(self, iterlines): + functionlines = [] + in_function = False for line in iterlines: if r_functionstart.match(line): - assert functionlines is None, ( + assert not in_function, ( "missed the end of the previous function") + yield False, functionlines + in_function = True functionlines = [] - if functionlines is not None: - functionlines.append(line) - else: - newfile.write(line) + functionlines.append(line) if r_functionend.match(line): - assert functionlines is not None, ( + assert in_function, ( "missed the start of the current function") + yield True, functionlines + in_function = False + functionlines = [] + assert not in_function, ( + "missed the end of the previous function") + yield False, functionlines + + def process(self, iterlines, newfile, entrypoint='main', filename='?'): + for in_function, lines in self.enum_function(iterlines): + if in_function: self.process_function(functionlines, newfile, entrypoint, filename) - functionlines = None + else: + newfile.writelines(lines) # unmodified def process_function(self, lines, newfile, entrypoint, filename): tracker = FunctionGcRootTracker(lines) From arigo at codespeak.net Sun Jan 20 17:04:46 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 20 Jan 2008 17:04:46 +0100 (CET) Subject: [pypy-svn] r50803 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080120160446.D1B2E168510@codespeak.net> Author: arigo Date: Sun Jan 20 17:04:45 2008 New Revision: 50803 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Typo. Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Sun Jan 20 17:04:45 2008 @@ -111,12 +111,10 @@ def process(self, iterlines, newfile, entrypoint='main', filename='?'): for in_function, lines in self.enum_function(iterlines): if in_function: - self.process_function(functionlines, newfile, entrypoint, - filename) - else: - newfile.writelines(lines) # unmodified + lines = self.process_function(lines, entrypoint, filename) + newfile.writelines(lines) - def process_function(self, lines, newfile, entrypoint, filename): + def process_function(self, lines, entrypoint, filename): tracker = FunctionGcRootTracker(lines) tracker.is_main = tracker.funcname == entrypoint if self.verbose: @@ -130,7 +128,7 @@ fp = tracker.uses_frame_pointer table = self.fixup_entrypoint_table(table, fp) self.gcmaptable.extend(table) - newfile.writelines(tracker.lines) + return tracker.lines def fixup_entrypoint_table(self, table, uses_frame_pointer): self.seen_main = True From arigo at codespeak.net Sun Jan 20 17:05:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 20 Jan 2008 17:05:22 +0100 (CET) Subject: [pypy-svn] r50804 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080120160522.2D0E6168516@codespeak.net> Author: arigo Date: Sun Jan 20 17:05:21 2008 New Revision: 50804 Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Log: Another typo, sorry Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Sun Jan 20 17:05:21 2008 @@ -109,7 +109,7 @@ yield False, functionlines def process(self, iterlines, newfile, entrypoint='main', filename='?'): - for in_function, lines in self.enum_function(iterlines): + for in_function, lines in self.find_functions(iterlines): if in_function: lines = self.process_function(lines, entrypoint, filename) newfile.writelines(lines) From bigdog at codespeak.net Sun Jan 20 17:25:15 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Sun, 20 Jan 2008 17:25:15 +0100 (CET) Subject: [pypy-svn] r50805 - pypy/dist/pypy/config Message-ID: <20080120162515.127CD168414@codespeak.net> Author: bigdog Date: Sun Jan 20 17:25:14 2008 New Revision: 50805 Modified: pypy/dist/pypy/config/pypyoption.py Log: Add "termios" to list of modules removed from working_modules list for windows. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun Jan 20 17:25:14 2008 @@ -32,6 +32,7 @@ del working_modules["fcntl"] del working_modules["readline"] del working_modules["crypt"] + del working_modules["termios"] module_dependencies = {'_ffi': [("objspace.usemodules.struct", True)], From bigdog at codespeak.net Sun Jan 20 17:28:20 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Sun, 20 Jan 2008 17:28:20 +0100 (CET) Subject: [pypy-svn] r50806 - pypy/dist/pypy/rlib Message-ID: <20080120162820.6A72B168510@codespeak.net> Author: bigdog Date: Sun Jan 20 17:28:20 2008 New Revision: 50806 Modified: pypy/dist/pypy/rlib/rmmap.py Log: modify windows specific ComplexCConfig to init local _compilation_info_ from CConfig object was grabbing old sytle __includes Modified: pypy/dist/pypy/rlib/rmmap.py ============================================================================== --- pypy/dist/pypy/rlib/rmmap.py (original) +++ pypy/dist/pypy/rlib/rmmap.py Sun Jan 20 17:28:20 2008 @@ -26,7 +26,7 @@ if _POSIX: includes += ['unistd.h', 'sys/mman.h'] elif _MS_WINDOWS: - includes.append("windows.h") + includes +=['winsock2.h','windows.h'] class CConfig: _compilation_info_ = ExternalCompilationInfo( @@ -125,7 +125,7 @@ elif _MS_WINDOWS: class ComplexCConfig: - _includes_ = CConfig._includes_ + _compilation_info_ =CConfig._compilation_info_ SYSINFO_STRUCT = rffi.CStruct( 'SYSINFO_STRUCT', From fijal at codespeak.net Sun Jan 20 17:53:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Jan 2008 17:53:47 +0100 (CET) Subject: [pypy-svn] r50807 - pypy/dist/pypy/rlib Message-ID: <20080120165347.63C46168510@codespeak.net> Author: fijal Date: Sun Jan 20 17:53:45 2008 New Revision: 50807 Modified: pypy/dist/pypy/rlib/rmmap.py Log: Spaces Modified: pypy/dist/pypy/rlib/rmmap.py ============================================================================== --- pypy/dist/pypy/rlib/rmmap.py (original) +++ pypy/dist/pypy/rlib/rmmap.py Sun Jan 20 17:53:45 2008 @@ -26,7 +26,7 @@ if _POSIX: includes += ['unistd.h', 'sys/mman.h'] elif _MS_WINDOWS: - includes +=['winsock2.h','windows.h'] + includes += ['winsock2.h','windows.h'] class CConfig: _compilation_info_ = ExternalCompilationInfo( @@ -125,7 +125,7 @@ elif _MS_WINDOWS: class ComplexCConfig: - _compilation_info_ =CConfig._compilation_info_ + _compilation_info_ = CConfig._compilation_info_ SYSINFO_STRUCT = rffi.CStruct( 'SYSINFO_STRUCT', From fijal at codespeak.net Sun Jan 20 17:54:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Jan 2008 17:54:47 +0100 (CET) Subject: [pypy-svn] r50808 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080120165447.B3CCA168510@codespeak.net> Author: fijal Date: Sun Jan 20 17:54:47 2008 New Revision: 50808 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: (boring flight) A hack to keep alive all callbacks. Otherwise it segfaults from time to time (not sure how to make it not keep stuff forever) Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Sun Jan 20 17:54:47 2008 @@ -374,6 +374,12 @@ # ____________________________________________________________ +# XXX THIS IS A HACK XXX +# ctypes does not keep callback arguments alive. So we do. Forever +# we need to think deeper how to approach this problem +# additionally, this adds mess to __del__ "semantics" +_all_callbacks = [] + def lltype2ctypes(llobj, normalize=True): """Convert the lltype object 'llobj' to its ctypes equivalent. 'normalize' should only be False in tests, where we want to @@ -404,7 +410,9 @@ return None else: return lltype2ctypes(llres) - return ctypes_func_type(callback) + res = ctypes_func_type(callback) + _all_callbacks.append(res) + return res if T.TO._gckind != 'raw': raise Exception("can only pass 'raw' data structures to C, not %r" From fijal at codespeak.net Sun Jan 20 17:55:55 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 20 Jan 2008 17:55:55 +0100 (CET) Subject: [pypy-svn] r50809 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080120165555.12B6E168510@codespeak.net> Author: fijal Date: Sun Jan 20 17:55:54 2008 New Revision: 50809 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: (boring flight) Support for opaque pointers through C (which are not passed at all :) Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Sun Jan 20 17:55:54 2008 @@ -205,6 +205,63 @@ aroundstate._freeze_() # ____________________________________________________________ +# Few helpers for keeping callback arguments alive +# this makes passing opaque objects possible (they don't even pass +# through C, only integer specifying number passes) + +_KEEPER_CACHE = {} + +def _keeper_for_type(TP): + try: + return _KEEPER_CACHE[TP] + except KeyError: + tp_str = str(TP) # make annotator happy + class KeepaliveKeeper(object): + def __init__(self): + self.stuff_to_keepalive = [] + self.free_positions = [] + + def __del__(self): + # checker + num = len([i for i in self.stuff_to_keepalive if i is not None]) + if num: + print "WARNING! %d elements kept alive for type %s" % \ + (num, tp_str) + keeper = KeepaliveKeeper() + _KEEPER_CACHE[TP] = keeper + return keeper +_keeper_for_type._annspecialcase_ = 'specialize:memo' + +def register_keepalive(obj): + """ Register object obj to be kept alive, + returns a position for that object + """ + keeper = _keeper_for_type(lltype.typeOf(obj)) + if len(keeper.free_positions): + pos = keeper.free_positions.pop() + keeper.stuff_to_keepalive[pos] = obj + return pos + # we don't have any free positions + pos = len(keeper.stuff_to_keepalive) + keeper.stuff_to_keepalive.append(obj) + return pos +register_keepalive._annspecialcase_ = 'specialize:argtype(0)' + +def get_keepalive_object(pos, TP): + keeper = _keeper_for_type(TP) + return keeper.stuff_to_keepalive[pos] +get_keepalive_object._annspecialcase_ = 'specialize:arg(1)' + +def unregister_keepalive(pos, TP): + """ Unregister an object of type TP, stored at position + pos (position previously returned by register_keepalive) + """ + keeper = _keeper_for_type(TP) + keeper.stuff_to_keepalive[pos] = None + keeper.free_positions.append(pos) +unregister_keepalive._annspecialcase_ = 'specialize:arg(1)' + +# ____________________________________________________________ TYPES = [] for _name in 'short int long'.split(): Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Sun Jan 20 17:55:54 2008 @@ -1,6 +1,7 @@ import py from pypy.rpython.lltypesystem.rffi import * +from pypy.rpython.lltypesystem.rffi import _keeper_for_type # crap from pypy.rlib.rposix import get_errno, set_errno from pypy.translator.c.test.test_genc import compile as compile_c from pypy.translator.llvm.test.runtest import compile_function as compile_llvm @@ -412,6 +413,22 @@ fn = self.compile(f, []) assert fn() == 6 + def test_pass_opaque_pointer_via_callback(self): + eating_callback = self.eating_callback() + TP = lltype.Ptr(lltype.GcStruct('X', ('x', lltype.Signed))) + struct = lltype.malloc(TP.TO) # gc structure + struct.x = 8 + + def g(i): + return get_keepalive_object(i, TP).x + + pos = register_keepalive(struct) + assert _keeper_for_type(TP).stuff_to_keepalive[pos] is struct + del struct + res = eating_callback(pos, g) + unregister_keepalive(pos, TP) + assert res == 8 + class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) From antocuni at codespeak.net Sun Jan 20 22:59:45 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 20 Jan 2008 22:59:45 +0100 (CET) Subject: [pypy-svn] r50814 - pypy/dist/pypy/module/clr/test Message-ID: <20080120215945.6A0C01684F1@codespeak.net> Author: antocuni Date: Sun Jan 20 22:59:44 2008 New Revision: 50814 Added: pypy/dist/pypy/module/clr/test/__init__.py (contents, props changed) Modified: pypy/dist/pypy/module/clr/test/test_clr.py pypy/dist/pypy/module/clr/test/test_importer.py Log: skip tests if not using pythonnet Added: pypy/dist/pypy/module/clr/test/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/clr/test/__init__.py Sun Jan 20 22:59:44 2008 @@ -0,0 +1 @@ +# Modified: pypy/dist/pypy/module/clr/test/test_clr.py ============================================================================== --- pypy/dist/pypy/module/clr/test/test_clr.py (original) +++ pypy/dist/pypy/module/clr/test/test_clr.py Sun Jan 20 22:59:44 2008 @@ -1,6 +1,14 @@ from pypy.conftest import gettestobjspace -mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +from pypy.module.clr.assemblyname import mscorlib +def skip_if_not_pythonnet(): + import py + try: + import clr + except ImportError: + py.test.skip('Must use pythonnet to access .NET libraries') + +skip_if_not_pythonnet() class AppTestDotnet: def setup_class(cls): Modified: pypy/dist/pypy/module/clr/test/test_importer.py ============================================================================== --- pypy/dist/pypy/module/clr/test/test_importer.py (original) +++ pypy/dist/pypy/module/clr/test/test_importer.py Sun Jan 20 22:59:44 2008 @@ -1,4 +1,7 @@ from pypy.conftest import gettestobjspace +from pypy.module.clr.test.test_clr import skip_if_not_pythonnet + +skip_if_not_pythonnet() class AppTestDotnet: def setup_class(cls): From fijal at codespeak.net Mon Jan 21 09:50:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 09:50:07 +0100 (CET) Subject: [pypy-svn] r50816 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080121085007.E79B6168526@codespeak.net> Author: fijal Date: Mon Jan 21 09:50:06 2008 New Revision: 50816 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: On rare occasions, allow to pass GcStructs around. Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Mon Jan 21 09:50:06 2008 @@ -414,7 +414,7 @@ _all_callbacks.append(res) return res - if T.TO._gckind != 'raw': + if T.TO._gckind != 'raw' and not T.TO._hints.get('callback', None): raise Exception("can only pass 'raw' data structures to C, not %r" % (T.TO._gckind,)) if container._storage is None: From fijal at codespeak.net Mon Jan 21 09:51:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 09:51:26 +0100 (CET) Subject: [pypy-svn] r50817 - in pypy/dist/pypy/rlib: . test Message-ID: <20080121085126.EA02B168542@codespeak.net> Author: fijal Date: Mon Jan 21 09:51:26 2008 New Revision: 50817 Modified: pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/test/test_libffi.py Log: Yay! libffi callbacks seems to work. And we don't need this fancy keepalive stuff in rffi.py after all. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Mon Jan 21 09:51:26 2008 @@ -113,7 +113,11 @@ FFI_OK = cConfig.FFI_OK FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI) -FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=CConfig._compilation_info_) +FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=CConfig. + _compilation_info_) + +FFI_CLOSUREP = rffi.COpaquePtr('ffi_closure', compilation_info=CConfig. + _compilation_info_) VOIDPP = rffi.CArrayPtr(rffi.VOIDP) @@ -121,6 +125,11 @@ FFI_TYPE_P, FFI_TYPE_PP], rffi.INT) c_ffi_call = external('ffi_call', [FFI_CIFP, rffi.VOIDP, rffi.VOIDP, VOIDPP], lltype.Void) +CALLBACK_TP = rffi.CCallback([FFI_CIFP, rffi.VOIDP, rffi.VOIDPP, rffi.VOIDP], + lltype.Void) +c_ffi_prep_closure = external('ffi_prep_closure', [FFI_CLOSUREP, FFI_CIFP, + CALLBACK_TP, rffi.VOIDP], + rffi.INT) def dlerror(): # XXX this would never work on top of ll2ctypes, because @@ -167,8 +176,16 @@ buf[0] = arg push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)' -def check_pointer_type(TP): - pass +def ll_callback(ffi_cif, ll_res, ll_args, ll_userdata): + """ Callback specification. + ffi_cif - something ffi specific, don't care + ll_args - rffi.VOIDPP - pointer to array of pointers to args + ll_restype - rffi.VOIDP - pointer to result + ll_userdata - a special structure which holds necessary information + (what the real callback is for example), casted to VOIDP + """ + userdata = rffi.cast(USERDATA_P, ll_userdata) + userdata.callback(ll_args, ll_res) class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) @@ -183,11 +200,10 @@ self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw') for i in range(argnum): self.ll_argtypes[i] = argtypes[i] - # XXX why cast to FFI_TYPE_PP is needed? ll2ctypes bug? self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw') res = c_ffi_prep_cif(self.ll_cif, FFI_DEFAULT_ABI, rffi.cast(rffi.UINT, argnum), restype, - rffi.cast(FFI_TYPE_PP, self.ll_argtypes)) + self.ll_argtypes) if not res == FFI_OK: raise OSError(-1, "Wrong typedef") @@ -197,6 +213,32 @@ if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor='raw') +CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP], + lltype.Void)) +USERDATA_P = lltype.Ptr(lltype.GcStruct('userdata', ('callback', CALLBACK_TP), + hints={'callback':True})) + +# as long as CallbackFuncPtr is kept alive, the underlaying userdata +# is kept alive as well +class CallbackFuncPtr(AbstractFuncPtr): + ll_closure = lltype.nullptr(FFI_CLOSUREP.TO) + ll_userdata = lltype.nullptr(USERDATA_P.TO) + + def __init__(self, argtypes, restype, func): + AbstractFuncPtr.__init__(self, "callback", argtypes, restype, None) + self.ll_closure = lltype.malloc(FFI_CLOSUREP.TO, flavor='raw') + self.ll_userdata = lltype.malloc(USERDATA_P.TO) + self.ll_userdata.callback = rffi.llhelper(CALLBACK_TP, func) + res = c_ffi_prep_closure(self.ll_closure, self.ll_cif, + ll_callback, rffi.cast(rffi.VOIDP, + self.ll_userdata)) + if not res == FFI_OK: + raise OSError(-1, "Unspecified error calling ffi_prep_closure") + + def __del__(self): + AbstractFuncPtr.__del__(self) + if self.ll_closure: + lltype.free(self.ll_closure, flavor='raw') class RawFuncPtr(AbstractFuncPtr): Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Mon Jan 21 09:51:26 2008 @@ -109,6 +109,38 @@ del libc assert not ALLOCATED + def test_callback(self): + libc = CDLL('libc.so.6') + qsort = libc.getpointer('qsort', [ffi_type_pointer, ffi_type_slong, + ffi_type_slong, ffi_type_pointer], + ffi_type_void) + + def callback(ll_args, ll_res): + a1 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[0])[0] + a2 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[1])[0] + res = rffi.cast(rffi.INTP, ll_res) + if a1 > a2: + res[0] = 1 + else: + res[0] = -1 + + ptr = CallbackFuncPtr([ffi_type_pointer, ffi_type_pointer], + ffi_type_sint, callback) + + TP = rffi.CArray(rffi.INT) + to_sort = lltype.malloc(TP, 4, flavor='raw') + to_sort[0] = 4 + to_sort[1] = 3 + to_sort[2] = 1 + to_sort[3] = 2 + qsort.push_arg(rffi.cast(rffi.VOIDP, to_sort)) + qsort.push_arg(rffi.sizeof(rffi.INT)) + qsort.push_arg(4) + qsort.push_arg(ptr.ll_closure) + qsort.call(lltype.Void) + assert [to_sort[i] for i in range(4)] == [1,2,3,4] + lltype.free(to_sort, flavor='raw') + def test_compile(self): import py py.test.skip("Segfaulting test, skip") From fijal at codespeak.net Mon Jan 21 09:55:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 09:55:07 +0100 (CET) Subject: [pypy-svn] r50818 - pypy/dist/pypy/jit/hintannotator/test Message-ID: <20080121085507.52F8E168544@codespeak.net> Author: fijal Date: Mon Jan 21 09:55:06 2008 New Revision: 50818 Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Log: Add an exploding test. Not sure if jit should see any rffi stuff. 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 Mon Jan 21 09:55:06 2008 @@ -1073,6 +1073,13 @@ hs = self.hannotate(f, [], policy=P_NOVIRTUAL) assert not hs.is_green() + def test_raw_malloc(self): + py.test.skip("Exploding") + S = lltype.Struct('x', ('x', lltype.Signed)) + def f(): + p = lltype.malloc(S, flavor='raw') + + hs = self.hannotate(f, [], policy=P_NOVIRTUAL) class TestOOType(BaseAnnotatorTest): type_system = 'ootype' From arigo at codespeak.net Mon Jan 21 11:50:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 11:50:51 +0100 (CET) Subject: [pypy-svn] r50819 - in pypy/dist/pypy/rpython/lltypesystem/module: . test Message-ID: <20080121105051.CFB8816857E@codespeak.net> Author: arigo Date: Mon Jan 21 11:50:49 2008 New Revision: 50819 Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py pypy/dist/pypy/rpython/lltypesystem/module/test/test_ll_math.py Log: Consider underflow to not be an error, like CPython. (The "raise OSError" looks like a typo that occurred when ll_math.py was ported from rev 48599 of pypy/translator/c/src/ll_math.h). Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py Mon Jan 21 11:50:49 2008 @@ -53,7 +53,7 @@ if errno: if errno == ERANGE: if not x: - raise OSError + return # we consider underflow to not be an error, like CPython raise OverflowError("math range error") else: raise ValueError("math domain error") Modified: pypy/dist/pypy/rpython/lltypesystem/module/test/test_ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/module/test/test_ll_math.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/module/test/test_ll_math.py Mon Jan 21 11:50:49 2008 @@ -42,3 +42,6 @@ return math.ldexp(x, y) assert self.interpret(f, [3.4, 2]) == f(3.4, 2) + # underflows give 0.0 with no exception raised + assert f(1.0, -10000) == 0.0 # sanity-check the host Python + assert self.interpret(f, [1.0, -10000]) == 0.0 From fijal at codespeak.net Mon Jan 21 12:03:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 12:03:07 +0100 (CET) Subject: [pypy-svn] r50820 - in pypy/dist/pypy/rlib: . test Message-ID: <20080121110307.5B7BB168560@codespeak.net> Author: fijal Date: Mon Jan 21 12:03:06 2008 New Revision: 50820 Modified: pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/test/test_libffi.py Log: Pass around also userdata instance Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Mon Jan 21 12:03:06 2008 @@ -185,7 +185,7 @@ (what the real callback is for example), casted to VOIDP """ userdata = rffi.cast(USERDATA_P, ll_userdata) - userdata.callback(ll_args, ll_res) + userdata.callback(ll_args, ll_res, userdata) class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) @@ -213,10 +213,13 @@ if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor='raw') -CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP], +USERDATA_P = lltype.Ptr(lltype.GcForwardReference()) +CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP, USERDATA_P], lltype.Void)) -USERDATA_P = lltype.Ptr(lltype.GcStruct('userdata', ('callback', CALLBACK_TP), - hints={'callback':True})) +USERDATA_P.TO.become(lltype.GcStruct('userdata', + ('callback', CALLBACK_TP), + ('addarg', rffi.INT), + hints={'callback':True})) # as long as CallbackFuncPtr is kept alive, the underlaying userdata # is kept alive as well @@ -224,11 +227,12 @@ ll_closure = lltype.nullptr(FFI_CLOSUREP.TO) ll_userdata = lltype.nullptr(USERDATA_P.TO) - def __init__(self, argtypes, restype, func): + def __init__(self, argtypes, restype, func, additional_arg=0): AbstractFuncPtr.__init__(self, "callback", argtypes, restype, None) self.ll_closure = lltype.malloc(FFI_CLOSUREP.TO, flavor='raw') self.ll_userdata = lltype.malloc(USERDATA_P.TO) self.ll_userdata.callback = rffi.llhelper(CALLBACK_TP, func) + self.ll_userdata.addarg = additional_arg res = c_ffi_prep_closure(self.ll_closure, self.ll_cif, ll_callback, rffi.cast(rffi.VOIDP, self.ll_userdata)) Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Mon Jan 21 12:03:06 2008 @@ -115,7 +115,7 @@ ffi_type_slong, ffi_type_pointer], ffi_type_void) - def callback(ll_args, ll_res): + def callback(ll_args, ll_res, stuff): a1 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[0])[0] a2 = rffi.cast(rffi.INTP, rffi.cast(rffi.VOIDPP, ll_args[0])[1])[0] res = rffi.cast(rffi.INTP, ll_res) From antocuni at codespeak.net Mon Jan 21 12:34:57 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Jan 2008 12:34:57 +0100 (CET) Subject: [pypy-svn] r50821 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20080121113457.994AB1684E1@codespeak.net> Author: antocuni Date: Mon Jan 21 12:34:55 2008 New Revision: 50821 Modified: pypy/dist/pypy/translator/cli/dotnet.py pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/query.py pypy/dist/pypy/translator/cli/rte.py pypy/dist/pypy/translator/cli/src/query.cs pypy/dist/pypy/translator/cli/support.py pypy/dist/pypy/translator/cli/test/test_dotnet.py pypy/dist/pypy/translator/cli/test/test_query.py Log: a big refactoring of query.py. Now info about types are loaded per-assembly instead of per-class, and they are not cached in pypy/_cache; this is much faster, and removes all that crappy [cli:query] logs. Modified: pypy/dist/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/dotnet.py (original) +++ pypy/dist/pypy/translator/cli/dotnet.py Mon Jan 21 12:34:55 2008 @@ -259,6 +259,7 @@ def compute_result_annotation(self): return SomeOOInstance(self.instance._INSTANCE) + class CliNamespace(object): def __init__(self, name): self._name = name @@ -270,23 +271,19 @@ return '%s.%s' % (self._name, name) def __getattr__(self, attr): - from pypy.translator.cli.query import load_class_or_namespace - # .NET namespace are not self-entities but just parts of the - # FullName of a class. This imply that there is no way ask - # .NET if a particular name is a namespace; there are many - # names that are clearly not namespaces such as im_self and - # _freeze_, but there is no general rule and we have to guess. - # For now, the heuristic simply check is the first char of the - # name is a UPPERCASE letter. + from pypy.translator.cli.query import get_cli_class, Types, Namespaces + from pypy.translator.cli.query import load_assembly, mscorlib + load_assembly(mscorlib) - if attr[0].isalpha() and attr[0] == attr[0].upper(): - # we assume it's a class or namespace - name = self.__fullname(attr) - load_class_or_namespace(name) - assert attr in self.__dict__ - return getattr(self, attr) + fullname = self.__fullname(attr) + if fullname in Namespaces: + value = CliNamespace(fullname) + elif fullname in Types: + value = get_cli_class(fullname) else: - raise AttributeError + raise AttributeError, attr + setattr(self, attr, value) + return value CLR = CliNamespace(None) @@ -421,7 +418,7 @@ return res def _create_NativeException(cliClass): - from pypy.translator.cli.query import getattr_ex + from pypy.translator.cli.support import getattr_ex TYPE = cliClass._INSTANCE if PythonNet.__name__ in ('CLR', 'clr'): # we are using pythonnet -- use the .NET class @@ -461,12 +458,12 @@ _about_ = new_array def compute_result_annotation(self, type_s, length_s): - from pypy.translator.cli.query import load_class_maybe + from pypy.translator.cli.query import get_cli_class assert type_s.is_constant() assert isinstance(length_s, SomeInteger) TYPE = type_s.const._INSTANCE fullname = '%s.%s[]' % (TYPE._namespace, TYPE._classname) - cliArray = load_class_maybe(fullname) + cliArray = get_cli_class(fullname) return SomeOOInstance(cliArray._INSTANCE) def specialize_call(self, hop): @@ -479,7 +476,7 @@ _about_ = init_array def compute_result_annotation(self, type_s, *args_s): - from pypy.translator.cli.query import load_class_maybe + from pypy.translator.cli.query import get_cli_class assert type_s.is_constant() TYPE = type_s.const._INSTANCE for i, arg_s in enumerate(args_s): @@ -487,7 +484,7 @@ raise TypeError, 'Wrong type of arg #%d: %s expected, %s found' % \ (i, TYPE, arg_s.ootype) fullname = '%s.%s[]' % (TYPE._namespace, TYPE._classname) - cliArray = load_class_maybe(fullname) + cliArray = get_cli_class(fullname) return SomeOOInstance(cliArray._INSTANCE) def specialize_call(self, hop): @@ -511,9 +508,9 @@ _about_ = typeof def compute_result_annotation(self, cliClass_s): - from query import load_class_maybe + from pypy.translator.cli.query import get_cli_class assert cliClass_s.is_constant() - cliType = load_class_maybe('System.Type') + cliType = get_cli_class('System.Type') return SomeOOInstance(cliType._INSTANCE) def specialize_call(self, hop): Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Mon Jan 21 12:34:55 2008 @@ -17,7 +17,6 @@ from pypy.translator.cli.rte import get_pypy_dll from pypy.translator.cli.support import Tee from pypy.translator.cli.prebuiltnodes import get_prebuilt_nodes -from pypy.translator.cli import query from pypy.translator.cli import constant class GenCli(GenOO): @@ -50,7 +49,6 @@ def generate_source(self): GenOO.generate_source(self) self.db.const_count.dump(self.const_stat) - query.savedesc() return self.tmpfile.strpath def create_assembler(self): Modified: pypy/dist/pypy/translator/cli/query.py ============================================================================== --- pypy/dist/pypy/translator/cli/query.py (original) +++ pypy/dist/pypy/translator/cli/query.py Mon Jan 21 12:34:55 2008 @@ -1,149 +1,147 @@ +import sys import cPickle as pickle import os.path +import py from py.compat import subprocess +from pypy.tool.udir import udir from pypy.rpython.ootypesystem import ootype from pypy.translator.cli.rte import Query from pypy.translator.cli.sdk import SDK from pypy.translator.cli.support import log from pypy.translator.cli.dotnet import CLR, CliNamespace, CliClass,\ NativeInstance, _overloaded_static_meth, _static_meth, OverloadingResolver - -ClassCache = {} -OOTypeCache = {} -Descriptions = {} - -class Dummy: pass -fake_root = Dummy() -fake_root._INSTANCE = ootype.ROOT -ClassCache['ROOT'] = fake_root -ClassCache['System.Array'] = fake_root -del fake_root -del Dummy - -def _descfilename(filename): - if filename is None: - curdir = os.path.dirname(__file__) - return os.path.join(curdir, 'query-descriptions') + +Assemblies = set() +Types = {} # TypeName -> ClassDesc +Namespaces = set() +mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' + +#_______________________________________________________________________________ +# This is the public interface of query.py + +def load_assembly(name): + if name in Assemblies: + return + Query.get() # clear the cache if we need to recompile + _cache = get_cachedir() + outfile = _cache.join(name + '.pickle') + if outfile.check(): + f = outfile.open('rb') + types = pickle.load(f) + f.close() else: - return filename + types = load_and_cache_assembly(name, outfile) -def savedesc(filename=None): - f = open(_descfilename(filename), 'wb') - pickle.dump(Descriptions, f, protocol=-1) + for ttype in types: + parts = ttype.split('.') + ns = parts[0] + Namespaces.add(ns) + for part in parts[1:-1]: + ns = '%s.%s' % (ns, part) + Namespaces.add(ns) + Assemblies.add(name) + Types.update(types) + + +def get_cli_class(name): + desc = get_class_desc(name) + return desc.get_cliclass() + +#_______________________________________________________________________________ + + +def get_cachedir(): + import pypy + _cache = py.path.local(pypy.__file__).new(basename='_cache').ensure(dir=1) + return _cache + +def load_and_cache_assembly(name, outfile): + tmpfile = udir.join(name) + arglist = SDK.runtime() + [Query.get(), name, str(tmpfile)] + retcode = subprocess.call(arglist) + assert retcode == 0 + mydict = {} + execfile(str(tmpfile), mydict) + types = mydict['types'] + f = outfile.open('wb') + pickle.dump(types, f, pickle.HIGHEST_PROTOCOL) f.close() + return types -def loaddesc(filename=None): - filename = _descfilename(filename) - if not os.path.exists(filename): - return - f = open(filename, 'rb') - try: - newdesc = pickle.load(f) - except pickle.UnpicklingError: - log.WARNING('query-descriptions file exits, but failed to unpickle') +def get_ootype(name): + # a bit messy, but works + if name.startswith('ootype.'): + _, name = name.split('.') + return getattr(ootype, name) else: - Descriptions.clear() - Descriptions.update(newdesc) + cliclass = get_cli_class(name) + return cliclass._INSTANCE -def getattr_ex(target, attr): - parts = attr.split('.') - for part in parts: - target = getattr(target, part) - return target - -def setattr_ex(target, attr, value): - if '.' in attr: - namespace, attr = attr.rsplit('.', 1) - target = getattr_ex(target, namespace) - setattr(target, attr, value) - -def load_class_or_namespace(name): - try: - desc = Descriptions[name] - except KeyError: - desc = query_description(name) - Descriptions[name] = desc - res = desc.build() - setattr_ex(CLR, name, res) - return res - -def query_description(name): - log.query('Loading description for %s' % name) - arglist = SDK.runtime() + [Query.get(), name] - query = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True) - stdout, stderr = query.communicate() - retval = query.wait() - if retval == 0: - cls = ClassDesc() - exec stdout in cls.__dict__ - del cls.__dict__['__builtins__'] - return cls - elif retval == 1: - raise RuntimeError, 'query.exe failed with this message:\n%s' % stderr - elif retval == 2: - # can't load type, assume it's a namespace - return NamespaceDesc(name) - -def load_class_maybe(name): - if name.startswith('System.Array+InternalArray'): - res = ClassCache['System.Array'] - ClassCache[name] = res - return res - elif name not in ClassCache: - return load_class_or_namespace(name) +def get_class_desc(name): + if name in Types: + return Types[name] + + if name == 'System.Array': + desc = ClassDesc() + desc.Assembly = mscorlib + desc.FullName = name + desc.BaseType = 'System.Object' + desc.IsArray = True + desc.ElementType = 'System.Object' # not really true, but we need something + desc.StaticMethods = [] + desc.Methods = [] + elif name.endswith('[]'): # it's an array + itemname = name[:-2] + itemdesc = get_class_desc(itemname) + desc = ClassDesc() + desc.Assembly = mscorlib + desc.FullName = name + desc.BaseType = 'System.Array' + desc.ElementType = itemdesc.FullName + desc.IsArray = True + desc.StaticMethods = [] + desc.Methods = [ + ('Get', ['ootype.Signed', ], itemdesc.FullName), + ('Set', ['ootype.Signed', itemdesc.FullName], 'ootype.Void') + ] else: - return ClassCache[name] + assert False, 'Unknown desc' + + Types[name] = desc + return desc + +class ClassDesc(object): + _cliclass = None -class Desc: - def build(self): - raise NotImplementedError - def __eq__(self, other): return self.__dict__ == other.__dict__ def __hash__(self): raise TypeError - -class NamespaceDesc(Desc): - def __init__(self, name): - self.name = name - def build(self): - return CliNamespace(self.name) - -class ClassDesc(Desc): - def build(self): + def get_cliclass(self): + if self._cliclass is not None: + return self._cliclass + assert self.Assembly.startswith('mscorlib') # TODO: support external assemblies namespace, name = self.FullName.rsplit('.', 1) # construct OOTYPE and CliClass - if self.FullName == 'System.Type': - # we need to special case System.Type because it contains - # circular dependencies, since its superclasses have got - # methods which take System.Type as parameters - BASETYPE = None - else: - load_class_maybe(self.BaseType) - BASETYPE = ClassCache[self.BaseType]._INSTANCE - TYPE = NativeInstance('[mscorlib]', namespace, name, BASETYPE, {}, {}) - TYPE._isArray = self.IsArray - if self.IsArray: - load_class_maybe(self.ElementType) - TYPE._ELEMENT = ClassCache[self.ElementType]._INSTANCE + # no superclass for now, will add it later + TYPE = NativeInstance('[mscorlib]', namespace, name, None, {}, {}) Class = CliClass(TYPE, {}) - OOTypeCache[self.OOType] = TYPE - ClassCache[self.FullName] = Class - - if BASETYPE is None: - load_class_maybe(self.BaseType) - BASETYPE = ClassCache[self.BaseType]._INSTANCE + self._cliclass = Class + # we need to check also for System.Array to prevent a circular recursion + if self.FullName in ('System.Object', 'System.Array'): + TYPE._set_superclass(ootype.ROOT) + else: + BASETYPE = get_ootype(self.BaseType) TYPE._set_superclass(BASETYPE) - # render dependencies - for name in self.Depend: - load_class_maybe(name) + TYPE._isArray = self.IsArray + if self.IsArray: + TYPE._ELEMENT = get_ootype(self.ElementType) # add both static and instance methods static_meths = self.group_methods(self.StaticMethods, _overloaded_static_meth, @@ -167,17 +165,6 @@ return res def get_method_type(self, Meth, args, result): - ARGS = [self.get_ootype(arg) for arg in args] - RESULT = self.get_ootype(result) + ARGS = [get_ootype(arg) for arg in args] + RESULT = get_ootype(result) return Meth(ARGS, RESULT) - - def get_ootype(self, t): - # a bit messy, but works - if t.startswith('ootype.'): - _, name = t.split('.') - return getattr(ootype, name) - else: - return OOTypeCache[t] - - -loaddesc() ## automatically loads the cached Dependencies Modified: pypy/dist/pypy/translator/cli/rte.py ============================================================================== --- pypy/dist/pypy/translator/cli/rte.py (original) +++ pypy/dist/pypy/translator/cli/rte.py Mon Jan 21 12:34:55 2008 @@ -95,10 +95,10 @@ def compile(cls, sources, out): # assume that if query.exe need to be recompiled the descriptions cache is invalid - from pypy.translator.cli.query import _descfilename - filename = _descfilename(None) - if os.path.exists(filename): - os.remove(filename) + from pypy.translator.cli.query import get_cachedir, mscorlib + mscorlib_cache = get_cachedir().join(mscorlib + '.pickle') + if mscorlib_cache.check(): + mscorlib_cache.remove() Target.compile.im_func(cls, sources, out) compile = classmethod(compile) Modified: pypy/dist/pypy/translator/cli/src/query.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/query.cs (original) +++ pypy/dist/pypy/translator/cli/src/query.cs Mon Jan 21 12:34:55 2008 @@ -1,53 +1,73 @@ using System; +using System.IO; using System.Reflection; using System.Collections.Generic; public class Query { - public static Dictionary PendingTypes = new Dictionary(); + private static StreamWriter outfile = null; public static int Main(string[] argv) { - if (argv.Length != 1) { - Console.Error.WriteLine("Usage: query full-qualified-name"); + if (argv.Length != 2) { + Console.Error.WriteLine("Usage: query assembly-name output-file"); return 1; } string name = argv[0]; - Type t = Type.GetType(name); - if (t == null) { - Console.Error.WriteLine("Cannot load type {0}", name); + string outname = argv[1]; + Assembly ass; + try { + ass = Assembly.Load(name); + } + catch(System.IO.IOException e) { + Console.Error.WriteLine("Cannot load assembly {0}: {1}", name, e.Message); return 2; } - if (!t.IsPublic) { - Console.Error.WriteLine("Cannot load a non-public type"); - return 2; + try { + outfile = new StreamWriter(outname); } - - PrintType(t); + catch(System.IO.IOException e) { + Console.Error.WriteLine("Cannot open file {0}: {1}", outname, e.Message); + return 3; + } + + PrintAssembly(ass); + outfile.Close(); return 0; } + private static void PrintAssembly(Assembly ass) + { + Type[] types = ass.GetTypes(); + outfile.WriteLine("# This file has been autogenerated by query.exe -- DO NOT EDIT"); + outfile.WriteLine("from pypy.translator.cli.query import ClassDesc"); + outfile.WriteLine("types = {}"); + foreach(Type t in types) { + if (IgnoreType(t)) + continue; + PrintType(t); + outfile.WriteLine("types['{0}'] = desc", t.FullName); + outfile.WriteLine("del desc"); + } + } + private static void PrintType(Type t) { - Console.WriteLine("Assembly = '{0}'", t.Assembly.FullName); - Console.WriteLine("FullName = '{0}'", t.FullName); - Console.WriteLine("BaseType = '{0}'", GetBaseType(t)); - Console.WriteLine("OOType = '{0}'", GetOOType(t)); - Console.WriteLine("IsArray = {0}", t.IsArray); - if (t.IsArray) - Console.WriteLine("ElementType = '{0}'", t.GetElementType().FullName); - PrintMethods("StaticMethods", t.GetMethods(BindingFlags.Static|BindingFlags.Public|BindingFlags.DeclaredOnly)); - PrintMethods("Methods", t.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.DeclaredOnly)); - PendingTypes.Remove(t); - PrintDepend(); + outfile.WriteLine("desc = ClassDesc()"); + outfile.WriteLine("desc.Assembly = '{0}'", t.Assembly.FullName); + outfile.WriteLine("desc.FullName = '{0}'", t.FullName); + outfile.WriteLine("desc.BaseType = '{0}'", GetBaseType(t)); + outfile.WriteLine("desc.IsArray = {0}", t.IsArray); + PrintMethods("desc.StaticMethods", t.GetMethods(BindingFlags.Static|BindingFlags.Public|BindingFlags.DeclaredOnly)); + PrintMethods("desc.Methods", t.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.DeclaredOnly)); } private static string GetBaseType(Type t) { if (t == typeof(object)) - return "ROOT"; // special case for System.Object to avoid circular dependencies + return "System.Object"; // special case for System.Object to avoid circular dependencies else if (t.BaseType == null) return "System.Object"; // the only known case is the BaseType of an interface else @@ -77,29 +97,25 @@ else if (t == typeof(string)) return "ootype.String"; else { - PendingTypes[t] = true; - string name = t.FullName.Replace(".", "_"); // TODO: ensure unicity - if (t.IsArray) - name = name.Replace("[]", "___array___"); - return name; + return t.FullName; } } private static void PrintMethods(string varname, MethodInfo[] methods) { - Console.WriteLine("{0} = [", varname); + outfile.WriteLine("{0} = [", varname); // MethodName, [ARGS], RESULT foreach(MethodInfo meth in methods) { if (IgnoreMethod(meth)) continue; - Console.Write(" ('{0}', [", meth.Name); + outfile.Write(" ('{0}', [", meth.Name); foreach(ParameterInfo par in meth.GetParameters()) { - Console.Write("'{0}'", GetOOType(par.ParameterType)); - Console.Write(", "); + outfile.Write("'{0}'", GetOOType(par.ParameterType)); + outfile.Write(", "); } - Console.WriteLine("], '{0}'),", GetOOType(meth.ReturnType)); + outfile.WriteLine("], '{0}'),", GetOOType(meth.ReturnType)); } - Console.WriteLine(" ]"); + outfile.WriteLine(" ]"); } private static bool IgnoreMethod(MethodInfo meth) @@ -124,21 +140,13 @@ { return !t.IsPrimitive && t != typeof(void) - &&(t == typeof(System.ValueType) || - t == typeof(System.Array) || + &&(t == typeof(System.Array) || + t.FullName == null || t.FullName.StartsWith("System.Array+InternalArray") || - t.IsValueType || + t.IsNotPublic || t.IsByRef || t.IsPointer || t.IsGenericType || t.IsGenericTypeDefinition); } - - private static void PrintDepend() - { - Console.Write("Depend = ["); - foreach(Type t in PendingTypes.Keys) - Console.Write("'{0}', ", t.FullName); - Console.WriteLine("]"); - } } Modified: pypy/dist/pypy/translator/cli/support.py ============================================================================== --- pypy/dist/pypy/translator/cli/support.py (original) +++ pypy/dist/pypy/translator/cli/support.py Mon Jan 21 12:34:55 2008 @@ -66,3 +66,14 @@ f.write('%s: %d\n' % (label, self.counters[key])) f.close() +def getattr_ex(target, attr): + parts = attr.split('.') + for part in parts: + target = getattr(target, part) + return target + +def setattr_ex(target, attr, value): + if '.' in attr: + namespace, attr = attr.rsplit('.', 1) + target = getattr_ex(target, namespace) + setattr(target, attr, value) Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Mon Jan 21 12:34:55 2008 @@ -349,6 +349,7 @@ assert res.startswith("Index is less than 0") def test_typeof(self): + System.Int32 # force Int32 to be loaded def fn(): x = box(42) return x.GetType() == typeof(System.Int32) Modified: pypy/dist/pypy/translator/cli/test/test_query.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_query.py (original) +++ pypy/dist/pypy/translator/cli/test/test_query.py Mon Jan 21 12:34:55 2008 @@ -1,16 +1,21 @@ +import py from pypy.translator.cli import query from pypy.translator.cli.dotnet import CLR, CliNamespace -def test_load_namespace_simple(): - query.load_class_or_namespace('System') - assert isinstance(CLR.System, CliNamespace) - assert CLR.System._name == 'System' +def setup_module(module): + from pypy.translator.cli.query import load_assembly, mscorlib + load_assembly(mscorlib) + +def test_load_assembly(): + query.load_assembly(query.mscorlib) + assert 'System.Math' in query.Types + assert 'System.Collections.ArrayList' in query.Types -def test_load_namespace_complex(): - query.load_class_or_namespace('System.Collections') - assert isinstance(CLR.System, CliNamespace) - assert isinstance(CLR.System.Collections, CliNamespace) +def test_namespaces(): + assert CLR.System._name == 'System' assert CLR.System.Collections._name == 'System.Collections' + py.test.raises(AttributeError, getattr, CLR, 'Foo') + py.test.raises(AttributeError, getattr, CLR.System, 'Foo') def test_CLR_getattr(): System = CLR.System @@ -25,17 +30,6 @@ assert 'ToString' in Object._INSTANCE._methods def test_array(): - query.load_class_or_namespace('System.Object[]') - cls = query.ClassCache['System.Object[]'] + cls = query.get_cli_class('System.Object[]') assert cls._INSTANCE._isArray assert cls._INSTANCE._ELEMENT is CLR.System.Object._INSTANCE - -def test_savedesc(): - from pypy.tool.udir import udir - CLR.System.Object # force System.Object to be loaded - olddesc = query.Descriptions.copy() - tmpfile = str(udir.join('descriptions')) - query.savedesc(tmpfile) - query.Descriptions.clear() - query.loaddesc(tmpfile) - assert query.Descriptions == olddesc From fijal at codespeak.net Mon Jan 21 12:42:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 12:42:45 +0100 (CET) Subject: [pypy-svn] r50822 - pypy/dist/pypy/module/pypyjit Message-ID: <20080121114245.CF24D16853D@codespeak.net> Author: fijal Date: Mon Jan 21 12:42:45 2008 New Revision: 50822 Modified: pypy/dist/pypy/module/pypyjit/portal.py Log: Don't go into nanos either Modified: pypy/dist/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/dist/pypy/module/pypyjit/portal.py (original) +++ pypy/dist/pypy/module/pypyjit/portal.py Mon Jan 21 12:42:45 2008 @@ -20,6 +20,8 @@ if mod.startswith('pypy.module.'): if not mod.startswith('pypy.module.pypyjit.'): return False + if mod.startswith('pypy.translator.goal.nanos'): + return False if mod in forbidden_modules: return False if func.__name__.startswith('_mm_') or '_mth_mm_' in func.__name__: From fijal at codespeak.net Mon Jan 21 12:48:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 12:48:51 +0100 (CET) Subject: [pypy-svn] r50823 - pypy/dist/pypy/module/_rawffi Message-ID: <20080121114851.5B8F516853D@codespeak.net> Author: fijal Date: Mon Jan 21 12:48:50 2008 New Revision: 50823 Modified: pypy/dist/pypy/module/_rawffi/array.py Log: Simplify code Modified: pypy/dist/pypy/module/_rawffi/array.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/array.py (original) +++ pypy/dist/pypy/module/_rawffi/array.py Mon Jan 21 12:48:50 2008 @@ -17,12 +17,12 @@ def push_elem(ll_array, pos, value): TP = lltype.typeOf(value) - ll_array = rffi.cast(lltype.Ptr(rffi.CArray(TP)), ll_array) + ll_array = rffi.cast(rffi.CArrayPtr(TP), ll_array) ll_array[pos] = value push_elem._annspecialcase_ = 'specialize:argtype(2)' def get_elem(ll_array, pos, ll_t): - ll_array = rffi.cast(lltype.Ptr(rffi.CArray(ll_t)), ll_array) + ll_array = rffi.cast(rffi.CArrayPtr(ll_t), ll_array) return ll_array[pos] get_elem._annspecialcase_ = 'specialize:arg(2)' From arigo at codespeak.net Mon Jan 21 13:10:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 13:10:13 +0100 (CET) Subject: [pypy-svn] r50824 - in pypy/dist/pypy: interpreter module/__builtin__ module/_file module/_socket module/_weakref Message-ID: <20080121121013.95E7816855B@codespeak.net> Author: arigo Date: Mon Jan 21 13:10:12 2008 New Revision: 50824 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/__builtin__/interp_classobj.py pypy/dist/pypy/module/_file/interp_file.py pypy/dist/pypy/module/_socket/interp_socket.py pypy/dist/pypy/module/_weakref/interp__weakref.py Log: Add logic for built-in objects to make sure that all the weakrefs to them are cleared before the rest of their __del__ methods run. This showed up in pypy-c-boehm runs of lib-python/modified-2.4.1/test/test_file.py, where a weakref to a file could sometimes still be alive after the file was closed by its __del__. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Jan 21 13:10:12 2008 @@ -117,6 +117,23 @@ raise OperationError(space.w_TypeError, space.wrap( "cannot create weak reference to '%s' object" % typename)) + def clear_all_weakrefs(self): + """Call this at the beginning of interp-level __del__() methods + in subclasses. It ensures that weakrefs (if any) are cleared + before the object is further destroyed. + """ + lifeline = self.getweakref() + if lifeline is not None: + # Clear all weakrefs to this object before we proceed with + # the destruction of the object. We detach the lifeline + # first: if the code following before_del() calls the + # app-level, e.g. a user-defined __del__(), and this code + # tries to use weakrefs again, it won't reuse the broken + # (already-cleared) weakrefs from this lifeline. + self.setweakref(lifeline.space, None) + lifeline.clear_all_weakrefs() + + 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().""" Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon Jan 21 13:10:12 2008 @@ -149,15 +149,7 @@ parent_destructor = getattr(cls, '__del__', None) class Proto(object): def __del__(self): - lifeline = self.getweakref() - if lifeline is not None: - # Clear all weakrefs to this object before we call - # the app-level __del__. We detach the lifeline - # first: if the app-level __del__ tries to use - # weakrefs again, they won't reuse the broken - # (already-cleared) ones from this lifeline. - self.setweakref(self.space, None) - lifeline.clear_all_weakrefs() + self.clear_all_weakrefs() try: self.space.userdel(self) except OperationError, e: @@ -546,6 +538,12 @@ weakref_descr.name = '__weakref__' def make_weakref_descr(cls): + """Make instances of the Wrappable subclass 'cls' weakrefable. + This returns the '__weakref__' desctriptor to use for the TypeDef. + Note that if the class also defines a custom '__del__', the + __del__ should call self.clear_all_weakrefs() before it clears + the resources used by the object. + """ # force the interface into the given cls def getweakref(self): return self._lifeline_ Modified: pypy/dist/pypy/module/__builtin__/interp_classobj.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/interp_classobj.py (original) +++ pypy/dist/pypy/module/__builtin__/interp_classobj.py Mon Jan 21 13:10:12 2008 @@ -694,19 +694,8 @@ ) class W_InstanceObjectWithDel(W_InstanceObject): - # XXX this is code duplication from pypy.interpreter.typedef - # find a way to prevent this. def __del__(self): - - lifeline = self.getweakref() - if lifeline is not None: - # Clear all weakrefs to this object before we call - # the app-level __del__. We detach the lifeline - # first: if the app-level __del__ tries to use - # weakrefs again, they won't reuse the broken - # (already-cleared) ones from this lifeline. - self.setweakref(self.space, None) - lifeline.clear_all_weakrefs() + self.clear_all_weakrefs() try: self.descr_del() except OperationError, e: Modified: pypy/dist/pypy/module/_file/interp_file.py ============================================================================== --- pypy/dist/pypy/module/_file/interp_file.py (original) +++ pypy/dist/pypy/module/_file/interp_file.py Mon Jan 21 13:10:12 2008 @@ -33,6 +33,7 @@ def __del__(self): # assume that the file and stream objects are only visible in the # thread that runs __del__, so no race condition should be possible + self.clear_all_weakrefs() self.direct_close() def fdopenstream(self, stream, fd, mode, name): Modified: pypy/dist/pypy/module/_socket/interp_socket.py ============================================================================== --- pypy/dist/pypy/module/_socket/interp_socket.py (original) +++ pypy/dist/pypy/module/_socket/interp_socket.py Mon Jan 21 13:10:12 2008 @@ -22,6 +22,10 @@ return space.str_w(w_obj) class W_RSocket(Wrappable, RSocket): + def __del__(self): + self.clear_all_weakrefs() + self.close() + def accept_w(self, space): """accept() -> (socket object, address info) Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/interp__weakref.py (original) +++ pypy/dist/pypy/module/_weakref/interp__weakref.py Mon Jan 21 13:10:12 2008 @@ -8,7 +8,8 @@ class WeakrefLifeline(object): - def __init__(self): + def __init__(self, space): + self.space = space # this is here for W_Root.clear_all_weakrefs() self.refs_weak = [] self.cached_weakref_index = -1 self.cached_proxy_index = -1 @@ -145,7 +146,7 @@ def descr__new__weakref(space, w_subtype, w_obj, w_callable=None): lifeline = w_obj.getweakref() if lifeline is None: - lifeline = WeakrefLifeline() + lifeline = WeakrefLifeline(space) w_obj.setweakref(space, lifeline) return lifeline.get_or_make_weakref(space, w_subtype, w_obj, w_callable) @@ -218,7 +219,7 @@ is about to be finalized.""" lifeline = w_obj.getweakref() if lifeline is None: - lifeline = WeakrefLifeline() + lifeline = WeakrefLifeline(space) w_obj.setweakref(space, lifeline) return lifeline.get_or_make_proxy(space, w_obj, w_callable) From arigo at codespeak.net Mon Jan 21 13:10:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 13:10:20 +0100 (CET) Subject: [pypy-svn] r50825 - pypy/dist/pypy/module/_file/test Message-ID: <20080121121020.7C71516856E@codespeak.net> Author: arigo Date: Mon Jan 21 13:10:20 2008 New Revision: 50825 Modified: pypy/dist/pypy/module/_file/test/test_file_extra.py Log: Test for previous checkin. Modified: pypy/dist/pypy/module/_file/test/test_file_extra.py ============================================================================== --- pypy/dist/pypy/module/_file/test/test_file_extra.py (original) +++ pypy/dist/pypy/module/_file/test/test_file_extra.py Mon Jan 21 13:10:20 2008 @@ -522,6 +522,26 @@ assert f.tell() == 5 f.close() + def test_weakref_dies_before_file_closes(self): + # Hard-to-reproduce failure (which should now be fixed). + # I think that this is how lib-python/modified-2.4.1/test_file.py + # sometimes failed on a Boehm pypy-c. + import weakref, gc + fn = self.temptestfile + f = open(fn, 'wb') + f.close() + f = open(fn, 'rb') + ref = weakref.ref(f) + attempts = range(10) + del f + for i in attempts: + f1 = ref() + if f1 is None: + break # all gone + assert not f1.closed # if still reachable, should be still open + del f1 + gc.collect() + def test_ValueError(self): fn = self.temptestfile f = open(fn, 'wb') From arigo at codespeak.net Mon Jan 21 13:10:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 13:10:51 +0100 (CET) Subject: [pypy-svn] r50826 - pypy/dist/pypy/objspace/std Message-ID: <20080121121051.0ACAD16855B@codespeak.net> Author: arigo Date: Mon Jan 21 13:10:50 2008 New Revision: 50826 Modified: pypy/dist/pypy/objspace/std/unicodetype.py Log: Rename keyword argument for unicode(). Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Mon Jan 21 13:10:50 2008 @@ -241,11 +241,12 @@ return unicode_from_encoded_object(space, w_str, "ascii", "strict") -def descr__new__(space, w_unicodetype, w_obj='', w_encoding=None, w_errors=None): +def descr__new__(space, w_unicodetype, w_string='', w_encoding=None, w_errors=None): # NB. the default value of w_obj is really a *wrapped* empty string: # there is gateway magic at work from pypy.objspace.std.unicodeobject import W_UnicodeObject from pypy.objspace.std.ropeunicodeobject import W_RopeUnicodeObject + w_obj = w_string w_obj_type = space.type(w_obj) encoding, errors = _get_encoding_and_errors(space, w_encoding, w_errors) From arigo at codespeak.net Mon Jan 21 13:14:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 13:14:05 +0100 (CET) Subject: [pypy-svn] r50827 - in pypy/dist/pypy: interpreter module/_file/test Message-ID: <20080121121405.235DF16855B@codespeak.net> Author: arigo Date: Mon Jan 21 13:14:04 2008 New Revision: 50827 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/_file/test/test_file_extra.py Log: We forgot to expose the __doc__ of GetSetProperty. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon Jan 21 13:14:04 2008 @@ -411,6 +411,7 @@ GetSetProperty, W_Root]), __name__ = interp_attrproperty('name', cls=GetSetProperty), __objclass__ = GetSetProperty(GetSetProperty.descr_get_objclass), + __doc__ = interp_attrproperty('doc', cls=GetSetProperty), ) Modified: pypy/dist/pypy/module/_file/test/test_file_extra.py ============================================================================== --- pypy/dist/pypy/module/_file/test/test_file_extra.py (original) +++ pypy/dist/pypy/module/_file/test/test_file_extra.py Mon Jan 21 13:14:04 2008 @@ -561,3 +561,6 @@ raises(ValueError, iter, f) raises(ValueError, f.xreadlines) f.close() # accepted as a no-op + + def test_docstrings(self): + assert file.closed.__doc__ == 'True if the file is closed' From fijal at codespeak.net Mon Jan 21 13:16:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 13:16:22 +0100 (CET) Subject: [pypy-svn] r50828 - pypy/dist/pypy/module/_rawffi Message-ID: <20080121121622.034A716855B@codespeak.net> Author: fijal Date: Mon Jan 21 13:16:22 2008 New Revision: 50828 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py Log: Kill dead code Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Mon Jan 21 13:16:22 2008 @@ -14,11 +14,6 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import intmask, r_uint -class FfiValueError(Exception): - def __init__(self, msg): - self.msg = msg - - def _signed_type_for(TYPE): sz = rffi.sizeof(TYPE) if sz == 4: return ffi_type_sint32 From fijal at codespeak.net Mon Jan 21 13:17:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 13:17:07 +0100 (CET) Subject: [pypy-svn] r50829 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080121121707.CEF0516855B@codespeak.net> Author: fijal Date: Mon Jan 21 13:17:07 2008 New Revision: 50829 Modified: pypy/dist/pypy/module/_rawffi/__init__.py pypy/dist/pypy/module/_rawffi/callback.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: Support for _rawffi callbacks (not sure how keepalive stuff will look like, for now it's a bit crappy) Modified: pypy/dist/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/__init__.py (original) +++ pypy/dist/pypy/module/_rawffi/__init__.py Mon Jan 21 13:17:07 2008 @@ -19,7 +19,7 @@ 'sizeof' : 'interp_rawffi.sizeof', 'alignment' : 'interp_rawffi.alignment', 'charp2string' : 'interp_rawffi.charp2string', - #'CallbackPtr' : 'callback.W_CallbackPtr', + 'CallbackPtr' : 'callback.W_CallbackPtr', } appleveldefs = { Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Mon Jan 21 13:17:07 2008 @@ -5,27 +5,62 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.module._rawffi.structure import unpack_fields +from pypy.module._rawffi.array import get_elem +from pypy.module._rawffi.interp_rawffi import W_DataInstance, _get_type_,\ + wrap_value, unwrap_value, unwrap_truncate_int +from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr -def stuff(a, b): - print "comparing" - return int(a > b) +def callback(ll_args, ll_res, ll_userdata): + userdata = rffi.cast(USERDATA_P, ll_userdata) + callback_ptr = W_CallbackPtr.CallbackPtr_by_number[userdata.addarg] + w_callable = callback_ptr.w_callable + res = rffi.cast(rffi.VOIDPP, ll_res) + argtypes = callback_ptr.args + space = callback_ptr.space + w_args = space.newlist([wrap_value(space, get_elem, ll_args[i], 0, + (argtypes[i], None, None)) + for i in range(len(argtypes))]) + w_res = space.call(w_callable, w_args) + if space.is_w(w_res, space.w_None): + res[0] = lltype.nullptr(rffi.VOIDP.TO) + else: + instance = space.interpclass_w(w_res) + if isinstance(instance, W_DataInstance): + res[0] = instance.ll_buffer + else: + res[0] = unwrap_truncate_int(rffi.VOIDP, space, w_res) -class W_CallbackPtr(Wrappable): +class W_CallbackPtr(W_DataInstance): + # XXX some weird hackery to be able to recover W_CallbackPtr object + # out of number + CallbackPtr_by_number = {} + CallbackPtr_id = 0 + def __init__(self, space, w_callable, w_args, w_result): + number = self.CallbackPtr_id + self.CallbackPtr_id += 1 + self.CallbackPtr_by_number[number] = self + self.space = space self.w_callable = w_callable + self.number = number self.args = [space.str_w(w_arg) for w_arg in space.unpackiterable( w_args)] + self.result = space.str_w(w_result) + ffiargs = [_get_type_(space, arg) for arg in self.args] + ffiresult = _get_type_(space, self.result) + # necessary to keep stuff alive + self.ll_callback = CallbackFuncPtr(ffiargs, ffiresult, + callback, number) + self.ll_buffer = self.ll_callback.ll_closure - def getllfuncptr(space, self): - TP = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) - ptr = lltype.functionptr(TP, stuff) - return space.wrap(rffi.cast(rffi.Unsigned, ptr)) + def __del__(self): + del self.CallbackPtr_by_number[self.number] def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result): return W_CallbackPtr(space, w_callable, w_args, w_result) W_CallbackPtr.typedef = TypeDef( 'CallbackPtr', - buffer = GetSetProperty(W_CallbackPtr.getllfuncptr), __new__ = interp2app(descr_new_callbackptr), + byptr = interp2app(W_CallbackPtr.byptr), ) Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Mon Jan 21 13:17:07 2008 @@ -359,18 +359,32 @@ arg1.free() def test_callback(self): - skip("Not working") import _rawffi + import struct libc = _rawffi.CDLL('libc.so.6') - to_sort = "kljhgfa" - ll_to_sort = _rawffi.Array('c')(to_sort) + ll_to_sort = _rawffi.Array('i')(4) + for i in range(4): + ll_to_sort[i] = 4-i qsort = libc.ptr('qsort', ['P', 'i', 'i', 'P'], None) + resarray = _rawffi.Array('i')(1) def compare(a, b): - return a < b - qsort(ll_to_sort, len(to_sort), 1, - _rawffi.CallbackPtr(compare, ['i', 'i'], 'i')) - res = [ll_to_sort[i] for i in range(len(to_sort))] - assert res == sorted(to_sort) + a1 = _rawffi.Array('i').fromaddress(a, 1) + a2 = _rawffi.Array('i').fromaddress(b, 1) + if a1[0] > a2[0]: + res = 1 + res = -1 + resarray[0] = res + return resarray + a1 = ll_to_sort.byptr() + a2 = _rawffi.Array('i')(1) + a2[0] = len(ll_to_sort) + a3 = _rawffi.Array('i')(1) + a3[0] = struct.calcsize('i') + cb = _rawffi.CallbackPtr(compare, ['P', 'P'], 'i') + a4 = cb.byptr() + qsort(a1, a2, a3, a4) + res = [ll_to_sort[i] for i in range(len(ll_to_sort))] + assert res == [1,2,3,4] def test_setattr_struct(self): import _rawffi From arigo at codespeak.net Mon Jan 21 13:44:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 13:44:52 +0100 (CET) Subject: [pypy-svn] r50831 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080121124452.5DFF31684D6@codespeak.net> Author: arigo Date: Mon Jan 21 13:44:51 2008 New Revision: 50831 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Annotation fix. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Mon Jan 21 13:44:51 2008 @@ -346,7 +346,7 @@ def CArrayPtr(tp): return lltype.Ptr(CArray(tp)) -CArray._annspecialcase_ = 'specialize:memo' +CArrayPtr._annspecialcase_ = 'specialize:memo' def CCallback(args, res): return lltype.Ptr(lltype.FuncType(args, res)) From antocuni at codespeak.net Mon Jan 21 13:56:37 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Jan 2008 13:56:37 +0100 (CET) Subject: [pypy-svn] r50833 - pypy/dist/pypy/interpreter Message-ID: <20080121125637.4BF45168563@codespeak.net> Author: antocuni Date: Mon Jan 21 13:56:36 2008 New Revision: 50833 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: (arigo) specialize appexec Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Jan 21 13:56:36 2008 @@ -834,6 +834,7 @@ w_func = self.fromcache(AppExecCache).getorbuild(source) args = Arguments(self, list(posargs_w)) return self.call_args(w_func, args) + appexec._annspecialcase_ = 'specialize:arg(2)' def decode_index(self, w_index_or_slice, seqlength): """Helper for custom sequence implementations From arigo at codespeak.net Mon Jan 21 14:21:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 14:21:44 +0100 (CET) Subject: [pypy-svn] r50835 - in pypy/dist/pypy: module/_rawffi rlib Message-ID: <20080121132144.AC37416856E@codespeak.net> Author: arigo Date: Mon Jan 21 14:21:44 2008 New Revision: 50835 Modified: pypy/dist/pypy/module/_rawffi/callback.py pypy/dist/pypy/rlib/libffi.py Log: Annotation fix attempts. Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Mon Jan 21 14:21:44 2008 @@ -51,7 +51,7 @@ # necessary to keep stuff alive self.ll_callback = CallbackFuncPtr(ffiargs, ffiresult, callback, number) - self.ll_buffer = self.ll_callback.ll_closure + self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) def __del__(self): del self.CallbackPtr_by_number[self.number] Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Mon Jan 21 14:21:44 2008 @@ -191,11 +191,10 @@ ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) - def __init__(self, name, argtypes, restype, funcsym): + def __init__(self, name, argtypes, restype): self.name = name self.argtypes = argtypes self.restype = restype - self.funcsym = funcsym argnum = len(argtypes) self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw') for i in range(argnum): @@ -228,7 +227,7 @@ ll_userdata = lltype.nullptr(USERDATA_P.TO) def __init__(self, argtypes, restype, func, additional_arg=0): - AbstractFuncPtr.__init__(self, "callback", argtypes, restype, None) + AbstractFuncPtr.__init__(self, "callback", argtypes, restype) self.ll_closure = lltype.malloc(FFI_CLOSUREP.TO, flavor='raw') self.ll_userdata = lltype.malloc(USERDATA_P.TO) self.ll_userdata.callback = rffi.llhelper(CALLBACK_TP, func) @@ -246,6 +245,10 @@ class RawFuncPtr(AbstractFuncPtr): + def __init__(self, name, argtypes, restype, funcsym): + AbstractFuncPtr.__init__(self, name, argtypes, restype) + self.funcsym = funcsym + def call(self, args_ll, ll_result): assert len(args_ll) == len(self.argtypes), ( "wrong number of arguments in call to %s(): " @@ -263,7 +266,8 @@ def __init__(self, name, argtypes, restype, funcsym): # initialize each one of pointers with null - AbstractFuncPtr.__init__(self, name, argtypes, restype, funcsym) + AbstractFuncPtr.__init__(self, name, argtypes, restype) + self.funcsym = funcsym self.argnum = len(self.argtypes) self.pushed_args = 0 self.ll_args = lltype.malloc(rffi.VOIDPP.TO, self.argnum, flavor='raw') From arigo at codespeak.net Mon Jan 21 14:59:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 14:59:03 +0100 (CET) Subject: [pypy-svn] r50837 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080121135903.3909F16856B@codespeak.net> Author: arigo Date: Mon Jan 21 14:59:02 2008 New Revision: 50837 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Fix the "Warning: captured address may be awkward" from the flow object space. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Mon Jan 21 14:59:02 2008 @@ -168,6 +168,7 @@ else: before = None after = None + callable_name = getattr(callable, '__name__', '?') args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%s): # no *args - no GIL for mallocing the tuple @@ -179,7 +180,7 @@ except Exception, e: os.write(2, "Warning: uncaught exception in callback: %%s %%s\n" %% - (str(callable), str(e))) + (callable_name, str(e))) result = errorcode if before: before() From fijal at codespeak.net Mon Jan 21 15:54:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 15:54:04 +0100 (CET) Subject: [pypy-svn] r50838 - pypy/dist/pypy/objspace/std Message-ID: <20080121145404.C0E6C16857E@codespeak.net> Author: fijal Date: Mon Jan 21 15:54:04 2008 New Revision: 50838 Modified: pypy/dist/pypy/objspace/std/stringobject.py Log: Rewrite it in a way to not merge chars and nones (confused jit and killed useful optimization) Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Mon Jan 21 15:54:04 2008 @@ -867,13 +867,20 @@ for c in s: i += 1 - bs_char = None # character quoted by backspace + use_bs_char = False # character quoted by backspace if c == '\\' or c == quote: bs_char = c - elif c == '\t': bs_char = 't' - elif c == '\r': bs_char = 'r' - elif c == '\n': bs_char = 'n' + use_bs_char = True + elif c == '\t': + bs_char = 't' + use_bs_char = True + elif c == '\r': + bs_char = 'r' + use_bs_char = True + elif c == '\n': + bs_char = 'n' + use_bs_char = True elif not '\x20' <= c < '\x7f': n = ord(c) buf[i] = '\\' @@ -886,7 +893,7 @@ else: buf[i] = c - if bs_char is not None: + if use_bs_char: buf[i] = '\\' i += 1 buf[i] = bs_char From antocuni at codespeak.net Mon Jan 21 15:56:33 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 21 Jan 2008 15:56:33 +0100 (CET) Subject: [pypy-svn] r50839 - in pypy/dist/pypy: module/clr translator/cli translator/cli/src translator/cli/test Message-ID: <20080121145633.F08DA168559@codespeak.net> Author: antocuni Date: Mon Jan 21 15:56:33 2008 New Revision: 50839 Modified: pypy/dist/pypy/module/clr/interp_clr.py pypy/dist/pypy/translator/cli/dotnet.py pypy/dist/pypy/translator/cli/query.py pypy/dist/pypy/translator/cli/src/query.cs pypy/dist/pypy/translator/cli/test/test_dotnet.py Log: prebuild the namespaces and types hierarchy, else the annotator gets confused because it thinks some getattr will fail. Modified: pypy/dist/pypy/module/clr/interp_clr.py ============================================================================== --- pypy/dist/pypy/module/clr/interp_clr.py (original) +++ pypy/dist/pypy/module/clr/interp_clr.py Mon Jan 21 15:56:33 2008 @@ -13,10 +13,6 @@ TargetInvocationException = NativeException(CLR.System.Reflection.TargetInvocationException) AmbiguousMatchException = NativeException(CLR.System.Reflection.AmbiguousMatchException) -System.Double # force the type to be loaded, else the annotator could think that System has no Double attribute -System.Boolean # the same -System.AppDomain - def get_method(space, b_type, name, b_paramtypes): try: method = b_type.GetMethod(name, b_paramtypes) Modified: pypy/dist/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/dotnet.py (original) +++ pypy/dist/pypy/translator/cli/dotnet.py Mon Jan 21 15:56:33 2008 @@ -260,33 +260,6 @@ return SomeOOInstance(self.instance._INSTANCE) -class CliNamespace(object): - def __init__(self, name): - self._name = name - - def __fullname(self, name): - if self._name is None: - return name - else: - return '%s.%s' % (self._name, name) - - def __getattr__(self, attr): - from pypy.translator.cli.query import get_cli_class, Types, Namespaces - from pypy.translator.cli.query import load_assembly, mscorlib - load_assembly(mscorlib) - - fullname = self.__fullname(attr) - if fullname in Namespaces: - value = CliNamespace(fullname) - elif fullname in Types: - value = get_cli_class(fullname) - else: - raise AttributeError, attr - setattr(self, attr, value) - return value - -CLR = CliNamespace(None) - BOXABLE_TYPES = [ootype.Signed, ootype.Unsigned, ootype.SignedLongLong, ootype.UnsignedLongLong, ootype.Bool, ootype.Float, ootype.Char, ootype.String] @@ -525,8 +498,8 @@ _about_ = eventhandler def compute_result_annotation(self, s_value): - from pypy.translator.cli.query import load_class_maybe - cliType = load_class_maybe('System.EventHandler') + from pypy.translator.cli.query import get_cli_class + cliType = get_cli_class('System.EventHandler') return SomeOOInstance(cliType._INSTANCE) def specialize_call(self, hop): @@ -534,3 +507,7 @@ methodname = hop.args_r[0].methodname c_methodname = hop.inputconst(ootype.Void, methodname) return hop.genop('cli_eventhandler', [v_obj, c_methodname], hop.r_result.lowleveltype) + +from pypy.translator.cli.query import CliNamespace +CLR = CliNamespace(None) +CLR._buildtree() Modified: pypy/dist/pypy/translator/cli/query.py ============================================================================== --- pypy/dist/pypy/translator/cli/query.py (original) +++ pypy/dist/pypy/translator/cli/query.py Mon Jan 21 15:56:33 2008 @@ -8,8 +8,6 @@ from pypy.translator.cli.rte import Query from pypy.translator.cli.sdk import SDK from pypy.translator.cli.support import log -from pypy.translator.cli.dotnet import CLR, CliNamespace, CliClass,\ - NativeInstance, _overloaded_static_meth, _static_meth, OverloadingResolver Assemblies = set() Types = {} # TypeName -> ClassDesc @@ -121,6 +119,9 @@ raise TypeError def get_cliclass(self): + from pypy.translator.cli.dotnet import CliClass, NativeInstance + from pypy.translator.cli.dotnet import _overloaded_static_meth, _static_meth + if self._cliclass is not None: return self._cliclass @@ -152,6 +153,7 @@ return Class def group_methods(self, methods, overload, meth, Meth): + from pypy.translator.cli.dotnet import OverloadingResolver groups = {} for name, args, result in methods: groups.setdefault(name, []).append((args, result)) @@ -168,3 +170,40 @@ ARGS = [get_ootype(arg) for arg in args] RESULT = get_ootype(result) return Meth(ARGS, RESULT) + +placeholder = object() +class CliNamespace(object): + def __init__(self, name): + self._name = name + self.__treebuilt = False + + def __fullname(self, name): + if self._name is None: + return name + else: + return '%s.%s' % (self._name, name) + + def _buildtree(self): + assert self._name is None, '_buildtree can be called only on top-level CLR, not on namespaces' + from pypy.translator.cli.support import getattr_ex + load_assembly(mscorlib) + for fullname in sorted(list(Namespaces)): + if '.' in fullname: + parent, name = fullname.rsplit('.', 1) + parent = getattr_ex(self, parent) + setattr(parent, name, CliNamespace(fullname)) + else: + setattr(self, fullname, CliNamespace(fullname)) + + for fullname in Types.keys(): + parent, name = fullname.rsplit('.', 1) + parent = getattr_ex(self, parent) + setattr(parent, name, placeholder) + + def __getattribute__(self, attr): + value = object.__getattribute__(self, attr) + if value is placeholder: + fullname = self.__fullname(attr) + value = get_cli_class(fullname) + setattr(self, attr, value) + return value Modified: pypy/dist/pypy/translator/cli/src/query.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/query.cs (original) +++ pypy/dist/pypy/translator/cli/src/query.cs Mon Jan 21 15:56:33 2008 @@ -143,6 +143,7 @@ &&(t == typeof(System.Array) || t.FullName == null || t.FullName.StartsWith("System.Array+InternalArray") || + t.IsNested || t.IsNotPublic || t.IsByRef || t.IsPointer || Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Mon Jan 21 15:56:33 2008 @@ -10,9 +10,7 @@ native_exc, new_array, init_array, typeof, eventhandler System = CLR.System -Math = CLR.System.Math ArrayList = CLR.System.Collections.ArrayList -Type = CLR.System.Type class TestDotnetAnnotation(object): @@ -38,11 +36,11 @@ def test_class(self): def fn(): - return Math + return System.Math a = RPythonAnnotator() s = a.build_types(fn, []) assert isinstance(s, SomeCliClass) - assert s.const is Math + assert s.const is System.Math def test_fullname(self): def fn(): @@ -50,22 +48,22 @@ a = RPythonAnnotator() s = a.build_types(fn, []) assert isinstance(s, SomeCliClass) - assert s.const is Math + assert s.const is System.Math def test_staticmeth(self): def fn(): - return Math.Abs + return System.Math.Abs a = RPythonAnnotator() s = a.build_types(fn, []) assert isinstance(s, SomeCliStaticMethod) - assert s.cli_class is Math + assert s.cli_class is System.Math assert s.meth_name == 'Abs' def test_staticmeth_call(self): def fn1(): - return Math.Abs(42) + return System.Math.Abs(42) def fn2(): - return Math.Abs(42.5) + return System.Math.Abs(42.5) a = RPythonAnnotator() assert type(a.build_types(fn1, [])) is annmodel.SomeInteger assert type(a.build_types(fn2, [])) is annmodel.SomeFloat @@ -172,7 +170,7 @@ def test_can_be_None(self): def fn(): - ttype = Type.GetType('foo') + ttype = System.Type.GetType('foo') return ttype.get_Namespace() a = RPythonAnnotator() s = a.build_types(fn, []) @@ -186,13 +184,13 @@ def test_staticmeth_call(self): def fn(x): - return Math.Abs(x) + return System.Math.Abs(x) assert self.interpret(fn, [-42]) == 42 def test_staticmeth_overload(self): self._skip_pythonnet('Pythonnet bug!') def fn(x, y): - return Math.Abs(x), Math.Abs(y) + return System.Math.Abs(x), System.Math.Abs(y) res = self.interpret(fn, [-42, -42.5]) item0, item1 = self.ll_to_tuple(res) assert item0 == 42 @@ -349,7 +347,6 @@ assert res.startswith("Index is less than 0") def test_typeof(self): - System.Int32 # force Int32 to be loaded def fn(): x = box(42) return x.GetType() == typeof(System.Int32) @@ -409,7 +406,7 @@ return "" def fn(): - ttype = Type.GetType('Consts, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089') + ttype = System.Type.GetType('Consts, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089') namespace = ttype.get_Namespace() if namespace is not None: return False From arigo at codespeak.net Mon Jan 21 16:13:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 16:13:57 +0100 (CET) Subject: [pypy-svn] r50840 - pypy/dist/pypy/annotation Message-ID: <20080121151357.2C948168553@codespeak.net> Author: arigo Date: Mon Jan 21 16:13:56 2008 New Revision: 50840 Modified: pypy/dist/pypy/annotation/binaryop.py Log: Improve the check for values degenerating to SomeObject to cover e.g. the items of a SomeTuple built as the union of two SomeTuples. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Mon Jan 21 16:13:56 2008 @@ -14,7 +14,8 @@ from pypy.annotation.model import SomeExternalObject, SomeWeakRef from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess from pypy.annotation.model import SomeSingleFloat -from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS +from pypy.annotation.model import unionof, UnionError, set, missing_operation +from pypy.annotation.model import isdegenerated from pypy.annotation.model import read_can_only_throw from pypy.annotation.model import add_knowntypedata, merge_knowntypedata from pypy.annotation.model import lltype_to_annotation @@ -30,6 +31,14 @@ def immutablevalue(x): return getbookkeeper().immutablevalue(x) +def unioncheck(*somevalues): + s_value = unionof(*somevalues) + if isdegenerated(s_value): + bookkeeper = getbookkeeper() + if bookkeeper is not None: + bookkeeper.ondegenerated('union', s_value) + return s_value + # XXX unify this with ObjSpace.MethodTable BINARY_OPERATIONS = set(['add', 'sub', 'mul', 'div', 'mod', 'truediv', 'floordiv', 'divmod', 'pow', @@ -80,11 +89,11 @@ result.is_type_of = is_type_of1 # try to preserve the origin of SomeObjects if obj1 == result: - return obj1 + result = obj1 elif obj2 == result: - return obj2 - else: - return result + result = obj2 + unioncheck(result) + return result # inplace_xxx ---> xxx by default def inplace_add((obj1, obj2)): return pair(obj1, obj2).add() @@ -519,7 +528,7 @@ if len(tup1.items) != len(tup2.items): return SomeObject() else: - unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)] + unions = [unioncheck(x,y) for x,y in zip(tup1.items, tup2.items)] return SomeTuple(items = unions) def add((tup1, tup2)): @@ -560,9 +569,9 @@ class __extend__(pairtype(SomeSlice, SomeSlice)): def union((slic1, slic2)): - return SomeSlice(unionof(slic1.start, slic2.start), - unionof(slic1.stop, slic2.stop), - unionof(slic1.step, slic2.step)) + return SomeSlice(unioncheck(slic1.start, slic2.start), + unioncheck(slic1.stop, slic2.stop), + unioncheck(slic1.step, slic2.step)) class __extend__(pairtype(SomeTuple, SomeInteger)): @@ -766,7 +775,7 @@ class __extend__(pairtype(SomeIterator, SomeIterator)): def union((iter1, iter2)): - s_cont = unionof(iter1.s_container, iter2.s_container) + s_cont = unioncheck(iter1.s_container, iter2.s_container) if iter1.variant != iter2.variant: raise UnionError("merging incompatible iterators variants") return SomeIterator(s_cont, *iter1.variant) @@ -780,7 +789,7 @@ bltn1.s_self is None or bltn2.s_self is None): raise UnionError("cannot merge two different builtin functions " "or methods:\n %r\n %r" % (bltn1, bltn2)) - s_self = unionof(bltn1.s_self, bltn2.s_self) + s_self = unioncheck(bltn1.s_self, bltn2.s_self) return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) class __extend__(pairtype(SomePBC, SomePBC)): @@ -808,7 +817,7 @@ unique_key = desc bk = desc.bookkeeper s_result = bk.emulate_pbc_call(unique_key, pbc, gencall.args_s) - s_result = unionof(s_result, gencall.s_result) + s_result = unioncheck(s_result, gencall.s_result) assert gencall.s_result.contains(s_result) return gencall From arigo at codespeak.net Mon Jan 21 16:21:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 16:21:58 +0100 (CET) Subject: [pypy-svn] r50841 - pypy/dist/pypy/tool Message-ID: <20080121152158.B08A8168569@codespeak.net> Author: arigo Date: Mon Jan 21 16:21:58 2008 New Revision: 50841 Modified: pypy/dist/pypy/tool/error.py Log: Got a KeyError here... Modified: pypy/dist/pypy/tool/error.py ============================================================================== --- pypy/dist/pypy/tool/error.py (original) +++ pypy/dist/pypy/tool/error.py Mon Jan 21 16:21:58 2008 @@ -114,7 +114,12 @@ def format_simple_call(annotator, oper, what, msg): msg.append("Simple call of incompatible family:") - descs = annotator.bindings[oper.args[0]].descriptions + try: + descs = annotator.bindings[oper.args[0]].descriptions + except (KeyError, AttributeError), e: + msg.append(" (%s getting at the binding!)" % ( + e.__class__.__name__,)) + return for desc in descs.keys(): func = desc.pyobj if func is None: From arigo at codespeak.net Mon Jan 21 16:25:01 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 16:25:01 +0100 (CET) Subject: [pypy-svn] r50842 - pypy/dist/pypy/annotation Message-ID: <20080121152501.3B25916856B@codespeak.net> Author: arigo Date: Mon Jan 21 16:25:00 2008 New Revision: 50842 Modified: pypy/dist/pypy/annotation/binaryop.py Log: Oups, this logic is too eager to complain. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Mon Jan 21 16:25:00 2008 @@ -15,7 +15,7 @@ from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess from pypy.annotation.model import SomeSingleFloat from pypy.annotation.model import unionof, UnionError, set, missing_operation -from pypy.annotation.model import isdegenerated +from pypy.annotation.model import isdegenerated, TLS from pypy.annotation.model import read_can_only_throw from pypy.annotation.model import add_knowntypedata, merge_knowntypedata from pypy.annotation.model import lltype_to_annotation @@ -33,7 +33,7 @@ def unioncheck(*somevalues): s_value = unionof(*somevalues) - if isdegenerated(s_value): + if isdegenerated(s_value) and not TLS.no_side_effects_in_union: bookkeeper = getbookkeeper() if bookkeeper is not None: bookkeeper.ondegenerated('union', s_value) From fijal at codespeak.net Mon Jan 21 16:38:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 16:38:22 +0100 (CET) Subject: [pypy-svn] r50843 - pypy/dist/pypy/module/_rawffi Message-ID: <20080121153822.9728516857E@codespeak.net> Author: fijal Date: Mon Jan 21 16:38:20 2008 New Revision: 50843 Modified: pypy/dist/pypy/module/_rawffi/callback.py Log: Try to fix annotation Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Mon Jan 21 16:38:20 2008 @@ -18,7 +18,7 @@ argtypes = callback_ptr.args space = callback_ptr.space w_args = space.newlist([wrap_value(space, get_elem, ll_args[i], 0, - (argtypes[i], None, None)) + (argtypes[i], 0, 0)) for i in range(len(argtypes))]) w_res = space.call(w_callable, w_args) if space.is_w(w_res, space.w_None): From fijal at codespeak.net Mon Jan 21 17:19:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 21 Jan 2008 17:19:34 +0100 (CET) Subject: [pypy-svn] r50846 - pypy/dist/pypy/module/_rawffi Message-ID: <20080121161934.CB7E416855E@codespeak.net> Author: fijal Date: Mon Jan 21 17:19:34 2008 New Revision: 50846 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py Log: Kill some dead code Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Mon Jan 21 17:19:34 2008 @@ -9,10 +9,8 @@ from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.unroll import unrolling_iterable -from pypy.module.struct.standardfmttable import min_max_acc_method -from pypy.module.struct.nativefmttable import native_fmttable from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib.rarithmetic import intmask, r_uint +from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat def _signed_type_for(TYPE): sz = rffi.sizeof(TYPE) From arigo at codespeak.net Mon Jan 21 18:00:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 21 Jan 2008 18:00:03 +0100 (CET) Subject: [pypy-svn] r50847 - pypy/dist/lib-python/modified-2.4.1/test Message-ID: <20080121170003.CC6D1169E16@codespeak.net> Author: arigo Date: Mon Jan 21 18:00:02 2008 New Revision: 50847 Modified: pypy/dist/lib-python/modified-2.4.1/test/test_file.py Log: In case the file was not garbage collected, f.tell() fails because the file was explicitly closed a few lines above. This masks the real error message. Modified: pypy/dist/lib-python/modified-2.4.1/test/test_file.py ============================================================================== --- pypy/dist/lib-python/modified-2.4.1/test/test_file.py (original) +++ pypy/dist/lib-python/modified-2.4.1/test/test_file.py Mon Jan 21 18:00:02 2008 @@ -17,7 +17,7 @@ gc.collect() gc.collect() try: - p.tell() + p.name except ReferenceError: pass else: From fijal at codespeak.net Tue Jan 22 09:20:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 09:20:47 +0100 (CET) Subject: [pypy-svn] r50858 - pypy/dist/pypy/module/_rawffi Message-ID: <20080122082047.DBBF7168563@codespeak.net> Author: fijal Date: Tue Jan 22 09:20:45 2008 New Revision: 50858 Modified: pypy/dist/pypy/module/_rawffi/callback.py Log: Forgotten about high-level address access Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Tue Jan 22 09:20:45 2008 @@ -63,4 +63,5 @@ 'CallbackPtr', __new__ = interp2app(descr_new_callbackptr), byptr = interp2app(W_CallbackPtr.byptr), + buffer = GetSetProperty(W_CallbackPtr.getbuffer), ) From pypy-svn at codespeak.net Tue Jan 22 10:06:44 2008 From: pypy-svn at codespeak.net (pypy-svn at codespeak.net) Date: Tue, 22 Jan 2008 10:06:44 +0100 (CET) Subject: [pypy-svn] So Many Deals and Ideas Message-ID: <20080122130644.9458.qmail@dsl88-226-52530.ttnet.net.tr> An HTML attachment was scrubbed... URL: From fijal at codespeak.net Tue Jan 22 10:15:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 10:15:58 +0100 (CET) Subject: [pypy-svn] r50859 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080122091558.A041A168533@codespeak.net> Author: fijal Date: Tue Jan 22 10:15:57 2008 New Revision: 50859 Modified: pypy/dist/pypy/module/_rawffi/callback.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: * use proper interface for results of callbacks * fix issues (we don't really care about having an address of such stuff) Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Tue Jan 22 10:15:57 2008 @@ -5,9 +5,9 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rpython.lltypesystem import lltype, rffi from pypy.module._rawffi.structure import unpack_fields -from pypy.module._rawffi.array import get_elem +from pypy.module._rawffi.array import get_elem, push_elem from pypy.module._rawffi.interp_rawffi import W_DataInstance, _get_type_,\ - wrap_value, unwrap_value, unwrap_truncate_int + wrap_value, unwrap_value, unwrap_truncate_int, letter2tp from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr def callback(ll_args, ll_res, ll_userdata): @@ -18,17 +18,11 @@ argtypes = callback_ptr.args space = callback_ptr.space w_args = space.newlist([wrap_value(space, get_elem, ll_args[i], 0, - (argtypes[i], 0, 0)) + letter2tp(space, argtypes[i])) for i in range(len(argtypes))]) w_res = space.call(w_callable, w_args) - if space.is_w(w_res, space.w_None): - res[0] = lltype.nullptr(rffi.VOIDP.TO) - else: - instance = space.interpclass_w(w_res) - if isinstance(instance, W_DataInstance): - res[0] = instance.ll_buffer - else: - res[0] = unwrap_truncate_int(rffi.VOIDP, space, w_res) + unwrap_value(space, push_elem, ll_res, 0, + letter2tp(space, callback_ptr.result), w_res) class W_CallbackPtr(W_DataInstance): # XXX some weird hackery to be able to recover W_CallbackPtr object @@ -38,7 +32,7 @@ def __init__(self, space, w_callable, w_args, w_result): number = self.CallbackPtr_id - self.CallbackPtr_id += 1 + self.__class__.CallbackPtr_id += 1 self.CallbackPtr_by_number[number] = self self.space = space self.w_callable = w_callable Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Tue Jan 22 10:15:57 2008 @@ -104,6 +104,11 @@ return prebuilt_array1; } + long long runcallback(long long(*callback)()) + { + return callback(); + } + ''')) return compile_c_module([c_file], 'x', ExternalCompilationInfo()) prepare_c_example = staticmethod(prepare_c_example) @@ -371,10 +376,9 @@ a1 = _rawffi.Array('i').fromaddress(a, 1) a2 = _rawffi.Array('i').fromaddress(b, 1) if a1[0] > a2[0]: - res = 1 - res = -1 - resarray[0] = res - return resarray + res = -1 + res = 1 + return res a1 = ll_to_sort.byptr() a2 = _rawffi.Array('i')(1) a2[0] = len(ll_to_sort) @@ -385,6 +389,27 @@ qsort(a1, a2, a3, a4) res = [ll_to_sort[i] for i in range(len(ll_to_sort))] assert res == [1,2,3,4] + a1.free() + a2.free() + a3.free() + a4.free() + ll_to_sort.free() + del cb + + def test_another_callback(self): + import _rawffi + lib = _rawffi.CDLL(self.lib_name) + runcallback = lib.ptr('runcallback', ['P'], 'q') + def callback(): + return 1<<42 + + cb = _rawffi.CallbackPtr(callback, [], 'q') + a1 = cb.byptr() + res = runcallback(a1) + assert res[0] == 1<<42 + res.free() + a1.free() + del cb def test_setattr_struct(self): import _rawffi From fijal at codespeak.net Tue Jan 22 10:35:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 10:35:41 +0100 (CET) Subject: [pypy-svn] r50860 - pypy/dist/pypy/module/_rawffi Message-ID: <20080122093541.72E0D168545@codespeak.net> Author: fijal Date: Tue Jan 22 10:35:40 2008 New Revision: 50860 Modified: pypy/dist/pypy/module/_rawffi/callback.py Log: Make both rpython and cpython happy. Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Tue Jan 22 10:35:40 2008 @@ -12,7 +12,7 @@ def callback(ll_args, ll_res, ll_userdata): userdata = rffi.cast(USERDATA_P, ll_userdata) - callback_ptr = W_CallbackPtr.CallbackPtr_by_number[userdata.addarg] + callback_ptr = global_counter.CallbackPtr_by_number[userdata.addarg] w_callable = callback_ptr.w_callable res = rffi.cast(rffi.VOIDPP, ll_res) argtypes = callback_ptr.args @@ -24,16 +24,22 @@ unwrap_value(space, push_elem, ll_res, 0, letter2tp(space, callback_ptr.result), w_res) +# XXX some weird hackery to be able to recover W_CallbackPtr object +# out of number +class GlobalCounter: + def __init__(self): + self.CallbackPtr_id = 0 + self.CallbackPtr_by_number = {} + +global_counter = GlobalCounter() + class W_CallbackPtr(W_DataInstance): - # XXX some weird hackery to be able to recover W_CallbackPtr object - # out of number - CallbackPtr_by_number = {} - CallbackPtr_id = 0 + global_counter = global_counter def __init__(self, space, w_callable, w_args, w_result): - number = self.CallbackPtr_id - self.__class__.CallbackPtr_id += 1 - self.CallbackPtr_by_number[number] = self + number = global_counter.CallbackPtr_id + global_counter.CallbackPtr_id += 1 + global_counter.CallbackPtr_by_number[number] = self self.space = space self.w_callable = w_callable self.number = number @@ -48,7 +54,7 @@ self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) def __del__(self): - del self.CallbackPtr_by_number[self.number] + del self.global_counter.CallbackPtr_by_number[self.number] def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result): return W_CallbackPtr(space, w_callable, w_args, w_result) From fijal at codespeak.net Tue Jan 22 11:19:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 11:19:43 +0100 (CET) Subject: [pypy-svn] r50861 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080122101943.4E1C9168569@codespeak.net> Author: fijal Date: Tue Jan 22 11:19:43 2008 New Revision: 50861 Added: pypy/dist/pypy/lib/app_test/ctypes/test_functions.py (contents, props changed) Log: Port test_functions Added: pypy/dist/pypy/lib/app_test/ctypes/test_functions.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_functions.py Tue Jan 22 11:19:43 2008 @@ -0,0 +1,401 @@ +""" +Here is probably the place to write the docs, since the test-cases +show how the type behave. + +Later... +""" + +from ctypes import * +import sys +import py + +try: + WINFUNCTYPE +except NameError: + # fake to enable this test on Linux + WINFUNCTYPE = CFUNCTYPE + + +def setup_module(mod): + import conftest + _ctypes_test = str(conftest.sofile) + mod.dll = CDLL(_ctypes_test) + if sys.platform == "win32": + mod.windll = WinDLL(_ctypes_test) + +class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] +class RECT(Structure): + _fields_ = [("left", c_int), ("top", c_int), + ("right", c_int), ("bottom", c_int)] +class TestFunctions: + + def test_mro(self): + # in Python 2.3, this raises TypeError: MRO conflict among bases classes, + # in Python 2.2 it works. + # + # But in early versions of _ctypes.c, the result of tp_new + # wasn't checked, and it even crashed Python. + # Found by Greg Chapman. + + try: + class X(object, Array): + _length_ = 5 + _type_ = "i" + except TypeError: + pass + + + from _ctypes import _Pointer + try: + class X(object, _Pointer): + pass + except TypeError: + pass + + from _ctypes import _SimpleCData + try: + class X(object, _SimpleCData): + _type_ = "i" + except TypeError: + pass + + try: + class X(object, Structure): + _fields_ = [] + except TypeError: + pass + + + def test_wchar_parm(self): + try: + c_wchar + except NameError: + return + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] + result = f(1, u"x", 3, 4, 5.0, 6.0) + assert result == 139 + assert type(result) == int + + def test_wchar_result(self): + try: + c_wchar + except NameError: + return + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_wchar + result = f(0, 0, 0, 0, 0, 0) + assert result == u'\x00' + + def test_voidresult(self): + f = dll._testfunc_v + f.restype = None + f.argtypes = [c_int, c_int, POINTER(c_int)] + result = c_int() + assert None == f(1, 2, byref(result)) + assert result.value == 3 + + def test_intresult(self): + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_int + result = f(1, 2, 3, 4, 5.0, 6.0) + assert result == 21 + assert type(result) == int + + result = f(-1, -2, -3, -4, -5.0, -6.0) + assert result == -21 + assert type(result) == int + + # If we declare the function to return a short, + # is the high part split off? + f.restype = c_short + result = f(1, 2, 3, 4, 5.0, 6.0) + assert result == 21 + assert type(result) == int + + result = f(1, 2, 3, 0x10004, 5.0, 6.0) + assert result == 21 + assert type(result) == int + + # You cannot assing character format codes as restype any longer + raises(TypeError, setattr, f, "restype", "i") + + def test_floatresult(self): + f = dll._testfunc_f_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_float + result = f(1, 2, 3, 4, 5.0, 6.0) + assert result == 21 + assert type(result) == float + + result = f(-1, -2, -3, -4, -5.0, -6.0) + assert result == -21 + assert type(result) == float + + def test_doubleresult(self): + f = dll._testfunc_d_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_double + result = f(1, 2, 3, 4, 5.0, 6.0) + assert result == 21 + assert type(result) == float + + result = f(-1, -2, -3, -4, -5.0, -6.0) + assert result == -21 + assert type(result) == float + + def test_longlongresult(self): + try: + c_longlong + except NameError: + return + f = dll._testfunc_q_bhilfd + f.restype = c_longlong + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + result = f(1, 2, 3, 4, 5.0, 6.0) + assert result == 21 + + f = dll._testfunc_q_bhilfdq + f.restype = c_longlong + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong] + result = f(1, 2, 3, 4, 5.0, 6.0, 21) + assert result == 42 + + def test_stringresult(self): + f = dll._testfunc_p_p + f.argtypes = None + f.restype = c_char_p + result = f("123") + assert result == "123" + + result = f(None) + assert result == None + + def test_pointers(self): + f = dll._testfunc_p_p + f.restype = POINTER(c_int) + f.argtypes = [POINTER(c_int)] + + # This only works if the value c_int(42) passed to the + # function is still alive while the pointer (the result) is + # used. + + v = c_int(42) + + assert pointer(v).contents.value == 42 + result = f(pointer(v)) + assert type(result) == POINTER(c_int) + assert result.contents.value == 42 + + # This on works... + result = f(pointer(v)) + assert result.contents.value == v.value + + p = pointer(c_int(99)) + result = f(p) + assert result.contents.value == 99 + + arg = byref(v) + result = f(arg) + assert not result.contents == v.value + + raises(ArgumentError, f, byref(c_short(22))) + + # It is dangerous, however, because you don't control the lifetime + # of the pointer: + result = f(byref(c_int(99))) + assert not result.contents == 99 + + def test_errors(self): + f = dll._testfunc_p_p + f.restype = c_int + + class X(Structure): + _fields_ = [("y", c_int)] + + raises(TypeError, f, X()) #cannot convert parameter + + ################################################################ + def test_shorts(self): + f = dll._testfunc_callback_i_if + + args = [] + expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] + + def callback(v): + args.append(v) + return v + + CallBack = CFUNCTYPE(c_int, c_int) + + cb = CallBack(callback) + f(2**18, cb) + assert args == expected + + ################################################################ + + + def test_callbacks(self): + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + def callback(value): + #print "called back with", value + return value + + cb = MyCallback(callback) + result = f(-10, cb) + assert result == -18 + + # test with prototype + f.argtypes = [c_int, MyCallback] + cb = MyCallback(callback) + result = f(-10, cb) + assert result == -18 + + AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int) + + # check that the prototype works: we call f with wrong + # argument types + cb = AnotherCallback(callback) + raises(ArgumentError, f, -10, cb) + + + def test_callbacks_2(self): + # Can also use simple datatypes as argument type specifiers + # for the callback function. + # In this case the call receives an instance of that type + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + f.argtypes = [c_int, MyCallback] + + def callback(value): + #print "called back with", value + assert type(value) == int + return value + + cb = MyCallback(callback) + result = f(-10, cb) + assert result == -18 + + def test_longlong_callbacks(self): + + f = dll._testfunc_callback_q_qf + f.restype = c_longlong + + MyCallback = CFUNCTYPE(c_longlong, c_longlong) + + f.argtypes = [c_longlong, MyCallback] + + def callback(value): + assert isinstance(value, (int, long)) + return value & 0x7FFFFFFF + + cb = MyCallback(callback) + + assert 13577625587 == f(1000000000000, cb) + + def test_errors(self): + raises(AttributeError, getattr, dll, "_xxx_yyy") + py.test.skip("in_dll not supported") + raises(ValueError, c_int.in_dll, dll, "_xxx_yyy") + + def test_byval(self): + py.test.skip("Structure by value") + # without prototype + ptin = POINT(1, 2) + ptout = POINT() + # EXPORT int _testfunc_byval(point in, point *pout) + result = dll._testfunc_byval(ptin, byref(ptout)) + got = result, ptout.x, ptout.y + expected = 3, 1, 2 + assert got == expected + + # with prototype + ptin = POINT(101, 102) + ptout = POINT() + dll._testfunc_byval.argtypes = (POINT, POINTER(POINT)) + dll._testfunc_byval.restype = c_int + result = dll._testfunc_byval(ptin, byref(ptout)) + got = result, ptout.x, ptout.y + expected = 203, 101, 102 + assert got == expected + + def test_struct_return_2H(self): + py.test.skip("Raw structure return") + class S2H(Structure): + _fields_ = [("x", c_short), + ("y", c_short)] + dll.ret_2h_func.restype = S2H + dll.ret_2h_func.argtypes = [S2H] + inp = S2H(99, 88) + s2h = dll.ret_2h_func(inp) + assert (s2h.x, s2h.y) == (99*2, 88*3) + + if sys.platform == "win32": + def test_struct_return_2H_stdcall(self): + class S2H(Structure): + _fields_ = [("x", c_short), + ("y", c_short)] + + windll.s_ret_2h_func.restype = S2H + windll.s_ret_2h_func.argtypes = [S2H] + s2h = windll.s_ret_2h_func(S2H(99, 88)) + assert (s2h.x, s2h.y) == (99*2, 88*3) + + def test_struct_return_8H(self): + py.test.skip("Raw structure return") + class S8I(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int), + ("d", c_int), + ("e", c_int), + ("f", c_int), + ("g", c_int), + ("h", c_int)] + dll.ret_8i_func.restype = S8I + dll.ret_8i_func.argtypes = [S8I] + inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) + s8i = dll.ret_8i_func(inp) + assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == ( + (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + + if sys.platform == "win32": + def test_struct_return_8H_stdcall(self): + class S8I(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int), + ("d", c_int), + ("e", c_int), + ("f", c_int), + ("g", c_int), + ("h", c_int)] + windll.s_ret_8i_func.restype = S8I + windll.s_ret_8i_func.argtypes = [S8I] + inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) + s8i = windll.s_ret_8i_func(inp) + assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == ( + (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + + def test_sf1651235(self): + py.test.skip("???") + # see http://www.python.org/sf/1651235 + + proto = CFUNCTYPE(c_int, RECT, POINT) + def callback(*args): + return 0 + + callback = proto(callback) + raises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT())) + From fijal at codespeak.net Tue Jan 22 11:20:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 11:20:36 +0100 (CET) Subject: [pypy-svn] r50862 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122102036.5494616856E@codespeak.net> Author: fijal Date: Tue Jan 22 11:20:35 2008 New Revision: 50862 Modified: pypy/dist/pypy/lib/_ctypes/__init__.py pypy/dist/pypy/lib/_ctypes/basics.py pypy/dist/pypy/lib/_ctypes/dummy.py pypy/dist/pypy/lib/_ctypes/function.py Log: A bit wacking to support more tests. Some rudimentary callback support. Modified: pypy/dist/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/__init__.py (original) +++ pypy/dist/pypy/lib/_ctypes/__init__.py Tue Jan 22 11:20:35 2008 @@ -1,9 +1,9 @@ from _ctypes.dummy import Union -from _ctypes.dummy import ArgumentError from _ctypes.dummy import resize from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr -from _ctypes.basics import _CData, sizeof, alignment, byref, addressof +from _ctypes.basics import _CData, sizeof, alignment, byref, addressof,\ + ArgumentError from _ctypes.primitive import _SimpleCData from _ctypes.pointer import _Pointer, _cast_addr from _ctypes.function import CFuncPtr Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Tue Jan 22 11:20:35 2008 @@ -2,6 +2,9 @@ import _rawffi import sys +class ArgumentError(Exception): + pass + class _CDataMeta(type): def from_param(self, value): if isinstance(value, self): Modified: pypy/dist/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/dummy.py (original) +++ pypy/dist/pypy/lib/_ctypes/dummy.py Tue Jan 22 11:20:35 2008 @@ -4,9 +4,6 @@ class Union(object): __metaclass__ = UnionType -class ArgumentError(Exception): - pass - def dummyfunc(*args, **kwargs): return None Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Tue Jan 22 11:20:35 2008 @@ -1,6 +1,6 @@ import types -from _ctypes.basics import _CData, _CDataMeta +from _ctypes.basics import _CData, _CDataMeta, ArgumentError import _rawffi class CFuncPtrType(_CDataMeta): @@ -34,22 +34,31 @@ self._restype_ = restype restype = property(_getrestype, _setrestype) - def __init__(self, address_or_name_and_dll=0): - if isinstance(address_or_name_and_dll, tuple): - self.name, self.dll = address_or_name_and_dll + def __init__(self, argument=None): + self.callable = None + self.name = None + if isinstance(argument, int): + self._buffer = _rawffi.Array('P').fromaddress(argument, 1) + # XXX finish this one, we need to be able to jump there somehow + elif callable(argument): + self.callable = argument + argtypes = [arg._ffiletter for arg in self._argtypes_] + restype = self._restype_._ffiletter + self._ptr = _rawffi.CallbackPtr(argument, argtypes, restype) + self._buffer = self._ptr.byptr() + elif isinstance(argument, tuple) and len(argument) == 2: + import ctypes + self.name, self.dll = argument + # we need to check dll anyway + self._getfuncptr([], ctypes.c_int) + elif argument is None: + return # needed for test.. else: - self.address = address_or_name_and_dll - if isinstance(self.address, int): - self._buffer = _rawffi.Array('P').fromaddress(self.address, 1) - self.name = None - + raise TypeError("Unknown constructor %s" % (argument,)) + def __call__(self, *args): - if self.name is None: - if isinstance(self.address, types.FunctionType): - # special hack to support to way a few functions like - # ctypes.cast() are implemented in ctypes/__init__.py - return self.address(*args) - raise NotImplementedError("Creation of function pointer to pure addresses is not implemented") + if self.callable is not None: + return self.callable(*args) argtypes = self._argtypes_ if argtypes is None: argtypes = self._guess_argtypes(args) @@ -68,7 +77,7 @@ def _guess_argtypes(self, args): from _ctypes import _CData - from ctypes import c_char_p, c_void_p + from ctypes import c_char_p, c_void_p, c_int, Array, Structure res = [] for arg in args: if isinstance(arg, str): @@ -77,10 +86,17 @@ res.append(type(arg)) elif arg is None: res.append(c_void_p) + elif arg == 0: + res.append(c_void_p) + elif isinstance(arg, int): + res.append(c_int) else: raise TypeError("Dont know how to handle %s" % (arg,)) return res def _wrap_args(self, argtypes, args): - return [argtype._CData_input(arg) for argtype, arg in - zip(argtypes, args)] + try: + return [argtype._CData_input(arg) for argtype, arg in + zip(argtypes, args)] + except TypeError, e: + raise ArgumentError(e.args[0]) From arigo at codespeak.net Tue Jan 22 11:58:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Jan 2008 11:58:09 +0100 (CET) Subject: [pypy-svn] r50863 - pypy/branch/loops-for-gcc Message-ID: <20080122105809.AA921168423@codespeak.net> Author: arigo Date: Tue Jan 22 11:58:08 2008 New Revision: 50863 Added: pypy/branch/loops-for-gcc/ - copied from r50862, pypy/dist/ Log: A branch in which to hack at the C backend to produce gcc-friendly loops. From fijal at codespeak.net Tue Jan 22 12:01:25 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 12:01:25 +0100 (CET) Subject: [pypy-svn] r50864 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080122110125.CBFE616854F@codespeak.net> Author: fijal Date: Tue Jan 22 12:01:25 2008 New Revision: 50864 Modified: pypy/dist/pypy/module/_rawffi/__init__.py pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: A bit more friendly routine for ctypes (adheres to ctypes insanity) Modified: pypy/dist/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/__init__.py (original) +++ pypy/dist/pypy/module/_rawffi/__init__.py Tue Jan 22 12:01:25 2008 @@ -19,6 +19,7 @@ 'sizeof' : 'interp_rawffi.sizeof', 'alignment' : 'interp_rawffi.alignment', 'charp2string' : 'interp_rawffi.charp2string', + 'charp2rawstring' : 'interp_rawffi.charp2rawstring', 'CallbackPtr' : 'callback.W_CallbackPtr', } Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Tue Jan 22 12:01:25 2008 @@ -334,3 +334,10 @@ s = rffi.charp2strn(rffi.cast(rffi.CCHARP, address), maxlength) return space.wrap(s) charp2string.unwrap_spec = [ObjSpace, r_uint, int] + +def charp2rawstring(space, address, maxlength=-1): + if maxlength == -1: + return charp2string(space, address) + s = rffi.charpsize2str(rffi.cast(rffi.CCHARP, address), maxlength) + return space.wrap(s) +charp2rawstring.unwrap_spec = [ObjSpace, r_uint, int] Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Tue Jan 22 12:01:25 2008 @@ -162,6 +162,11 @@ arg2[0] = 'x' res = char_check(arg1, arg2) assert _rawffi.charp2string(res[0]) == 'xxxxxx' + assert _rawffi.charp2rawstring(res[0]) == 'xxxxxx' + assert _rawffi.charp2rawstring(res[0], 3) == 'xxx' + a = A(6, 'xx\x00\x00xx') + assert _rawffi.charp2string(a.buffer) == 'xx' + assert _rawffi.charp2rawstring(a.buffer, 4) == 'xx\x00\x00' res.free() arg1[0] = 'x' arg2[0] = 'y' From fijal at codespeak.net Tue Jan 22 12:34:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 12:34:35 +0100 (CET) Subject: [pypy-svn] r50865 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122113435.69BE9168509@codespeak.net> Author: fijal Date: Tue Jan 22 12:34:33 2008 New Revision: 50865 Modified: pypy/dist/pypy/lib/_ctypes/dummy.py Log: * Remove unnecessary stuff from here * EXPLODE when calling nonimplemented function Modified: pypy/dist/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/dummy.py (original) +++ pypy/dist/pypy/lib/_ctypes/dummy.py Tue Jan 22 12:34:33 2008 @@ -5,13 +5,8 @@ __metaclass__ = UnionType def dummyfunc(*args, **kwargs): - return None + EXPLODE -addressof = dummyfunc -alignment = dummyfunc resize = dummyfunc -_memmove_addr = dummyfunc _memset_addr = dummyfunc -_string_at_addr = dummyfunc -_cast_addr = dummyfunc From fijal at codespeak.net Tue Jan 22 12:51:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 12:51:29 +0100 (CET) Subject: [pypy-svn] r50866 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080122115129.1CF0D16854C@codespeak.net> Author: fijal Date: Tue Jan 22 12:51:28 2008 New Revision: 50866 Added: pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py (contents, props changed) Log: Add this test Added: pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py Tue Jan 22 12:51:28 2008 @@ -0,0 +1,61 @@ + +import py +import sys +from ctypes import * + +class TestMemFunctions: + def test_memmove(self): + # large buffers apparently increase the chance that the memory + # is allocated in high address space. + a = create_string_buffer(1000000) + p = "Hello, World" + result = memmove(a, p, len(p)) + assert a.value == "Hello, World" + + assert string_at(result) == "Hello, World" + assert string_at(result, 5) == "Hello" + assert string_at(result, 16) == "Hello, World\0\0\0\0" + assert string_at(result, 0) == "" + + def test_memset(self): + a = create_string_buffer(1000000) + result = memset(a, ord('x'), 16) + assert a.value == "xxxxxxxxxxxxxxxx" + + assert string_at(result) == "xxxxxxxxxxxxxxxx" + assert string_at(a) == "xxxxxxxxxxxxxxxx" + assert string_at(a, 20) == "xxxxxxxxxxxxxxxx\0\0\0\0" + + def test_cast(self): + py.test.skip("I'm not sure I understood") + a = (c_ubyte * 32)(*map(ord, "abcdef")) + assert cast(a, c_char_p).value == "abcdef" + assert cast(a, POINTER(c_byte))[:7] == ( + [97, 98, 99, 100, 101, 102, 0]) + + def test_string_at(self): + s = string_at("foo bar") + # XXX The following may be wrong, depending on how Python + # manages string instances + #assert 2 == sys.getrefcount(s) + assert s, "foo bar" + + assert string_at("foo bar", 8) == "foo bar\0" + assert string_at("foo bar", 3) == "foo" + + try: + create_unicode_buffer + except NameError: + pass + else: + def test_wstring_at(self): + p = create_unicode_buffer("Hello, World") + a = create_unicode_buffer(1000000) + result = memmove(a, p, len(p) * sizeof(c_wchar)) + assert a.value == "Hello, World" + + assert wstring_at(a) == "Hello, World" + assert wstring_at(a, 5) == "Hello" + assert wstring_at(a, 16) == "Hello, World\0\0\0\0" + assert wstring_at(a, 0) == "" + From fijal at codespeak.net Tue Jan 22 12:52:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 12:52:00 +0100 (CET) Subject: [pypy-svn] r50867 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122115200.8C51716854C@codespeak.net> Author: fijal Date: Tue Jan 22 12:52:00 2008 New Revision: 50867 Added: pypy/dist/pypy/lib/_ctypes/builtin.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/__init__.py pypy/dist/pypy/lib/_ctypes/dummy.py pypy/dist/pypy/lib/_ctypes/function.py Log: Support for some builtin functions. Modified: pypy/dist/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/__init__.py (original) +++ pypy/dist/pypy/lib/_ctypes/__init__.py Tue Jan 22 12:52:00 2008 @@ -1,7 +1,5 @@ from _ctypes.dummy import Union from _ctypes.dummy import resize -from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr - from _ctypes.basics import _CData, sizeof, alignment, byref, addressof,\ ArgumentError from _ctypes.primitive import _SimpleCData @@ -10,6 +8,7 @@ from _ctypes.dll import dlopen from _ctypes.structure import Structure from _ctypes.array import Array +from _ctypes.builtin import _memmove_addr, _string_at_addr, _memset_addr __version__ = '1.0.2' #XXX platform dependant? Added: pypy/dist/pypy/lib/_ctypes/builtin.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/_ctypes/builtin.py Tue Jan 22 12:52:00 2008 @@ -0,0 +1,12 @@ + +import _rawffi, sys + +_memmove_addr = ('memmove', 'libc.so.6') +_memset_addr = ('memset', 'libc.so.6') + +def _string_at_addr(addr, lgt): + # address here can be almost anything + import ctypes + obj = ctypes.c_char_p._CData_input(addr)[0] + return _rawffi.charp2rawstring(obj, lgt) + Modified: pypy/dist/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/dummy.py (original) +++ pypy/dist/pypy/lib/_ctypes/dummy.py Tue Jan 22 12:52:00 2008 @@ -8,5 +8,4 @@ EXPLODE resize = dummyfunc -_memset_addr = dummyfunc Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Tue Jan 22 12:52:00 2008 @@ -29,9 +29,12 @@ def _getrestype(self): return self._restype_ def _setrestype(self, restype): + if restype is int: + from ctypes import c_int + restype = c_int if not isinstance(restype, _CDataMeta) and not restype is None: raise TypeError("Expected ctypes type, got %s" % (restype,)) - self._restype_ = restype + self._restype_ = restype restype = property(_getrestype, _setrestype) def __init__(self, argument=None): @@ -49,6 +52,8 @@ elif isinstance(argument, tuple) and len(argument) == 2: import ctypes self.name, self.dll = argument + if isinstance(self.dll, str): + self.dll = ctypes.CDLL(self.dll) # we need to check dll anyway self._getfuncptr([], ctypes.c_int) elif argument is None: From fijal at codespeak.net Tue Jan 22 13:32:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 13:32:41 +0100 (CET) Subject: [pypy-svn] r50868 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080122123241.2AAE816854C@codespeak.net> Author: fijal Date: Tue Jan 22 13:32:40 2008 New Revision: 50868 Modified: pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Unskip few tests Modified: pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_pointers.py Tue Jan 22 13:32:40 2008 @@ -59,7 +59,7 @@ assert i.value == 54345 def test_callbacks_with_pointers(self): - py.test.skip("callbacks not supported") + py.test.skip("This test looks bogus (never checks anything)") # a function type receiving a pointer PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int)) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Tue Jan 22 13:32:40 2008 @@ -67,7 +67,6 @@ (calcsize("c%c0%c" % (code, code)), code)) def test_unions(self): - py.test.skip("No unions support") for code, tp in self.formats.items(): class X(Union): _fields_ = [("x", c_char), @@ -107,7 +106,6 @@ assert sizeof(XX) == calcsize("3s 3s 0s") def test_emtpy(self): - py.test.skip("No unions support") # I had problems with these # # Although these are patological cases: Empty Structures! @@ -144,7 +142,6 @@ raises((TypeError, AttributeError), setattr, X.x, "offset", 92) raises((TypeError, AttributeError), setattr, X.x, "size", 92) - py.test.skip("No unions support") class X(Union): _fields_ = [("x", c_int), ("y", c_char)] From fijal at codespeak.net Tue Jan 22 13:33:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 13:33:02 +0100 (CET) Subject: [pypy-svn] r50869 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122123302.4C16E16854C@codespeak.net> Author: fijal Date: Tue Jan 22 13:33:01 2008 New Revision: 50869 Added: pypy/dist/pypy/lib/_ctypes/union.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/__init__.py pypy/dist/pypy/lib/_ctypes/dummy.py pypy/dist/pypy/lib/_ctypes/structure.py Log: Rudimentary support for unions (they still does not work) Modified: pypy/dist/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/__init__.py (original) +++ pypy/dist/pypy/lib/_ctypes/__init__.py Tue Jan 22 13:33:01 2008 @@ -1,4 +1,3 @@ -from _ctypes.dummy import Union from _ctypes.dummy import resize from _ctypes.basics import _CData, sizeof, alignment, byref, addressof,\ ArgumentError @@ -9,6 +8,7 @@ from _ctypes.structure import Structure from _ctypes.array import Array from _ctypes.builtin import _memmove_addr, _string_at_addr, _memset_addr +from _ctypes.union import Union __version__ = '1.0.2' #XXX platform dependant? Modified: pypy/dist/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/dummy.py (original) +++ pypy/dist/pypy/lib/_ctypes/dummy.py Tue Jan 22 13:33:01 2008 @@ -1,9 +1,3 @@ -class UnionType(type): - pass - -class Union(object): - __metaclass__ = UnionType - def dummyfunc(*args, **kwargs): EXPLODE Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Tue Jan 22 13:33:01 2008 @@ -22,7 +22,13 @@ size = round_up(size, alignment) return size, alignment, pos -def names_and_fields(_fields_, superclass): + +def struct_getattr(self, name): + if hasattr(self, '_fieldtypes') and name in self._fieldtypes: + return self._fieldtypes[name] + return _CDataMeta.__getattribute__(self, name) + +def names_and_fields(_fields_, superclass, zero_offset=False): for _, tp in _fields_: if not isinstance(tp, _CDataMeta): raise TypeError("Expected CData subclass, got %s" % (tp,)) @@ -33,7 +39,10 @@ names = [name for name, ctype in all_fields] rawfields = [(name, ctype._ffishape) for name, ctype in all_fields] - _, _, pos = size_alignment_pos(all_fields) + if not zero_offset: + _, _, pos = size_alignment_pos(all_fields) + else: + pos = [0] * len(all_fields) fields = {} for i, (name, ctype) in enumerate(all_fields): fields[name] = Field(name, pos[i], ctypes.sizeof(ctype), ctype) @@ -78,6 +87,8 @@ return res + __getattr__ = struct_getattr + def __setattr__(self, name, value): if name == '_fields_': if self.__dict__.get('_fields_', None): @@ -92,12 +103,6 @@ return _CDataMeta.__setattr__(self, name, value) - def __getattr__(self, name): - if hasattr(self, '_fieldtypes') and name in self._fieldtypes: - return self._fieldtypes[name] - return _CDataMeta.__getattribute__(self, name) - #return Field(name, - def from_address(self, address): instance = self.__new__(self) instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address) Added: pypy/dist/pypy/lib/_ctypes/union.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/_ctypes/union.py Tue Jan 22 13:33:01 2008 @@ -0,0 +1,29 @@ + + +import _rawffi +from _ctypes.basics import _CData, _CDataMeta +from _ctypes.structure import round_up, names_and_fields, struct_getattr +import inspect + +class UnionMeta(_CDataMeta): + def __new__(self, name, cls, typedict): + res = type.__new__(self, name, cls, typedict) + if '_fields_' in typedict: + res._names, rawfields, res._fieldtypes = names_and_fields( + typedict['_fields_'], cls[0], True) + + return res + + def _sizeofinstances(self): + return max([field.size for field in self._fieldtypes.values()] + + [0]) + + def _alignmentofinstances(self): + return max([field.alignment for field in self._fieldtypes.values()] + + [1]) + + __getattr__ = struct_getattr + +class Union(_CData): + __metaclass__ = UnionMeta + _ffiletter = 'P' From cfbolz at codespeak.net Tue Jan 22 13:51:37 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 22 Jan 2008 13:51:37 +0100 (CET) Subject: [pypy-svn] r50870 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122125137.0EACE168552@codespeak.net> Author: cfbolz Date: Tue Jan 22 13:51:36 2008 New Revision: 50870 Modified: pypy/dist/pypy/lib/_ctypes/dummy.py Log: raise proper error, not obscure NameError Modified: pypy/dist/pypy/lib/_ctypes/dummy.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/dummy.py (original) +++ pypy/dist/pypy/lib/_ctypes/dummy.py Tue Jan 22 13:51:36 2008 @@ -1,5 +1,5 @@ def dummyfunc(*args, **kwargs): - EXPLODE + raise NotImplementedError("non-implemented ctypes function") resize = dummyfunc From fijal at codespeak.net Tue Jan 22 13:53:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 13:53:54 +0100 (CET) Subject: [pypy-svn] r50871 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080122125354.EA05A168552@codespeak.net> Author: fijal Date: Tue Jan 22 13:53:54 2008 New Revision: 50871 Added: pypy/dist/pypy/lib/app_test/ctypes/test_unions.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/union.py Log: Some more unions support Modified: pypy/dist/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/union.py (original) +++ pypy/dist/pypy/lib/_ctypes/union.py Tue Jan 22 13:53:54 2008 @@ -11,19 +11,52 @@ if '_fields_' in typedict: res._names, rawfields, res._fieldtypes = names_and_fields( typedict['_fields_'], cls[0], True) - + res._ffishape = (res._sizeofinstances(), + res._alignmentofinstances()) + # we need to create an array of size one for each + # of our elements + res._ffiarrays = {} + for name, field in res._fieldtypes.iteritems(): + res._ffiarrays[name] = _rawffi.Array(field.ctype._ffishape) + def __init__(self): # don't allow arguments by now + # malloc size + size = self.__class__._sizeofinstances() + self.__dict__['_buffer'] = _rawffi.Array('c')(size) + res.__init__ = __init__ return res def _sizeofinstances(self): - return max([field.size for field in self._fieldtypes.values()] - + [0]) + if not hasattr(self, '_size_'): + self._size_ = max([field.size for field in + self._fieldtypes.values()] + [0]) + return self._size_ def _alignmentofinstances(self): - return max([field.alignment for field in self._fieldtypes.values()] - + [1]) + from ctypes import alignment + if not hasattr(self, '_alignment_'): + self._alignment_ = max([alignment(field.ctype) for field in + self._fieldtypes.values()] + [1]) + return self._alignment_ __getattr__ = struct_getattr class Union(_CData): __metaclass__ = UnionMeta _ffiletter = 'P' + + def __getattr__(self, name): + try: + fieldtype = self._fieldtypes[name].ctype + except KeyError: + raise AttributeError(name) + val = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)[0] + return fieldtype._CData_output(val) + + def __setattr__(self, name, value): + try: + fieldtype = self._fieldtypes[name].ctype + except KeyError: + raise AttributeError(name) + value = fieldtype._CData_input(value) + buf = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1) + buf[0] = value[0] Added: pypy/dist/pypy/lib/app_test/ctypes/test_unions.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_unions.py Tue Jan 22 13:53:54 2008 @@ -0,0 +1,12 @@ + +from ctypes import * + +class TestUnion: + def test_getattr(self): + class Stuff(Union): + _fields_ = [('x', c_char), ('y', c_int)] + + stuff = Stuff() + stuff.y = ord('x') + assert stuff.x == 'x' + From fijal at codespeak.net Tue Jan 22 13:54:39 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 13:54:39 +0100 (CET) Subject: [pypy-svn] r50872 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122125439.CF44C168554@codespeak.net> Author: fijal Date: Tue Jan 22 13:54:39 2008 New Revision: 50872 Modified: pypy/dist/pypy/lib/_ctypes/array.py Log: Don't treat getslice on arrays as always returning strings (yay, test needed) Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Tue Jan 22 13:54:39 2008 @@ -84,7 +84,10 @@ def _slice_getitem(self, index): start, stop = self._get_slice_params(index) - return "".join([self[i] for i in range(start, stop)]) + l = [self[i] for i in range(start, stop)] + if getattr(self._type_, '_type_', None) == 'c': + return "".join(l) + return l def _subarray(self, index): """Return a _rawffi array of length 1 whose address is the same as From fijal at codespeak.net Tue Jan 22 13:55:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 13:55:59 +0100 (CET) Subject: [pypy-svn] r50873 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122125559.2BFDE168554@codespeak.net> Author: fijal Date: Tue Jan 22 13:55:58 2008 New Revision: 50873 Modified: pypy/dist/pypy/lib/_ctypes/basics.py Log: Be on the safe side Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Tue Jan 22 13:55:58 2008 @@ -32,7 +32,7 @@ and this returns a general Python object that corresponds. """ res = self.__new__(self) - res._buffer = resarray + res.__dict__['_buffer'] = resarray return res.__ctypes_from_outparam__() def __mul__(self, other): From fijal at codespeak.net Tue Jan 22 14:00:19 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 14:00:19 +0100 (CET) Subject: [pypy-svn] r50875 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080122130019.58B1E168563@codespeak.net> Author: fijal Date: Tue Jan 22 14:00:14 2008 New Revision: 50875 Modified: pypy/dist/pypy/lib/_ctypes/basics.py pypy/dist/pypy/lib/_ctypes/union.py Log: Assert and a fix Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Tue Jan 22 14:00:14 2008 @@ -27,6 +27,7 @@ return cobj._get_buffer_for_param() def _CData_output(self, resarray): + assert isinstance(resarray, _rawffi.ArrayInstance) """Used when data exits ctypes and goes into user code. 'resarray' is a _rawffi array of length 1 containing the value, and this returns a general Python object that corresponds. Modified: pypy/dist/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/union.py (original) +++ pypy/dist/pypy/lib/_ctypes/union.py Tue Jan 22 14:00:14 2008 @@ -49,7 +49,7 @@ fieldtype = self._fieldtypes[name].ctype except KeyError: raise AttributeError(name) - val = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)[0] + val = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1) return fieldtype._CData_output(val) def __setattr__(self, name, value): From fijal at codespeak.net Tue Jan 22 14:10:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 14:10:20 +0100 (CET) Subject: [pypy-svn] r50877 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080122131020.3D55016850E@codespeak.net> Author: fijal Date: Tue Jan 22 14:10:19 2008 New Revision: 50877 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_unions.py Log: unions of structures, a test and support Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Tue Jan 22 14:10:19 2008 @@ -116,6 +116,13 @@ def _alignmentofinstances(self): return self._ffistruct.alignment + def _CData_output(self, resarray): + assert isinstance(resarray, _rawffi.ArrayInstance) + res = self.__new__(self) + ffistruct = self._ffistruct.fromaddress(resarray.buffer) + res.__dict__['_buffer'] = ffistruct + return res.__ctypes_from_outparam__() + class Structure(_CData): __metaclass__ = StructureMeta _ffiletter = 'P' Modified: pypy/dist/pypy/lib/app_test/ctypes/test_unions.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_unions.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_unions.py Tue Jan 22 14:10:19 2008 @@ -10,3 +10,18 @@ stuff.y = ord('x') assert stuff.x == 'x' + def test_union_of_structures(self): + class Stuff(Structure): + _fields_ = [('x', c_int)] + + class Stuff2(Structure): + _fields_ = [('x', c_int)] + + class UnionofStuff(Union): + _fields_ = [('one', Stuff), + ('two', Stuff2)] + + u = UnionofStuff() + u.one.x = 3 + assert u.two.x == 3 + From arigo at codespeak.net Tue Jan 22 14:13:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 22 Jan 2008 14:13:45 +0100 (CET) Subject: [pypy-svn] r50878 - pypy/branch/loops-for-gcc/pypy/translator/c Message-ID: <20080122131345.3DFCA168554@codespeak.net> Author: arigo Date: Tue Jan 22 14:13:44 2008 New Revision: 50878 Modified: pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py Log: Obscure and not really tested logic. Modified: pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py (original) +++ pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py Tue Jan 22 14:13:44 2008 @@ -34,6 +34,7 @@ functionname currentblock blocknum + backlinks oldgraph""".split() def __init__(self, graph, db, exception_policy=None, functionname=None): @@ -112,14 +113,58 @@ self.db.gctransformer.inline_helpers(graph) return graph + def order_blocks(self): + from pypy.tool.algo import graphlib + self.blocknum = {} + self.backlinks = {} + vertices = {} + edge_list = [] + for index, block in enumerate(self.graph.iterblocks()): + self.blocknum[block] = index + vertices[block] = True + for link in block.exits: + edge_list.append(graphlib.Edge(block, link.target)) + edges = graphlib.make_edge_dict(edge_list) + cycles = graphlib.all_cycles(self.graph.startblock, vertices, edges) + cycles.sort(key=len) + for cycle in cycles: + for edge in cycle: + if edge.source not in vertices: + break # cycle overlaps already-seen blocks + else: + # make this cycle a C-level loop + def edge2link(edge): + for link in edge.source.exits: + if link.target is edge.target: + return link + raise AssertionError("an edge's link has gone missing") + + edges = [] + for i, edge in enumerate(cycle): + v = edge.source.exitswitch + if isinstance(v, Variable) and len(edge.source.exits) == 2: + TYPE = self.lltypemap(v) + if TYPE in (Bool, PyObjPtr): + edges.append((self.blocknum[edge.source], i)) + if not edges: + continue + _, i = min(edges) + backedge = cycle[i-1] + forwardedge = cycle[i] + headblock = backedge.target + assert headblock is forwardedge.source + self.backlinks[edge2link(backedge)] = None + exitcase = edge2link(forwardedge).exitcase + assert exitcase in (False, True) + self.backlinks[headblock] = exitcase + for edge in cycle: + del vertices[edge.target] + def implementation_begin(self): self.oldgraph = self.graph self.graph = self.patch_graph(copy_graph=True) SSI_to_SSA(self.graph) self.collect_var_and_types() - self.blocknum = {} - for block in self.graph.iterblocks(): - self.blocknum[block] = len(self.blocknum) db = self.db lltypes = {} for v in self.vars: @@ -127,6 +172,7 @@ typename = db.gettype(T) lltypes[id(v)] = T, typename self.lltypes = lltypes + self.order_blocks() def graphs_to_patch(self): yield self.graph @@ -135,6 +181,7 @@ self.lltypes = None self.vars = None self.blocknum = None + self.backlinks = None self.currentblock = None self.graph = self.oldgraph del self.oldgraph @@ -204,9 +251,10 @@ graph = self.graph # generate the body of each block - for block in graph.iterblocks(): + allblocks = [(num, block) for (block, num) in self.blocknum.items()] + allblocks.sort() + for myblocknum, block in allblocks: self.currentblock = block - myblocknum = self.blocknum[block] yield '' yield 'block%d:' % myblocknum for i, op in enumerate(block.operations): @@ -231,6 +279,25 @@ assert len(block.exits) == 1 for op in self.gen_link(block.exits[0]): yield op + elif block in self.backlinks: + looplink, exitlink = block.exits + if looplink.exitcase != self.backlinks[block]: + looplink, exitlink = exitlink, looplink + assert looplink.exitcase == self.backlinks[block] + assert exitlink.exitcase == (not self.backlinks[block]) + expr = self.expr(block.exitswitch) + if not looplink.exitcase: + expr = '!' + expr + yield 'while (%s) {' % expr + for op in self.gen_link(looplink): + yield '\t' + op + yield '\t block%d_back:' % myblocknum + for i, op in enumerate(block.operations): + for line in self.gen_op(op): + yield '\t' + line + yield '}' + for op in self.gen_link(exitlink): + yield op else: assert block.exitswitch != c_last_exception # block ending in a switch on a value @@ -303,7 +370,10 @@ assignments.append((a2typename, dest, src)) for line in gen_assignments(assignments): yield line - yield 'goto block%d;' % self.blocknum[link.target] + label = 'block%d' % self.blocknum[link.target] + if link in self.backlinks: + label += '_back' + yield 'goto %s;' % label def gen_op(self, op): macro = 'OP_%s' % op.opname.upper() From fijal at codespeak.net Tue Jan 22 14:22:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 14:22:23 +0100 (CET) Subject: [pypy-svn] r50879 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080122132223.5918816850E@codespeak.net> Author: fijal Date: Tue Jan 22 14:22:22 2008 New Revision: 50879 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Some patology and a test for it Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Tue Jan 22 14:22:22 2008 @@ -142,11 +142,13 @@ value = fieldtype._CData_input(value) self._buffer.__setattr__(name, value[0]) - def __getattr__(self, name): + def __getattribute__(self, name): + if name == '_fieldtypes': + return _CData.__getattribute__(self, '_fieldtypes') try: fieldtype = self._fieldtypes[name].ctype except KeyError: - raise AttributeError(name) + return _CData.__getattribute__(self, name) return fieldtype._CData_output(self._subarray(fieldtype, name)) def _get_buffer_for_param(self): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Tue Jan 22 14:22:22 2008 @@ -420,3 +420,14 @@ else: raise AssertionError, "AttributeError not raised" + +class TestPatologicalCases: + def test_structure_overloading_getattr(self): + class X(Structure): + _fields_ = [('x', c_int)] + + def __getattr__(self, name): + raise AttributeError, name + + x = X() + assert x.x == 0 From fijal at codespeak.net Tue Jan 22 14:35:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 14:35:18 +0100 (CET) Subject: [pypy-svn] r50880 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080122133518.C4002168552@codespeak.net> Author: fijal Date: Tue Jan 22 14:35:16 2008 New Revision: 50880 Modified: pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/app_test/ctypes/test_array.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: * Support for array of structures * Make skip messages more elaborate Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Tue Jan 22 14:35:16 2008 @@ -101,7 +101,14 @@ return value = self._type_._CData_input(value) index = self._fix_index(index) - self._buffer[index] = value[0] + if not isinstance(self._type_._ffishape, tuple): + self._buffer[index] = value[0] + # something more sophisticated, cannot set field directly + else: + from ctypes import memmove + dest = self._buffer.itemaddress(index) + source = value[0] + memmove(dest, source, self._type_._ffishape[0]) def __getitem__(self, index): if isinstance(index, slice): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_array.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_array.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_array.py Tue Jan 22 14:35:16 2008 @@ -108,3 +108,16 @@ sz = (c_wchar * 3).from_address(addressof(p)) assert sz[:] == "foo" assert sz.value == "foo" + +class TestSophisticatedThings: + def test_array_of_structures(self): + class X(Structure): + _fields_ = [('x', c_int), ('y', c_int)] + + Y = X * 2 + y = Y() + x = X() + x.y = 3 + y[1] = x + assert y[1].y == 3 + Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Tue Jan 22 14:35:16 2008 @@ -202,7 +202,7 @@ raises(ValueError, type(Structure), "X", (Structure,), d) def test_initializers(self): - py.test.skip("unsupported") + py.test.skip("Structures with inlined arrays") class Person(Structure): _fields_ = [("name", c_char*6), ("age", c_int)] @@ -234,7 +234,7 @@ raises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)]) def test_intarray_fields(self): - py.test.skip("unsupported") + py.test.skip("Structures with inlined arrays") class SomeInts(Structure): _fields_ = [("a", c_int * 4)] @@ -431,3 +431,4 @@ x = X() assert x.x == 0 + From fijal at codespeak.net Tue Jan 22 17:00:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 17:00:36 +0100 (CET) Subject: [pypy-svn] r50881 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080122160036.EB2D016855A@codespeak.net> Author: fijal Date: Tue Jan 22 17:00:35 2008 New Revision: 50881 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: rffi.getintfield helper, if we don't want to touch lltype magic. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Tue Jan 22 17:00:35 2008 @@ -651,3 +651,10 @@ assert isinstance(TDST, lltype.Number) setattr(pdst, fieldname, cast(TDST, value)) setintfield._annspecialcase_ = 'specialize:ll_and_arg(1)' + +def getintfield(pdst, fieldname): + """As temporary as previous: get integer from a field in structure, + casting it to lltype.Signed + """ + return cast(lltype.Signed, getattr(pdst, fieldname)) +getintfield._annspecialcase_ = 'specialize:ll_and_arg(1)' From fijal at codespeak.net Tue Jan 22 17:03:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 17:03:27 +0100 (CET) Subject: [pypy-svn] r50882 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080122160327.F068916855A@codespeak.net> Author: fijal Date: Tue Jan 22 17:03:27 2008 New Revision: 50882 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: Adapt this test to work on 64 bit as well. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Tue Jan 22 17:03:27 2008 @@ -481,8 +481,10 @@ graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - assert s == {'cast_int_to_uint': 1, 'direct_call': 1, 'cast_primitive': 2, - 'cast_int_to_float': 1} + expected = {'cast_int_to_uint': 1, 'direct_call': 1, + 'cast_primitive': 2, 'cast_int_to_float': 1} + for k, v in expected.items(): + assert s[k] == v def test_stringpolicy1(self): eci = ExternalCompilationInfo(includes=['string.h']) From fijal at codespeak.net Tue Jan 22 17:04:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 17:04:04 +0100 (CET) Subject: [pypy-svn] r50883 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080122160404.C645B16855A@codespeak.net> Author: fijal Date: Tue Jan 22 17:04:03 2008 New Revision: 50883 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: Automatic casts of external function calls. Helps a bit with rffi on 64 bit when int is 32 bit. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Tue Jan 22 17:04:03 2008 @@ -140,13 +140,18 @@ if before: before() # NB. it is essential that no exception checking occurs after # the call to before(), because we don't have the GIL any more! - result = funcptr(*real_args) + res = funcptr(*real_args) if invoke_around_handlers: if after: after() for i, TARGET in unrolling_arg_tps: if to_free[i]: lltype.free(to_free[i], flavor='raw') - return result + if rarithmetic.r_int is not r_int: + if result is INT: + return cast(lltype.Signed, res) + elif result is UINT: + return cast(lltype.Unsigned, res) + return res wrapper._annspecialcase_ = 'specialize:ll' wrapper._always_inline_ = True # for debugging, stick ll func ptr to that From fijal at codespeak.net Tue Jan 22 17:27:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 17:27:56 +0100 (CET) Subject: [pypy-svn] r50884 - pypy/dist/pypy/objspace/std Message-ID: <20080122162756.D622C16856E@codespeak.net> Author: fijal Date: Tue Jan 22 17:27:56 2008 New Revision: 50884 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: Be a bit more precise. Otherwise it cannot be wrapped and explodes in a very strange manner. Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Tue Jan 22 17:27:56 2008 @@ -13,7 +13,8 @@ from pypy.objspace.std.multimethod import FailedToImplement from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std import stdtypedef -from pypy.rlib.rarithmetic import base_int +from pypy.rlib.rarithmetic import base_int, r_int, r_uint, \ + r_longlong, r_ulonglong from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.jit import hint, we_are_jitted import sys @@ -425,7 +426,7 @@ w_result = x.__spacebind__(self) #print 'wrapping', x, '->', w_result return w_result - if isinstance(x, base_int): + if isinstance(x, (r_int, r_uint, r_longlong, r_ulonglong)): return W_LongObject.fromrarith_int(x) # _____ below here is where the annotator should not get _____ From fijal at codespeak.net Tue Jan 22 17:34:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 17:34:37 +0100 (CET) Subject: [pypy-svn] r50885 - pypy/dist/pypy/objspace/std Message-ID: <20080122163437.5F805169E2A@codespeak.net> Author: fijal Date: Tue Jan 22 17:34:35 2008 New Revision: 50885 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: Confuse annotator less (This would soon go away anyway) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Tue Jan 22 17:34:35 2008 @@ -426,7 +426,8 @@ w_result = x.__spacebind__(self) #print 'wrapping', x, '->', w_result return w_result - if isinstance(x, (r_int, r_uint, r_longlong, r_ulonglong)): + if isinstance(x, r_int) or isinstance(x, r_uint) or \ + isinstance(x, r_longlong) or isinstance(x, r_ulonglong): return W_LongObject.fromrarith_int(x) # _____ below here is where the annotator should not get _____ From fijal at codespeak.net Tue Jan 22 18:12:15 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 18:12:15 +0100 (CET) Subject: [pypy-svn] r50886 - pypy/dist/pypy/rlib Message-ID: <20080122171215.AA528169E2A@codespeak.net> Author: fijal Date: Tue Jan 22 18:12:14 2008 New Revision: 50886 Modified: pypy/dist/pypy/rlib/rsocket.py Log: Make rsocket 64bit compatible Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Tue Jan 22 18:12:14 2008 @@ -523,7 +523,7 @@ fd = _c.INVALID_SOCKET def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0): """Create a new socket.""" - fd = intmask(_c.socket(family, type, proto)) + fd = _c.socket(family, type, proto) if _c.invalid_socket(fd): raise self.error_handler() # PLAT RISCOS @@ -642,7 +642,7 @@ address.unlock() if _c.invalid_socket(newfd): raise self.error_handler() - address.addrlen = addrlen + address.addrlen = rffi.cast(lltype.Signed, addrlen) sock = make_socket(newfd, self.family, self.type, self.proto, SocketClass) return (sock, address) @@ -735,7 +735,7 @@ address.unlock() if res < 0: raise self.error_handler() - address.addrlen = addrlen + address.addrlen = rffi.cast(lltype.Signed, addrlen) return address def getsockname(self): @@ -749,7 +749,7 @@ address.unlock() if res < 0: raise self.error_handler() - address.addrlen = addrlen + address.addrlen = rffi.cast(lltype.Signed, addrlen) return address def getsockopt(self, level, option, maxlen): @@ -762,7 +762,7 @@ buf, bufsize_p) if res < 0: raise self.error_handler() - size = bufsize_p[0] + size = rffi.cast(lltype.Signed, bufsize_p[0]) assert size >= 0 # socklen_t is signed on Windows result = ''.join([buf[i] for i in range(size)]) finally: @@ -782,7 +782,7 @@ flagsize_p) if res < 0: raise self.error_handler() - result = flag_p[0] + result = rffi.cast(lltype.Signed, flag_p[0]) finally: lltype.free(flagsize_p, flavor='raw') finally: @@ -838,7 +838,7 @@ try: read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags, addr_p, addrlen_p) - addrlen = addrlen_p[0] + addrlen = rffi.cast(lltype.Signed, addrlen_p[0]) finally: lltype.free(addrlen_p, flavor='raw') address.unlock() @@ -1031,8 +1031,8 @@ res = _c.socketpair(family, type, proto, result) if res < 0: raise last_error() - fd0 = result[0] - fd1 = result[1] + fd0 = rffi.cast(lltype.Signed, result[0]) + fd1 = rffi.cast(lltype.Signed, result[1]) lltype.free(result, flavor='raw') return (make_socket(fd0, family, type, proto, SocketClass), make_socket(fd1, family, type, proto, SocketClass)) @@ -1069,7 +1069,7 @@ def gethost_common(hostname, hostent, addr=None): if not hostent: raise HSocketError(hostname) - family = hostent.c_h_addrtype + family = rffi.getintfield(hostent, 'c_h_addrtype') if addr is not None and addr.family != family: raise CSocketError(_c.EAFNOSUPPORT) @@ -1135,7 +1135,8 @@ result = [] info = res while info: - addr = make_address(info.c_ai_addr, info.c_ai_addrlen, + addr = make_address(info.c_ai_addr, + rffi.getintfield(info, 'c_ai_addrlen'), address_to_fill) if info.c_ai_canonname: canonname = rffi.charp2str(info.c_ai_canonname) @@ -1207,7 +1208,7 @@ if ip == "255.255.255.255": return "\xff\xff\xff\xff" packed_addr = _c.inet_addr(ip) - if packed_addr == rffi.cast(rffi.UINT, INADDR_NONE): + if packed_addr == rffi.cast(lltype.Unsigned, INADDR_NONE): raise RSocketError("illegal IP address string passed to inet_aton") size = sizeof(_c.in_addr) buf = mallocbuf(size) From fijal at codespeak.net Tue Jan 22 18:32:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 18:32:17 +0100 (CET) Subject: [pypy-svn] r50887 - pypy/dist/pypy/module/bz2 Message-ID: <20080122173217.14548169E3D@codespeak.net> Author: fijal Date: Tue Jan 22 18:32:16 2008 New Revision: 50887 Modified: pypy/dist/pypy/module/bz2/interp_bz2.py Log: Make bz2 modules 64bit-ready Modified: pypy/dist/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/dist/pypy/module/bz2/interp_bz2.py (original) +++ pypy/dist/pypy/module/bz2/interp_bz2.py Tue Jan 22 18:32:16 2008 @@ -91,14 +91,16 @@ if BZ_CONFIG_ERROR: if rffi.sizeof(rffi.LONG) >= 8: def _bzs_total_out(bzs): - return (bzs.c_total_out_hi32 << 32) + bzs.c_total_out_lo32 + return (rffi.getintfield(bzs, 'c_total_out_hi32') << 32) + \ + rffi.getintfield(bzs, 'c_total_out_lo32') else: # we can't return a long long value from here, because most # callers wouldn't be able to handle it anyway def _bzs_total_out(bzs): - if bzs.c_total_out_hi32 != 0 or bzs.c_total_out_lo32 > sys.maxint: + if rffi.getintfield(bzs, 'c_total_out_hi32') != 0 or \ + rffi.getintfield(bzs, 'c_total_out_lo32') > sys.maxint: raise MemoryError - return bzs.c_total_out_lo32 + return rffi.getintfield(bzs, 'c_total_out_lo32') else: XXX # this case needs fixing (old bz2 library?) def _bzs_total_out(bzs): @@ -457,9 +459,9 @@ try: self.bzs.c_next_in = in_buf - self.bzs.c_avail_in = rffi.cast(rffi.UINT, in_bufsize) + rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize) self.bzs.c_next_out = out_buf - self.bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) temp = [] while True: @@ -467,9 +469,9 @@ if bzerror != BZ_RUN_OK: _catch_bz2_error(self.space, bzerror) - if self.bzs.c_avail_in == 0: + if rffi.getintfield(self.bzs, 'c_avail_in') == 0: break - elif self.bzs.c_avail_out == 0: + elif rffi.getintfield(self.bzs, 'c_avail_out') == 0: total_out = _bzs_total_out(self.bzs) data = "".join([out_buf[i] for i in range(total_out)]) temp.append(data) @@ -479,7 +481,7 @@ out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', zero=True) self.bzs.c_next_out = out_buf - self.bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) if temp: total_out = _bzs_total_out(self.bzs) @@ -509,7 +511,7 @@ try: self.bzs.c_next_out = out_buf - self.bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) total_out = _bzs_total_out(self.bzs) @@ -521,7 +523,7 @@ elif bzerror != BZ_FINISH_OK: _catch_bz2_error(self.space, bzerror) - if self.bzs.c_avail_out == 0: + if rffi.getintfield(self.bzs, 'c_avail_out') == 0: data = "".join([out_buf[i] for i in range(_bzs_total_out(self.bzs))]) temp.append(data) @@ -529,12 +531,12 @@ out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', zero=True) self.bzs.c_next_out = out_buf - self.bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) if temp: return self.space.wrap("".join(temp)) - if self.bzs.c_avail_out: + if rffi.getintfield(self.bzs, 'c_avail_out'): size = _bzs_total_out(self.bzs) - total_out res = "".join([out_buf[i] for i in range(size)]) return self.space.wrap(res) @@ -615,25 +617,25 @@ try: self.bzs.c_next_in = in_buf - self.bzs.c_avail_in = rffi.cast(rffi.UINT, in_bufsize) + rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize) self.bzs.c_next_out = out_buf - self.bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) temp = [] while True: bzerror = BZ2_bzDecompress(self.bzs) if bzerror == BZ_STREAM_END: - if self.bzs.c_avail_in != 0: - unused = [self.bzs.c_next_in[i] for i in range(self.bzs.c_avail_in)] + if rffi.getintfield(self.bzs, 'c_avail_in') != 0: + unused = [self.bzs.c_next_in[i] for i in range(rffi.getintfield(self.bzs, 'c_avail_in'))] self.unused_data = "".join(unused) self.running = False break if bzerror != BZ_OK: _catch_bz2_error(self.space, bzerror) - if self.bzs.c_avail_in == 0: + if rffi.getintfield(self.bzs, 'c_avail_in') == 0: break - elif self.bzs.c_avail_out == 0: + elif rffi.getintfield(self.bzs, 'c_avail_out') == 0: total_out = _bzs_total_out(self.bzs) data = "".join([out_buf[i] for i in range(total_out)]) temp.append(data) @@ -642,7 +644,7 @@ out_bufsize = _new_buffer_size(out_bufsize) out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw') self.bzs.c_next_out = out_buf - self.bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(self.bzs, 'c_avail_out', out_bufsize) if temp: total_out = _bzs_total_out(self.bzs) @@ -693,9 +695,9 @@ try: bzs.c_next_in = in_buf - bzs.c_avail_in = rffi.cast(rffi.UINT, in_bufsize) + rffi.setintfield(bzs, 'c_avail_in', in_bufsize) bzs.c_next_out = out_buf - bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(bzs, 'c_avail_out', out_bufsize) bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0) if bzerror != BZ_OK: @@ -711,7 +713,7 @@ BZ2_bzCompressEnd(bzs) _catch_bz2_error(space, bzerror) - if bzs.c_avail_out == 0: + if rffi.getintfield(bzs, 'c_avail_out') == 0: data = "".join([out_buf[i] for i in range(_bzs_total_out(bzs))]) temp.append(data) @@ -720,12 +722,12 @@ out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', zero=True) bzs.c_next_out = out_buf - bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(bzs, 'c_avail_out', out_bufsize) if temp: res = "".join(temp) - if bzs.c_avail_out: + if rffi.getintfield(bzs, 'c_avail_out'): size = _bzs_total_out(bzs) - total_out res = "".join([out_buf[i] for i in range(size)]) else: @@ -762,9 +764,9 @@ bzs.c_next_in = in_buf - bzs.c_avail_in = rffi.cast(rffi.UINT, in_bufsize) + rffi.setintfield(bzs, 'c_avail_in', in_bufsize) bzs.c_next_out = out_buf - bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(bzs, 'c_avail_out', out_bufsize) bzerror = BZ2_bzDecompressInit(bzs, 0, 0) if bzerror != BZ_OK: @@ -779,11 +781,11 @@ BZ2_bzDecompressEnd(bzs) _catch_bz2_error(space, bzerror) - if bzs.c_avail_in == 0: + if rffi.getintfield(bzs, 'c_avail_in') == 0: BZ2_bzDecompressEnd(bzs) raise OperationError(space.w_ValueError, space.wrap("couldn't find end of stream")) - elif bzs.c_avail_out == 0: + elif rffi.getintfield(bzs, 'c_avail_out') == 0: total_out = _bzs_total_out(bzs) data = "".join([out_buf[i] for i in range(total_out)]) temp.append(data) @@ -793,7 +795,7 @@ out_buf = lltype.malloc(rffi.CCHARP.TO, out_bufsize, flavor='raw', zero=True) bzs.c_next_out = out_buf - bzs.c_avail_out = rffi.cast(rffi.UINT, out_bufsize) + rffi.setintfield(bzs, 'c_avail_out', out_bufsize) total_out = _bzs_total_out(bzs) if temp: From fijal at codespeak.net Tue Jan 22 18:56:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 22 Jan 2008 18:56:32 +0100 (CET) Subject: [pypy-svn] r50888 - pypy/dist/pypy/module/rctime Message-ID: <20080122175632.CD93F16855E@codespeak.net> Author: fijal Date: Tue Jan 22 18:56:31 2008 New Revision: 50888 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: Make rctime 64 bit 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 Jan 22 18:56:31 2008 @@ -172,15 +172,15 @@ def _tm_to_tuple(space, t): time_tuple = [] - time_tuple.append(space.wrap(t.c_tm_year + 1900)) - time_tuple.append(space.wrap(t.c_tm_mon + 1)) # want january == 1 - time_tuple.append(space.wrap(t.c_tm_mday)) - time_tuple.append(space.wrap(t.c_tm_hour)) - time_tuple.append(space.wrap(t.c_tm_min)) - time_tuple.append(space.wrap(t.c_tm_sec)) - time_tuple.append(space.wrap((t.c_tm_wday + 6) % 7)) # want monday == 0 - time_tuple.append(space.wrap(t.c_tm_yday + 1)) # want january, 1 == 1 - time_tuple.append(space.wrap(t.c_tm_isdst)) + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_year') + 1900)) + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_mon') + 1)) # want january == 1 + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_mday')) ) + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_hour')) ) + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_min')) ) + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_sec')) ) + time_tuple.append(space.wrap((rffi.getintfield(t, 'c_tm_wday') + 6) % 7)) # want monday == 0 + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_yday') + 1)) # want january, 1 == 1 + time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_isdst')) ) w_struct_time = _get_module_object(space, 'struct_time') w_time_tuple = space.newtuple(time_tuple) @@ -235,14 +235,17 @@ raise OperationError(space.w_ValueError, space.wrap("year out of range")) - if glob_buf.c_tm_wday < 0: + if rffi.getintfield(glob_buf, 'c_tm_wday') < 0: raise OperationError(space.w_ValueError, space.wrap("day of week out of range")) rffi.setintfield(glob_buf, 'c_tm_year', y - 1900) - rffi.setintfield(glob_buf, 'c_tm_mon', glob_buf.c_tm_mon - 1) - rffi.setintfield(glob_buf, 'c_tm_wday', (glob_buf.c_tm_wday + 1) % 7) - rffi.setintfield(glob_buf, 'c_tm_yday', glob_buf.c_tm_yday - 1) + rffi.setintfield(glob_buf, 'c_tm_mon', + rffi.getintfield(glob_buf, 'c_tm_mon') - 1) + rffi.setintfield(glob_buf, 'c_tm_wday', + (rffi.getintfield(glob_buf, 'c_tm_wday') + 1) % 7) + rffi.setintfield(glob_buf, 'c_tm_yday', + rffi.getintfield(glob_buf, 'c_tm_yday') - 1) return glob_buf @@ -398,25 +401,25 @@ # indexing blindly into some array for a textual representation # by some bad index (fixes bug #897625). # No check for year since handled in gettmarg(). - if buf_value.c_tm_mon < 0 or buf_value.c_tm_mon > 11: + if rffi.getintfield(buf_value, 'c_tm_mon') < 0 or rffi.getintfield(buf_value, 'c_tm_mon') > 11: raise OperationError(space.w_ValueError, space.wrap("month out of range")) - if buf_value.c_tm_mday < 1 or buf_value.c_tm_mday > 31: + if rffi.getintfield(buf_value, 'c_tm_mday') < 1 or rffi.getintfield(buf_value, 'c_tm_mday') > 31: raise OperationError(space.w_ValueError, space.wrap("day of month out of range")) - if buf_value.c_tm_hour < 0 or buf_value.c_tm_hour > 23: + if rffi.getintfield(buf_value, 'c_tm_hour') < 0 or rffi.getintfield(buf_value, 'c_tm_hour') > 23: raise OperationError(space.w_ValueError, space.wrap("hour out of range")) - if buf_value.c_tm_min < 0 or buf_value.c_tm_min > 59: + if rffi.getintfield(buf_value, 'c_tm_min') < 0 or rffi.getintfield(buf_value, 'c_tm_min') > 59: raise OperationError(space.w_ValueError, space.wrap("minute out of range")) - if buf_value.c_tm_sec < 0 or buf_value.c_tm_sec > 61: + if rffi.getintfield(buf_value, 'c_tm_sec') < 0 or rffi.getintfield(buf_value, 'c_tm_sec') > 61: raise OperationError(space.w_ValueError, space.wrap("seconds out of range")) - if buf_value.c_tm_yday < 0 or buf_value.c_tm_yday > 365: + if rffi.getintfield(buf_value, 'c_tm_yday') < 0 or rffi.getintfield(buf_value, 'c_tm_yday') > 365: raise OperationError(space.w_ValueError, space.wrap("day of year out of range")) - if buf_value.c_tm_isdst < -1 or buf_value.c_tm_isdst > 1: + if rffi.getintfield(buf_value, 'c_tm_isdst') < -1 or rffi.getintfield(buf_value, 'c_tm_isdst') > 1: raise OperationError(space.w_ValueError, space.wrap("daylight savings flag out of range")) From exarkun at codespeak.net Tue Jan 22 23:09:34 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Tue, 22 Jan 2008 23:09:34 +0100 (CET) Subject: [pypy-svn] r50892 - pypy/build/buildbot Message-ID: <20080122220934.D47CC16856B@codespeak.net> Author: exarkun Date: Tue Jan 22 23:09:33 2008 New Revision: 50892 Modified: pypy/build/buildbot/pypy_status.py Log: a little hack to make testing easier; also omit builders with absolutely no results Modified: pypy/build/buildbot/pypy_status.py ============================================================================== --- pypy/build/buildbot/pypy_status.py (original) +++ pypy/build/buildbot/pypy_status.py Tue Jan 22 23:09:33 2008 @@ -8,6 +8,82 @@ from buildbot.interfaces import LOG_CHANNEL_STDOUT from buildbot.status.web.base import ICurrentBox, HtmlResource, map_branches, build_get_class +def body(self, request): + status = self.getStatus(request) + builderNames = status.getBuilderNames() + failedTests = {} + anyBuildResults = Set() + + buildNumbers = range(self.oldBuildCount - 1, -1, -1) + + for name in builderNames: + recentFailures = Set() + builder = status.getBuilder(name) + recentBuilds = builder.generateFinishedBuilds( + branches=[None], num_builds=self.oldBuildCount) + for build in recentBuilds: + recentFailures.update(self.getLog(build, 'failed').splitlines()) + + for builderName in builderNames: + builder = status.getBuilder(builderName) + recentBuilds = builder.generateFinishedBuilds( + branches=[None], num_builds=self.oldBuildCount) + for buildNumber, build in enumerate(recentBuilds): + passed = self.getLog(build, 'passed').splitlines() + failed = self.getLog(build, 'failed').splitlines() + skipped = self.getLog(build, 'skipped').splitlines() + if passed or failed or skipped: + anyBuildResults.add(builderName) + results = dict.fromkeys( + passed, + tags.span(style="background-color: green;")['P']) + results.update( + dict.fromkeys( + failed, + tags.span(style="background-color: red;")['F'])) + results.update( + dict.fromkeys( + skipped, + tags.span(style="background-color: yellow;")['S'])) + + for testName in recentFailures: + key = (builderName, buildNumber, testName) + failedTests[key] = results.get( + testName, + tags.span(style="background-color: cyan;")['?']) + + testResultsTable = tags.table() + heading = tags.tr() + for buildNumber in buildNumbers: + heading[tags.td()[buildNumber]] + heading[tags.td()["<- How many builds ago"]] + testResultsTable[heading] + + builderNames = [ + name for name in builderNames if name in anyBuildResults] + + for testName in recentFailures: + row = tags.tr() + for buildNumber in buildNumbers: + result = [] + for builderName in builderNames: + key = (builderName, buildNumber, testName) + result.append(failedTests[key]) + row[tags.td()[result]] + row[tags.td()[testName]] + testResultsTable[row] + + legend = tags.div[ + tags.div()["P - Passed"], + tags.div()["F - Failed"], + tags.div()["S - Skipped"], + tags.div()["? - No result available"]] + + return flatten(tags.div()[ + legend, + testResultsTable]) + + class RecentlyFailingTests(HtmlResource): oldBuildCount = 10 @@ -21,68 +97,10 @@ return '' def body(self, request): - status = self.getStatus(request) - builderNames = status.getBuilderNames() - failedTests = {} - - buildNumbers = range(self.oldBuildCount - 1, -1, -1) - - for name in builderNames: - recentFailures = Set() - builder = status.getBuilder(name) - recentBuilds = builder.generateFinishedBuilds( - branches=[None], num_builds=self.oldBuildCount) - for build in recentBuilds: - print build - recentFailures.update(self.getLog(build, 'failed').splitlines()) - - for builderName in builderNames: - builder = status.getBuilder(builderName) - recentBuilds = builder.generateFinishedBuilds( - branches=[None], num_builds=self.oldBuildCount) - for buildNumber, build in enumerate(recentBuilds): - results = dict.fromkeys( - self.getLog(build, 'passed').splitlines(), - tags.span(style="background-color: green;")['P']) - results.update( - dict.fromkeys( - self.getLog(build, 'failed').splitlines(), - tags.span(style="background-color: red;")['F'])) - results.update( - dict.fromkeys( - self.getLog(build, 'skipped').splitlines(), - tags.span(style="background-color: yellow;")['S'])) - - for testName in recentFailures: - key = (builderName, buildNumber, testName) - failedTests[key] = results.get( - testName, - tags.span(style="background-color: cyan;")['?']) - - testResultsTable = tags.table() - heading = tags.tr() - for buildNumber in buildNumbers: - heading[tags.td()[buildNumber]] - heading[tags.td()["<- How many builds ago"]] - testResultsTable[heading] - - for testName in recentFailures: - row = tags.tr() - for buildNumber in buildNumbers: - result = [] - for builderName in builderNames: - key = (builderName, buildNumber, testName) - result.append(failedTests[key]) - row[tags.td()[result]] - row[tags.td()[testName]] - testResultsTable[row] - - legend = tags.div[ - tags.div()["P - Passed"], - tags.div()["F - Failed"], - tags.div()["S - Skipped"], - tags.div()["? - No result available"]] - - return flatten(tags.div()[ - legend, - testResultsTable]) + # Avoid having to restart the master to manually exercise each code + # change by putting all the interesting logic into a free function + # and reloading the module before each call to it. Yea, this is + # retarded, but this isn't real software anyway. + import pypy_status + reload(pypy_status) + return body(self, request) From exarkun at codespeak.net Tue Jan 22 23:13:47 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Tue, 22 Jan 2008 23:13:47 +0100 (CET) Subject: [pypy-svn] r50893 - pypy/build/buildbot Message-ID: <20080122221347.647C916856B@codespeak.net> Author: exarkun Date: Tue Jan 22 23:13:46 2008 New Revision: 50893 Modified: pypy/build/buildbot/pypy_status.py Log: sorting the results makes them a lot easier to look at Modified: pypy/build/buildbot/pypy_status.py ============================================================================== --- pypy/build/buildbot/pypy_status.py (original) +++ pypy/build/buildbot/pypy_status.py Tue Jan 22 23:13:46 2008 @@ -62,7 +62,7 @@ builderNames = [ name for name in builderNames if name in anyBuildResults] - for testName in recentFailures: + for testName in sorted(recentFailures): row = tags.tr() for buildNumber in buildNumbers: result = [] From exarkun at codespeak.net Tue Jan 22 23:16:13 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Tue, 22 Jan 2008 23:16:13 +0100 (CET) Subject: [pypy-svn] r50894 - pypy/build/buildbot Message-ID: <20080122221613.6AFAE16856B@codespeak.net> Author: exarkun Date: Tue Jan 22 23:16:12 2008 New Revision: 50894 Modified: pypy/build/buildbot/pypy_status.py Log: put the builder names in so you can tell what the table means Modified: pypy/build/buildbot/pypy_status.py ============================================================================== --- pypy/build/buildbot/pypy_status.py (original) +++ pypy/build/buildbot/pypy_status.py Tue Jan 22 23:16:12 2008 @@ -77,7 +77,11 @@ tags.div()["P - Passed"], tags.div()["F - Failed"], tags.div()["S - Skipped"], - tags.div()["? - No result available"]] + tags.div()["? - No result available"], + tags.div()["Table cells correspond to these builders, left to right:"], + [tags.div()[name] + for name + in builderNames]] return flatten(tags.div()[ legend, From cfbolz at codespeak.net Tue Jan 22 23:36:51 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 22 Jan 2008 23:36:51 +0100 (CET) Subject: [pypy-svn] r50895 - in pypy/dist/pypy: config interpreter objspace objspace/test Message-ID: <20080122223651.43C4A16855B@codespeak.net> Author: cfbolz Date: Tue Jan 22 23:36:50 2008 New Revision: 50895 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: expose the space.call_args method to the reflective object space. This needed a config option which allows to disable the speed hacks in the calling code that is normally there. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue Jan 22 23:36:50 2008 @@ -46,6 +46,9 @@ ChoiceOption("name", "Object Space name", ["std", "flow", "thunk", "dump", "taint", "reflective"], "std", + requires={"reflective": + [("objspace.disable_call_speedhacks", True)] + }, cmdline='--objspace -o'), ChoiceOption("parser", "which parser to use for app-level code", @@ -108,6 +111,10 @@ "Honor the __builtins__ key of a module dictionary", default=False), + BoolOption("disable_call_speedhacks", + "make sure that all calls go through space.call_args", + default=False), + OptionDescription("std", "Standard Object Space Options", [ BoolOption("withtproxy", "support transparent proxies", default=True), Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jan 22 23:36:50 2008 @@ -661,43 +661,45 @@ return self.call_args(w_callable, args) def call_function(self, w_func, *args_w): - # XXX start of hack for performance - from pypy.interpreter.function import Function, Method - if isinstance(w_func, Method): - w_inst = w_func.w_instance - if w_inst is not None: - func = w_func.w_function - if isinstance(func, Function): - return func.funccall(w_inst, *args_w) - elif args_w and self.is_true( - self.abstract_isinstance(args_w[0], w_func.w_class)): - w_func = w_func.w_function - - if isinstance(w_func, Function): - return w_func.funccall(*args_w) - # XXX end of hack for performance + if not self.config.objspace.disable_call_speedhacks: + # XXX start of hack for performance + from pypy.interpreter.function import Function, Method + if isinstance(w_func, Method): + w_inst = w_func.w_instance + if w_inst is not None: + func = w_func.w_function + if isinstance(func, Function): + return func.funccall(w_inst, *args_w) + elif args_w and self.is_true( + self.abstract_isinstance(args_w[0], w_func.w_class)): + w_func = w_func.w_function + + if isinstance(w_func, Function): + return w_func.funccall(*args_w) + # XXX end of hack for performance args = Arguments(self, list(args_w)) return self.call_args(w_func, args) def call_valuestack(self, w_func, nargs, frame): - # XXX start of hack for performance - from pypy.interpreter.function import Function, Method - hint(w_func.__class__, promote=True) - if isinstance(w_func, Method): - w_inst = w_func.w_instance - if w_inst is not None: - func = w_func.w_function - if isinstance(func, Function): - return func.funccall_obj_valuestack(w_inst, nargs, frame) - elif nargs > 0 and self.is_true( - self.abstract_isinstance(frame.peekvalue(nargs-1), # :-( - w_func.w_class)): - w_func = w_func.w_function - - if isinstance(w_func, Function): - return w_func.funccall_valuestack(nargs, frame) - # XXX end of hack for performance + if not self.config.objspace.disable_call_speedhacks: + # XXX start of hack for performance + from pypy.interpreter.function import Function, Method + hint(w_func.__class__, promote=True) + if isinstance(w_func, Method): + w_inst = w_func.w_instance + if w_inst is not None: + func = w_func.w_function + if isinstance(func, Function): + return func.funccall_obj_valuestack(w_inst, nargs, frame) + elif nargs > 0 and self.is_true( + self.abstract_isinstance(frame.peekvalue(nargs-1), # :-( + w_func.w_class)): + w_func = w_func.w_function + + if isinstance(w_func, Function): + return w_func.funccall_valuestack(nargs, frame) + # XXX end of hack for performance args = frame.make_arguments(nargs) try: Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Tue Jan 22 23:36:50 2008 @@ -1,4 +1,5 @@ -from pypy.interpreter import gateway +from pypy.interpreter import gateway, typedef +from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable from pypy.interpreter.error import OperationError from pypy.objspace import std from pypy.objspace.std.typeobject import W_TypeObject @@ -7,23 +8,22 @@ def set_reflectivespace(space, w_reflectivespace): ec = space.getexecutioncontext() if space.is_w(w_reflectivespace, space.w_None): - ec.w_reflectivespace = None + ec.w_rspace = None else: - ec.w_reflectivespace = w_reflectivespace + ec.w_rspace = w_reflectivespace app_set_reflectivespace = gateway.interp2app(set_reflectivespace) def get_reflective_space(space): ec = space.getexecutioncontext() - if ec.w_reflectivespace is not None: - w_rspace = ec.w_reflectivespace - ec.w_reflectivespace = None + if ec.w_rspace is not None: + w_rspace = ec.w_rspace + ec.w_rspace = None return w_rspace return None def reset_reflective_space(space, w_rspace): ec = space.getexecutioncontext() - ec.w_reflectivespace = w_rspace - + ec.w_rspace = w_rspace DontWrapMe = [ 'wrap', @@ -37,10 +37,10 @@ 'unwrap', 'is_true', 'is_w', - 'call_args', 'marshal_w', ] + def proxymaker(space, opname, parentfn): if opname in DontWrapMe: return None @@ -66,6 +66,23 @@ if w_newobj is not None: return w_newobj return w_obj + elif opname == "call_args": + def fn(w_callable, args): + w_rspace = get_reflective_space(space) + if w_rspace is not None: + try: + try: + w_f = space.getattr(w_rspace, space.wrap(opname)) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + args = args.prepend(w_callable) + w_args, w_kwargs = args.topacked() + return space.call(w_f, w_args, w_kwargs) + finally: + reset_reflective_space(space, w_rspace) + return parentfn(w_callable, args) elif opname.startswith("new"): def fn(*args): w_obj = parentfn(*args) @@ -95,7 +112,7 @@ class ReflectiveObjSpace(std.Space): def createexecutioncontext(self): ec = std.Space.createexecutioncontext(self) - ec.w_reflectivespace = None + ec.w_rspace = None return ec def Space(*args, **kwds): Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Tue Jan 22 23:36:50 2008 @@ -83,3 +83,41 @@ a = A() set_reflectivespace(Space()) assert a.f() == 2 + + def test_autocurry(self): + # rather simplified for now + from __pypy__ import set_reflectivespace + class partial(object): + def __init__(self, func, *args, **kwargs): + self.func = func + self.args = args + self.kwargs = kwargs + def __call__(self, *args, **kwargs): + args = self.args + args + for key, value in self.kwargs.iteritems(): + if key in kwargs: + raise TypeError("got multiple values for keyword argument %r" % (key, )) + kwargs[key] = value + return self.func(*args, **kwargs) + import types + class Space: + def call_args(self, func, *args, **kwargs): + print func, args, kwargs + if (len(kwargs) != 0 or not + isinstance(func, types.FunctionType)): + return func(*args, **kwargs) + defaults = func.func_defaults + if defaults is None: + defaults = () + argcount = func.func_code.co_argcount + minargs = argcount - len(defaults) + if len(args) >= minargs: + return func(*args, **kwargs) + return partial(func, *args, **kwargs) + def f(x, y, z): + return x + y * z + set_reflectivespace(Space()) + g = f(1, 2) + assert g(3) == f(1, 2, 3) + # XXX the following does not work, of course: + # assert f(4)(6)(7) == f(4, 6, 7) From cfbolz at codespeak.net Tue Jan 22 23:48:48 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 22 Jan 2008 23:48:48 +0100 (CET) Subject: [pypy-svn] r50896 - pypy/dist/pypy/objspace/test Message-ID: <20080122224848.59CD1169E2A@codespeak.net> Author: cfbolz Date: Tue Jan 22 23:48:47 2008 New Revision: 50896 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: be a bit more advanced for the currying Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Tue Jan 22 23:48:47 2008 @@ -92,19 +92,27 @@ self.func = func self.args = args self.kwargs = kwargs - def __call__(self, *args, **kwargs): + def combine_args(self, args, kwargs): args = self.args + args for key, value in self.kwargs.iteritems(): if key in kwargs: raise TypeError("got multiple values for keyword argument %r" % (key, )) kwargs[key] = value + return args, kwargs + + def __call__(self, *args, **kwargs): + args, kwargs = self.combine_args(args, kwargs) return self.func(*args, **kwargs) import types class Space: def call_args(self, func, *args, **kwargs): print func, args, kwargs - if (len(kwargs) != 0 or not - isinstance(func, types.FunctionType)): + if len(kwargs) != 0: # XXX for now + return func(*args, **kwargs) + if isinstance(func, partial): + args, kwargs = func.combine_args(args, kwargs) + func = func.func + elif not isinstance(func, types.FunctionType): return func(*args, **kwargs) defaults = func.func_defaults if defaults is None: @@ -119,5 +127,4 @@ set_reflectivespace(Space()) g = f(1, 2) assert g(3) == f(1, 2, 3) - # XXX the following does not work, of course: - # assert f(4)(6)(7) == f(4, 6, 7) + assert f(4)(6)(7) == f(4, 6, 7) From cfbolz at codespeak.net Tue Jan 22 23:57:11 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 22 Jan 2008 23:57:11 +0100 (CET) Subject: [pypy-svn] r50897 - pypy/dist/pypy/objspace/test Message-ID: <20080122225711.64B0216856E@codespeak.net> Author: cfbolz Date: Tue Jan 22 23:57:11 2008 New Revision: 50897 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: some failing test lines (made unreachable by a return) that show the problem of not being able to fall back sanely from within the reflective space. Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Tue Jan 22 23:57:11 2008 @@ -128,3 +128,8 @@ g = f(1, 2) assert g(3) == f(1, 2, 3) assert f(4)(6)(7) == f(4, 6, 7) + return + # XXX the following does not work: + def g(x): + return f(x) + assert g(4)(5, 6) == f(4, 5, 6) From cfbolz at codespeak.net Wed Jan 23 00:01:02 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 00:01:02 +0100 (CET) Subject: [pypy-svn] r50899 - pypy/dist/pypy/objspace/test Message-ID: <20080122230102.3F996168572@codespeak.net> Author: cfbolz Date: Wed Jan 23 00:01:01 2008 New Revision: 50899 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: good point by maciek: really do a skip to not forget that there is something to fix Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 00:01:01 2008 @@ -128,8 +128,7 @@ g = f(1, 2) assert g(3) == f(1, 2, 3) assert f(4)(6)(7) == f(4, 6, 7) - return - # XXX the following does not work: + skip("XXX the following does not work because there are no fallbacks in the reflective object space") def g(x): return f(x) assert g(4)(5, 6) == f(4, 5, 6) From exarkun at codespeak.net Wed Jan 23 00:46:58 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 23 Jan 2008 00:46:58 +0100 (CET) Subject: [pypy-svn] r50900 - pypy/build/buildbot Message-ID: <20080122234658.C8AE716856B@codespeak.net> Author: exarkun Date: Wed Jan 23 00:46:57 2008 New Revision: 50900 Added: pypy/build/buildbot/netstring-conftest.py pypy/build/buildbot/netstring.py Modified: pypy/build/buildbot/pypybuilders.py Log: use an output format that tolerates embedded newlines in data Added: pypy/build/buildbot/netstring-conftest.py ============================================================================== --- (empty file) +++ pypy/build/buildbot/netstring-conftest.py Wed Jan 23 00:46:57 2008 @@ -0,0 +1,45 @@ + +import sys + +import py +from py.__.test.session import Session +from py.__.test.reporter import AbstractReporter + +from netstring import netstring + +class MyReporter(AbstractReporter): + def __init__(self, *args, **kwds): + super(MyReporter, self).__init__(*args, **kwds) + + # XXXXXXXXXXXXXXx SUPER HACK mostly broken only works if you run + # py.test just how I run py.test, sorry. -exarkun + self.name = filter(None, sys.argv[-1].split('/')[:-1]) + + def report_unknown(self, event): + pass + + def report_TestStarted(self, event): + pass + + def report_TestFinished(self, event): + pass + + def report_ReceivedItemOutcome(self, event): + name = '.'.join(self.name) + if event.outcome.passed: + netstring(self.out, name, 'passed') + elif event.outcome.skipped: + netstring(self.out, name, 'skipped') + else: + netstring(self.out, name, 'failed', + event.outcome.excinfo.value) + + def report_ItemStart(self, event): + self.name.append(event.item.name) + + def report_ItemFinish(self, event): + self.name.pop() + +class MySession(Session): + reporterclass = MyReporter + Added: pypy/build/buildbot/netstring.py ============================================================================== --- (empty file) +++ pypy/build/buildbot/netstring.py Wed Jan 23 00:46:57 2008 @@ -0,0 +1,17 @@ + +def netstring(fObj, *strings): + for s in strings: + fObj.write('%d:%s\n' % (len(s), s)) + +def netstringparser(netstrings): + position = 0 + while True: + lengthEnd = netstrings.find(':', position) + if lengthEnd == -1: + break + length = int(netstrings[position:lengthEnd]) + yield netstrings[lengthEnd + 1:lengthEnd + 1 + length] + position = lengthEnd + length + 2 + +s = "1:x\n2:ab\n3:123\n" +assert map(str, netstringparser(s)) == ["x", "ab", "123"] Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Wed Jan 23 00:46:57 2008 @@ -6,6 +6,8 @@ from buildbot.steps.transfer import FileUpload, FileDownload from buildbot.steps.python_twisted import Trial +from netstring import netstringparser + class Translate(ShellCommand): name = "translate" description = ["Translating"] @@ -22,7 +24,6 @@ ShellCommand.__init__(self, workdir, *a, **kw) - class PyTest(ShellCommand): name = "py.test pypy" description = ["PyPy", "Tests"] @@ -51,9 +52,13 @@ def createSummary(self, log): """ - foo.test.test_foo.py.AppTestFoo.().test_foo passed - foo.test.test_foo.py.AppTestFoo.().test_bar failed - foo.test.test_foo.py.AppTestFoo.().test_baz skipped + 43:foo.test.test_foo.py.AppTestFoo.().test_foo + 6:passed + 43:foo.test.test_foo.py.AppTestFoo.().test_bar + 6:failed + 17:assert foo == bar + 43:foo.test.test_foo.py.AppTestFoo.().test_baz + 7:skipped """ stdout = ''.join( log.getChunks(channels=[LOG_CHANNEL_STDOUT], @@ -65,12 +70,22 @@ 'skipped': [], } weird = [] - for result in stdout.splitlines(): - testName, testResult = result.rsplit(None, 1) - if testResult in resultLists: - resultLists[testResult].append(testName) + results = netstringparser(stdout) + while True: + try: + testName = results.next() + outcome = results.next() + if outcome == 'failed': + message = results.next() + else: + message = None + except StopIteration: + break else: - weird.append(result) + if outcome in resultLists: + resultLists[outcome].append(testName) + else: + weird.append(testName) resultLists['weird'] = weird for testGroup, testNames in resultLists.iteritems(): @@ -80,7 +95,6 @@ '\n'.join(testNames)) - class PySwitch(ShellCommand): name = "switch" description = ["Switch", "Py", "to", "reporter-merge"] @@ -108,10 +122,16 @@ self.addStep(PySwitch) self.addStep( FileDownload, - mastersrc="text-conftest.py", + mastersrc="netstring-conftest.py", slavedest="conftest.py", workdir="build/pypy-src") + self.addStep( + FileDownload, + mastersrc="netstring.py", + slavedest="netstring.py", + workdir="build/pypy-src") + if pytestArguments is not None: self.addStep( PyTest, From cfbolz at codespeak.net Wed Jan 23 13:27:08 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 13:27:08 +0100 (CET) Subject: [pypy-svn] r50910 - pypy/dist/pypy/config/test Message-ID: <20080123122708.C2C32168448@codespeak.net> Author: cfbolz Date: Wed Jan 23 13:27:08 2008 New Revision: 50910 Modified: pypy/dist/pypy/config/test/test_pypyoption.py Log: use generative tests for checking whether all options have docs to make sure that if you add more than one new option you see all the missing docs. 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 Wed Jan 23 13:27:08 2008 @@ -35,7 +35,19 @@ conf.translation.gc = name assert conf.translation.gctransformer == "framework" +def test_rweakref_required(): + conf = get_pypy_config() + conf.translation.rweakref = False + conf.objspace.std.allopts = True + + assert not conf.objspace.std.withtypeversion + assert not conf.objspace.std.withmethodcache + assert not conf.objspace.std.withshadowtracking + def test_check_documentation(): + def check_file_exists(fn): + assert configdocdir.join(fn).check() + from pypy.doc.config.confrest import all_optiondescrs configdocdir = thisdir.dirpath().dirpath().join("doc", "config") for descr in all_optiondescrs: @@ -43,13 +55,5 @@ c = Config(descr) for path in c.getpaths(include_groups=True): fn = prefix + "." + path + ".txt" - assert configdocdir.join(fn).check() + yield check_file_exists, fn -def test_rweakref_required(): - conf = get_pypy_config() - conf.translation.rweakref = False - conf.objspace.std.allopts = True - - assert not conf.objspace.std.withtypeversion - assert not conf.objspace.std.withmethodcache - assert not conf.objspace.std.withshadowtracking From cfbolz at codespeak.net Wed Jan 23 13:28:31 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 13:28:31 +0100 (CET) Subject: [pypy-svn] r50911 - pypy/dist/pypy/doc/config Message-ID: <20080123122831.EBFD41683EA@codespeak.net> Author: cfbolz Date: Wed Jan 23 13:28:30 2008 New Revision: 50911 Added: pypy/dist/pypy/doc/config/objspace.disable_call_speedhacks.txt (contents, props changed) Log: add docs for the disable_call_speedhacks option Added: pypy/dist/pypy/doc/config/objspace.disable_call_speedhacks.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/objspace.disable_call_speedhacks.txt Wed Jan 23 13:28:30 2008 @@ -0,0 +1,2 @@ +disable the speed hacks that the interpreter normally does. Usually you don't +want to set this to False, but some object spaces require it. From cfbolz at codespeak.net Wed Jan 23 14:04:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 14:04:17 +0100 (CET) Subject: [pypy-svn] r50912 - in pypy/dist/pypy/objspace: . test Message-ID: <20080123130417.10075168471@codespeak.net> Author: cfbolz Date: Wed Jan 23 14:04:17 2008 New Revision: 50912 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: allow the reflective object space to fall back to the normal object space behaviour without disabling itself completely. The semantics are a small bit confusing but I think they do the right thing. Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Wed Jan 23 14:04:17 2008 @@ -1,4 +1,4 @@ -from pypy.interpreter import gateway, typedef +from pypy.interpreter import gateway, typedef, argument from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable from pypy.interpreter.error import OperationError from pypy.objspace import std @@ -15,8 +15,8 @@ def get_reflective_space(space): ec = space.getexecutioncontext() - if ec.w_rspace is not None: - w_rspace = ec.w_rspace + w_rspace = ec.w_rspace + if w_rspace is not None: ec.w_rspace = None return w_rspace return None @@ -25,6 +25,67 @@ ec = space.getexecutioncontext() ec.w_rspace = w_rspace +class W_SpaceAccess(Wrappable): + def __init__(self, space, w_reflectivespace): + self.space = space + self.w_reflectivespace = w_reflectivespace + +W_SpaceAccess_dict = {} + +def get_spaceop_args(name): + for opname, _, args, _ in ObjSpace.MethodTable: + if opname == name: + return args + +def make_space_access_method(name, wrappedfn, parentfn): + if name.startswith("new"): + # those options cannot call back to applevel, so no need to expose them + return + if name == "call_args": + def func(self, space, w_func, args): + w_old_reflectivespace = get_reflective_space(space) + set_reflectivespace(space, self.w_reflectivespace) + try: + return parentfn(w_func, args) + finally: + reset_reflective_space(space, w_old_reflectivespace) + unwrap_spec = ['self', ObjSpace, W_Root, argument.Arguments] + else: + args = get_spaceop_args(name) + if args == 1: + def func(self, space, w_arg1): + w_old_reflectivespace = get_reflective_space(space) + set_reflectivespace(space, self.w_reflectivespace) + try: + return parentfn(w_arg1) + finally: + reset_reflective_space(space, w_old_reflectivespace) + elif args == 2: + def func(self, space, w_arg1, w_arg2): + w_old_reflectivespace = get_reflective_space(space) + set_reflectivespace(space, self.w_reflectivespace) + try: + return parentfn(w_arg1, w_arg2) + finally: + reset_reflective_space(space, w_old_reflectivespace) + elif args == 3: + def func(self, space, w_arg1, w_arg2, w_arg3): + w_old_reflectivespace = get_reflective_space(space) + set_reflectivespace(space, self.w_reflectivespace) + try: + return parentfn(w_arg1, w_arg2, w_arg3) + finally: + reset_reflective_space(space, w_old_reflectivespace) + else: + raise NotImplementedError + unwrap_spec = ["self", ObjSpace] + [W_Root] * args + func_name = "descr_" + name + func.func_name = func_name + setattr(W_SpaceAccess, func_name, func) + bound_func = getattr(W_SpaceAccess, func_name) + W_SpaceAccess_dict[name] = gateway.interp2app(bound_func, unwrap_spec=unwrap_spec) + + DontWrapMe = [ 'wrap', 'str_w', @@ -44,6 +105,7 @@ def proxymaker(space, opname, parentfn): if opname in DontWrapMe: return None + want_spaceaccess = not opname.startswith("new") def user_hook(*args_w): w_rspace = get_reflective_space(space) if w_rspace is not None: @@ -54,7 +116,12 @@ if not e.match(space, space.w_AttributeError): raise else: - return space.call_function(w_f, *args_w) + if want_spaceaccess: + spaceaccess = W_SpaceAccess(space, w_rspace) + w_spaceaccess = space.wrap(spaceaccess) + return space.call_function(w_f, w_spaceaccess, *args_w) + else: + return space.call_function(w_f, *args_w) finally: reset_reflective_space(space, w_rspace) return None @@ -66,6 +133,13 @@ if w_newobj is not None: return w_newobj return w_obj + elif opname.startswith("new"): + def fn(*args): + w_obj = parentfn(*args) + w_newobj = user_hook(w_obj) + if w_newobj is not None: + return w_newobj + return w_obj elif opname == "call_args": def fn(w_callable, args): w_rspace = get_reflective_space(space) @@ -77,19 +151,15 @@ if not e.match(space, space.w_AttributeError): raise else: - args = args.prepend(w_callable) + spaceaccess = W_SpaceAccess(space, w_rspace) + w_spaceaccess = space.wrap(spaceaccess) + # XXX argh, not terribly efficient + args = args.prepend(w_callable).prepend(w_spaceaccess) w_args, w_kwargs = args.topacked() return space.call(w_f, w_args, w_kwargs) finally: reset_reflective_space(space, w_rspace) return parentfn(w_callable, args) - elif opname.startswith("new"): - def fn(*args): - w_obj = parentfn(*args) - w_newobj = user_hook(w_obj) - if w_newobj is not None: - return w_newobj - return w_obj elif opname == "type": def fn(*args_w): w_obj = user_hook(*args_w) @@ -106,6 +176,7 @@ if w_obj is not None: return w_obj return parentfn(*args_w) + make_space_access_method(opname, fn, parentfn) fn.func_name = opname return fn @@ -121,5 +192,6 @@ w___pypy__ = space.getbuiltinmodule("__pypy__") space.setattr(w___pypy__, space.wrap('set_reflectivespace'), space.wrap(app_set_reflectivespace)) + W_SpaceAccess.typedef = typedef.TypeDef("ObjSpace", **W_SpaceAccess_dict) return space Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 14:04:17 2008 @@ -8,7 +8,7 @@ def test_add(self): from __pypy__ import set_reflectivespace class Space: - def add(self, x, y): + def add(self, space, x, y): return 40+2 set_reflectivespace(Space()) @@ -20,6 +20,23 @@ x = 1 y = 2 assert x + y == 3 + + def test_fallback(self): + from __pypy__ import set_reflectivespace + class Space: + def mul(self, space, x, y): + return space.add(x, y) + + class Add(object): + def __init__(self, val): + self.val = val + def __add__(self, other): + return self.val * other.val + a2 = Add(2) + a5 = Add(5) + set_reflectivespace(Space()) + assert a2 * a5 == 7 + set_reflectivespace(None) def test_default_behaviour(self): from __pypy__ import set_reflectivespace @@ -59,7 +76,7 @@ def test_type_must_return_type(self): from __pypy__ import set_reflectivespace class Space: - def type(self, o): + def type(self, space, o): if o is l: return 1 return type(o) @@ -71,7 +88,7 @@ def test_type(self): from __pypy__ import set_reflectivespace class Space: - def type(self, o): + def type(self, space, o): if o is a: return B return type(o) @@ -105,22 +122,22 @@ return self.func(*args, **kwargs) import types class Space: - def call_args(self, func, *args, **kwargs): + def call_args(self, space, func, *args, **kwargs): print func, args, kwargs if len(kwargs) != 0: # XXX for now - return func(*args, **kwargs) + return space.call_args(func, *args, **kwargs) if isinstance(func, partial): args, kwargs = func.combine_args(args, kwargs) func = func.func elif not isinstance(func, types.FunctionType): - return func(*args, **kwargs) + return space.call_args(func, *args, **kwargs) defaults = func.func_defaults if defaults is None: defaults = () argcount = func.func_code.co_argcount minargs = argcount - len(defaults) if len(args) >= minargs: - return func(*args, **kwargs) + return space.call_args(func, *args, **kwargs) return partial(func, *args, **kwargs) def f(x, y, z): return x + y * z @@ -128,7 +145,6 @@ g = f(1, 2) assert g(3) == f(1, 2, 3) assert f(4)(6)(7) == f(4, 6, 7) - skip("XXX the following does not work because there are no fallbacks in the reflective object space") def g(x): return f(x) assert g(4)(5, 6) == f(4, 5, 6) From fijal at codespeak.net Wed Jan 23 14:15:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Jan 2008 14:15:20 +0100 (CET) Subject: [pypy-svn] r50913 - in pypy/dist/pypy/jit/codegen/i386: . test Message-ID: <20080123131520.EC851168473@codespeak.net> Author: fijal Date: Wed Jan 23 14:15:20 2008 New Revision: 50913 Modified: pypy/dist/pypy/jit/codegen/i386/ri386setup.py pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py Log: Two opcodes for operations on floats. 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 Wed Jan 23 14:15:20 2008 @@ -433,6 +433,15 @@ BREAKPOINT.mode0(['\xCC']) BREAKPOINT.as_alias = "INT3" +# ------------------------- floating point instructions ------------------ +FLD = Instruction() +FLD.mode1(MODRM, ['\xDD', modrm(1)]) + +FADD = Instruction() +FADD.mode1(MODRM, ['\xDC', modrm(1)]) + +# ------------------------- end of floating point ------------------------ + UD2 = Instruction() # reserved as an illegal instruction UD2.mode0(['\x0F\x0B']) Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py Wed Jan 23 14:15:20 2008 @@ -73,7 +73,10 @@ 'MOV', memSIB(None,ecx,3,0), eax # call +17 yield check, '\xE8\x11\x00\x00\x00', 'CALL', rel32(22) - + # fld + yield check, '\xDD\x44\x24\x04', 'FLD', mem(esp, 4) + # fadd + yield check, '\xDC\x44\x24\x08', 'FADD', mem(esp, 8) ##def test_conditional(): ## """Compare the encoding for the instructions JE, JAE, JC etc., From cfbolz at codespeak.net Wed Jan 23 14:16:28 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 14:16:28 +0100 (CET) Subject: [pypy-svn] r50914 - pypy/dist/pypy/objspace/test Message-ID: <20080123131628.AD89E168472@codespeak.net> Author: cfbolz Date: Wed Jan 23 14:16:28 2008 New Revision: 50914 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: try to teach the tests about methods Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 14:16:28 2008 @@ -122,15 +122,23 @@ return self.func(*args, **kwargs) import types class Space: - def call_args(self, space, func, *args, **kwargs): - print func, args, kwargs + def call_args(self, space, callable, *args, **kwargs): + print callable, args, kwargs if len(kwargs) != 0: # XXX for now - return space.call_args(func, *args, **kwargs) - if isinstance(func, partial): - args, kwargs = func.combine_args(args, kwargs) - func = func.func - elif not isinstance(func, types.FunctionType): - return space.call_args(func, *args, **kwargs) + return space.call_args(callable, *args, **kwargs) + if isinstance(callable, partial): + args, kwargs = callable.combine_args(args, kwargs) + func = callable.func + elif isinstance(callable, types.MethodType): + if callable.im_self is not None: + args = (callable.im_self, ) + args + func = callable.im_func + else: + return space.call_args(callable, *args, **kwargs) + elif not isinstance(callable, types.FunctionType): + return space.call_args(callable, *args, **kwargs) + else: + func = callable defaults = func.func_defaults if defaults is None: defaults = () @@ -148,3 +156,10 @@ def g(x): return f(x) assert g(4)(5, 6) == f(4, 5, 6) + class A(object): + def __init__(self, val): + self.val = val + def func(self, b, c): + return self.val + b * c + a = A(3) + assert a.func()(5, 6) == f(3, 5, 6) From antocuni at codespeak.net Wed Jan 23 15:08:06 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 23 Jan 2008 15:08:06 +0100 (CET) Subject: [pypy-svn] r50916 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20080123140806.77974168471@codespeak.net> Author: antocuni Date: Wed Jan 23 15:08:05 2008 New Revision: 50916 Modified: pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/dotnet.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/query.py pypy/dist/pypy/translator/cli/src/query.cs pypy/dist/pypy/translator/cli/test/test_dotnet.py pypy/dist/pypy/translator/cli/test/test_query.py Log: - add support for reading static fields of .NET classes - add support to value types Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Wed Jan 23 15:08:05 2008 @@ -41,13 +41,14 @@ class CliReferenceType(CliType): + prefix = 'class ' + def typename(self): - return 'class ' + self.classname() + return self.prefix + self.classname() def classname(self): raise NotImplementedError - class CliClassType(CliReferenceType): def __init__(self, assembly, name): self.assembly = assembly @@ -59,6 +60,9 @@ else: return self.name +class CliValueType(CliClassType): + prefix = 'valuetype ' + class CliGenericType(CliReferenceType): def __init__(self, assembly, name, numparam): @@ -229,12 +233,16 @@ elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType): return types.object elif isinstance(t, ootype.Instance): + if getattr(t, '_is_value_type', False): + cls = CliValueType + else: + cls = CliClassType NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None) if NATIVE_INSTANCE: - return CliClassType(None, NATIVE_INSTANCE._name) + return cls(None, NATIVE_INSTANCE._name) else: name = self.db.pending_class(t) - return CliClassType(None, name) + return cls(None, name) elif isinstance(t, ootype.Record): name = self.db.pending_record(t) return CliClassType(None, name) Modified: pypy/dist/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/dotnet.py (original) +++ pypy/dist/pypy/translator/cli/dotnet.py Wed Jan 23 15:08:05 2008 @@ -21,7 +21,15 @@ def getattr(self, s_attr): assert self.is_constant() assert s_attr.is_constant() - return SomeCliStaticMethod(self.const, s_attr.const) + cliclass = self.const + attrname = s_attr.const + if attrname in cliclass._static_fields: + TYPE = cliclass._static_fields[attrname] + return OverloadingResolver.lltype_to_annotation(TYPE) + elif attrname in cliclass._static_methods: + return SomeCliStaticMethod(cliclass, attrname) + else: + return s_ImpossibleValue def simple_call(self, *s_args): assert self.is_constant() @@ -75,7 +83,15 @@ self.cli_class = cli_class def rtype_getattr(self, hop): - return hop.inputconst(ootype.Void, self.cli_class) + attrname = hop.args_v[1].value + if attrname in self.cli_class._static_methods: + return hop.inputconst(ootype.Void, self.cli_class) + else: + assert attrname in self.cli_class._static_fields + TYPE = self.cli_class._static_fields[attrname] + c_class = hop.inputarg(hop.args_r[0], arg=0) + c_name = hop.inputconst(ootype.Void, hop.args_v[1].value) + return hop.genop("cli_getstaticfield", [c_class, c_name], resulttype=hop.r_result.lowleveltype) def rtype_simple_call(self, hop): # TODO: resolve constructor overloading @@ -199,16 +215,18 @@ fullname = '%s%s.%s' % (assembly, namespace, name) self._namespace = namespace self._classname = name + self._is_value_type = False ootype.Instance.__init__(self, fullname, superclass, fields, methods, _is_root, _hints) ## RPython interface definition class CliClass(object): - def __init__(self, INSTANCE, static_methods): + def __init__(self, INSTANCE, static_methods, static_fields): self._name = INSTANCE._name self._INSTANCE = INSTANCE self._static_methods = {} + self._static_fields = {} self._add_methods(static_methods) def __repr__(self): @@ -222,6 +240,9 @@ for name, meth in methods.iteritems(): meth._set_attrs(self, name) + def _add_static_fields(self, fields): + self._static_fields.update(fields) + def _lookup(self, meth_name, ARGS): meth = self._static_methods[meth_name] return meth._get_desc(ARGS) @@ -239,7 +260,7 @@ self._PythonNet_class = obj def __getattr__(self, attr): - if attr in self._static_methods: + if attr in self._static_methods or attr in self._static_fields: self._load_class() return getattr(self._PythonNet_class, attr) else: Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Wed Jan 23 15:08:05 2008 @@ -203,17 +203,21 @@ def load_self(self): self.opcode('ldarg.0') - def load_arg(self,v): + def load_arg(self, v): self.opcode('ldarg', repr(v.name)) - def load_local(self,v): - self.opcode('ldloc', repr(v.name)) + def load_local(self, v): + TYPE = v.concretetype + if getattr(TYPE, '_is_value_type', False): + self.opcode('ldloca', repr(v.name)) + else: + self.opcode('ldloc', repr(v.name)) def switch(self, targets): cmd = 'switch(%s)' % ', '.join(targets) self.opcode(cmd) - def load_const(self,type_,v): + def load_const(self,type_, v): if type_ is Void: pass elif type_ is Bool: Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Wed Jan 23 15:08:05 2008 @@ -215,6 +215,14 @@ generator.ilasm.opcode('ldftn instance', desc) generator.ilasm.opcode('newobj', 'instance void class [mscorlib]System.EventHandler::.ctor(object, native int)') +class _GetStaticField(MicroInstruction): + def render(self, generator, op): + cli_class = op.args[0].value + fldname = op.args[1].value + TYPE = op.result.concretetype + cts_type = generator.cts.lltype_to_cts(TYPE) + desc = '%s::%s' % (cli_class._name, fldname) + generator.ilasm.load_static_field(cts_type, desc) OOTYPE_TO_MNEMONIC = { @@ -243,4 +251,5 @@ SetArrayElem = _SetArrayElem() TypeOf = _TypeOf() EventHandler = _EventHandler() +GetStaticField = _GetStaticField() CastPrimitive = _CastPrimitive() Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Wed Jan 23 15:08:05 2008 @@ -1,7 +1,7 @@ from pypy.translator.cli.metavm import Call, CallMethod, \ IndirectCall, GetField, SetField, DownCast, NewCustomDict,\ MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\ - TypeOf, CastPrimitive, EventHandler + TypeOf, CastPrimitive, EventHandler, GetStaticField from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode from pypy.translator.cli.cts import WEAKREF @@ -44,6 +44,7 @@ 'cli_typeof': [TypeOf], 'cli_arraylength': 'ldlen', 'cli_eventhandler': [EventHandler], + 'cli_getstaticfield': [GetStaticField], 'oois': 'ceq', 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not, 'instanceof': [CastTo, 'ldnull', 'cgt.un'], Modified: pypy/dist/pypy/translator/cli/query.py ============================================================================== --- pypy/dist/pypy/translator/cli/query.py (original) +++ pypy/dist/pypy/translator/cli/query.py Wed Jan 23 15:08:05 2008 @@ -86,8 +86,6 @@ desc.BaseType = 'System.Object' desc.IsArray = True desc.ElementType = 'System.Object' # not really true, but we need something - desc.StaticMethods = [] - desc.Methods = [] elif name.endswith('[]'): # it's an array itemname = name[:-2] itemdesc = get_class_desc(itemname) @@ -97,7 +95,6 @@ desc.BaseType = 'System.Array' desc.ElementType = itemdesc.FullName desc.IsArray = True - desc.StaticMethods = [] desc.Methods = [ ('Get', ['ootype.Signed', ], itemdesc.FullName), ('Set', ['ootype.Signed', itemdesc.FullName], 'ootype.Void') @@ -110,6 +107,13 @@ class ClassDesc(object): + + # default values + StaticFields = [] + StaticMethods = [] + Methods = [] + IsValueType = False + _cliclass = None def __eq__(self, other): @@ -131,7 +135,8 @@ # construct OOTYPE and CliClass # no superclass for now, will add it later TYPE = NativeInstance('[mscorlib]', namespace, name, None, {}, {}) - Class = CliClass(TYPE, {}) + TYPE._is_value_type = self.IsValueType + Class = CliClass(TYPE, {}, {}) self._cliclass = Class # we need to check also for System.Array to prevent a circular recursion if self.FullName in ('System.Object', 'System.Array'): @@ -144,11 +149,13 @@ if self.IsArray: TYPE._ELEMENT = get_ootype(self.ElementType) - # add both static and instance methods + # add both static and instance methods, and static fields static_meths = self.group_methods(self.StaticMethods, _overloaded_static_meth, _static_meth, ootype.StaticMethod) meths = self.group_methods(self.Methods, ootype.overload, ootype.meth, ootype.Meth) + fields = dict([(name, get_ootype(t)) for name, t in self.StaticFields]) Class._add_methods(static_meths) + Class._add_static_fields(fields) TYPE._add_methods(meths) return Class Modified: pypy/dist/pypy/translator/cli/src/query.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/query.cs (original) +++ pypy/dist/pypy/translator/cli/src/query.cs Wed Jan 23 15:08:05 2008 @@ -60,8 +60,10 @@ outfile.WriteLine("desc.FullName = '{0}'", t.FullName); outfile.WriteLine("desc.BaseType = '{0}'", GetBaseType(t)); outfile.WriteLine("desc.IsArray = {0}", t.IsArray); + outfile.WriteLine("desc.IsValueType = {0}", t.IsValueType); PrintMethods("desc.StaticMethods", t.GetMethods(BindingFlags.Static|BindingFlags.Public|BindingFlags.DeclaredOnly)); PrintMethods("desc.Methods", t.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.DeclaredOnly)); + PrintFields("desc.StaticFields", t.GetFields(BindingFlags.Static|BindingFlags.Public|BindingFlags.DeclaredOnly)); } private static string GetBaseType(Type t) @@ -118,6 +120,15 @@ outfile.WriteLine(" ]"); } + private static void PrintFields(string varname, FieldInfo[] fields) + { + outfile.WriteLine("{0} = [", varname); + // FieldName, RESULT + foreach(FieldInfo fld in fields) + outfile.WriteLine(" ('{0}', '{1}'),", fld.Name, GetOOType(fld.FieldType)); + outfile.WriteLine(" ]"); + } + private static bool IgnoreMethod(MethodInfo meth) { if (!meth.IsPublic) Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Wed Jan 23 15:08:05 2008 @@ -432,6 +432,14 @@ res = self.interpret(fn, [False]) assert res == 42 + def test_static_fields(self): + OpCodes = System.Reflection.Emit.OpCodes + def fn(): + op = OpCodes.Add + return op.get_Name() + res = self.interpret(fn, []) + assert self.ll_to_string(res) == 'add' + class TestPythonnet(TestDotnetRtyping): # don't interpreter functions but execute them directly through pythonnet def interpret(self, f, args, backendopt='ignored'): Modified: pypy/dist/pypy/translator/cli/test/test_query.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_query.py (original) +++ pypy/dist/pypy/translator/cli/test/test_query.py Wed Jan 23 15:08:05 2008 @@ -23,6 +23,10 @@ assert System._name == 'System' assert hasattr(CLR, 'System') +def test_static_fields(): + desc = query.get_class_desc('System.Reflection.Emit.OpCodes') + assert ('Add', 'System.Reflection.Emit.OpCode') in desc.StaticFields + def test_System_Object(): Object = CLR.System.Object assert Object._name == '[mscorlib]System.Object' From arigo at codespeak.net Wed Jan 23 15:15:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 15:15:19 +0100 (CET) Subject: [pypy-svn] r50917 - pypy/dist/pypy/annotation Message-ID: <20080123141519.5F062168471@codespeak.net> Author: arigo Date: Wed Jan 23 15:15:18 2008 New Revision: 50917 Modified: pypy/dist/pypy/annotation/binaryop.py Log: Fix for pypy.tool.test.test_error. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Wed Jan 23 15:15:18 2008 @@ -33,10 +33,11 @@ def unioncheck(*somevalues): s_value = unionof(*somevalues) - if isdegenerated(s_value) and not TLS.no_side_effects_in_union: - bookkeeper = getbookkeeper() - if bookkeeper is not None: - bookkeeper.ondegenerated('union', s_value) + if isdegenerated(s_value): + if not getattr(TLS, 'no_side_effects_in_union', 0): + bookkeeper = getbookkeeper() + if bookkeeper is not None: + bookkeeper.ondegenerated('union', s_value) return s_value # XXX unify this with ObjSpace.MethodTable From cfbolz at codespeak.net Wed Jan 23 15:25:15 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 15:25:15 +0100 (CET) Subject: [pypy-svn] r50922 - pypy/dist/pypy/objspace/test Message-ID: <20080123142515.DFC3016842A@codespeak.net> Author: cfbolz Date: Wed Jan 23 15:25:15 2008 New Revision: 50922 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: support for unbound methods Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 15:25:15 2008 @@ -105,8 +105,9 @@ # rather simplified for now from __pypy__ import set_reflectivespace class partial(object): - def __init__(self, func, *args, **kwargs): + def __init__(self, func, callable, *args, **kwargs): self.func = func + self.callable = callable self.args = args self.kwargs = kwargs def combine_args(self, args, kwargs): @@ -116,10 +117,9 @@ raise TypeError("got multiple values for keyword argument %r" % (key, )) kwargs[key] = value return args, kwargs - def __call__(self, *args, **kwargs): args, kwargs = self.combine_args(args, kwargs) - return self.func(*args, **kwargs) + return self.callable(*args, **kwargs) import types class Space: def call_args(self, space, callable, *args, **kwargs): @@ -129,12 +129,14 @@ if isinstance(callable, partial): args, kwargs = callable.combine_args(args, kwargs) func = callable.func - elif isinstance(callable, types.MethodType): + callable = callable.callable + if isinstance(callable, types.MethodType): if callable.im_self is not None: args = (callable.im_self, ) + args func = callable.im_func + callable = func else: - return space.call_args(callable, *args, **kwargs) + func = callable.im_func elif not isinstance(callable, types.FunctionType): return space.call_args(callable, *args, **kwargs) else: @@ -145,8 +147,8 @@ argcount = func.func_code.co_argcount minargs = argcount - len(defaults) if len(args) >= minargs: - return space.call_args(func, *args, **kwargs) - return partial(func, *args, **kwargs) + return space.call_args(callable, *args, **kwargs) + return partial(func, callable, *args, **kwargs) def f(x, y, z): return x + y * z set_reflectivespace(Space()) @@ -163,3 +165,4 @@ return self.val + b * c a = A(3) assert a.func()(5, 6) == f(3, 5, 6) + assert A.func()(a)(5)(6) == f(3, 5, 6) From fijal at codespeak.net Wed Jan 23 15:32:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 23 Jan 2008 15:32:29 +0100 (CET) Subject: [pypy-svn] r50923 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080123143229.B5296168471@codespeak.net> Author: fijal Date: Wed Jan 23 15:32:29 2008 New Revision: 50923 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Log: Some weird cast. Pure-python only right now. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Wed Jan 23 15:32:29 2008 @@ -7,6 +7,7 @@ from pypy.tool.tls import tlsobject from types import NoneType from sys import maxint +import struct import weakref log = py.log.Producer('lltype') @@ -1772,6 +1773,9 @@ assert oddint & 1, "only odd integers can be cast back to ptr" return _ptr(PTRTYPE, oddint, solid=True) +def cast_float_to_int(val): + return struct.unpack('i', struct.pack('f', val))[0] + def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): if not isinstance(GCSTRUCT, RttiStruct): raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Wed Jan 23 15:32:29 2008 @@ -696,6 +696,9 @@ assert cast_ptr_to_int(t) == 21 assert s == cast_pointer(Ptr(S), t) +def test_cast_float(): + assert cast_float_to_int(2.3) == 0x40133333 + def test_str_of_dead_ptr(): S = Struct('S', ('x', Signed)) T = GcStruct('T', ('s', S)) From arigo at codespeak.net Wed Jan 23 16:19:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 16:19:43 +0100 (CET) Subject: [pypy-svn] r50925 - in pypy/branch/asmgcroot/pypy/translator/c: . gcc gcc/test test Message-ID: <20080123151943.C8B18168433@codespeak.net> Author: arigo Date: Wed Jan 23 16:19:43 2008 New Revision: 50925 Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/ (props changed) pypy/branch/asmgcroot/pypy/translator/c/gcc/__init__.py (contents, props changed) pypy/branch/asmgcroot/pypy/translator/c/gcc/test/ (props changed) pypy/branch/asmgcroot/pypy/translator/c/gcc/test/__init__.py (contents, props changed) pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py (contents, props changed) pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py - copied, changed from r50802, pypy/branch/asmgcroot/pypy/translator/c/test/test_trackgcroot.py pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py - copied unchanged from r50804, pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Removed: pypy/branch/asmgcroot/pypy/translator/c/test/test_trackgcroot.py pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py Log: Put logic and tests for --asmgcroot and trackgcroot.py into their own subdirectory 'gcc'. Some tests fail. Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/__init__.py ============================================================================== Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/__init__.py ============================================================================== Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py Wed Jan 23 16:19:43 2008 @@ -0,0 +1,58 @@ +import py +import sys, os +from pypy.translator.c.test import test_newgc +from pypy.translator.translator import TranslationContext +from pypy.translator.c.genc import CStandaloneBuilder +from pypy.annotation.listdef import s_list_of_strings +from pypy import conftest + + +class AbstractTestAsmGCRoot: + # the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved + # instructions: + should_be_moving = False + + def getcompiled(self, func): + def main(argv): + res = func() + print 'Result:', res + return 0 + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) + config.translation.gc = self.gcpolicy + config.translation.asmgcroot = True + t = TranslationContext(config=config) + self.t = t + a = t.buildannotator() + a.build_types(main, [s_list_of_strings]) + t.buildrtyper().specialize() + t.checkgraphs() + + cbuilder = CStandaloneBuilder(t, main, config=config) + c_source_filename = cbuilder.generate_source( + defines = cbuilder.DEBUG_DEFINES) + if conftest.option.view: + t.view() + exe_name = cbuilder.compile() + + def run(): + lines = [] + print 'RUN: starting', exe_name + g = os.popen("'%s'" % (exe_name,), 'r') + for line in g: + print 'RUN:', line.rstrip() + lines.append(line) + g.close() + if not lines: + py.test.fail("no output from subprocess") + if not lines[-1].startswith('Result:'): + py.test.fail("unexpected output from subprocess") + return int(lines[-1][len('Result:'):].strip()) + return run + + +class TestAsmGCRootWithSemiSpaceGC(AbstractTestAsmGCRoot, + test_newgc.TestSemiSpaceGC): + pass + # for the individual tests see + # ====> ../../test/test_newgc.py Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/genc.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/genc.py Wed Jan 23 16:19:43 2008 @@ -41,6 +41,10 @@ gcpolicyclass = self.get_gcpolicyclass() + if self.config.translation.asmgcroot: + if not self.standalone: + raise NotImplementedError("--asmgcroot requires standalone") + if self.config.translation.stackless: if not self.standalone: raise Exception("stackless: only for stand-alone builds") @@ -278,9 +282,12 @@ def compile(self): if self.config.translation.asmgcroot: - raise Exception("Dunno how to compile with --asmgcroot. " - "Just go to the %s directory and type 'make'." - % (self.targetdir,)) + # as we are gcc-only anyway, let's just use the Makefile. + cmdline = "make -C '%s'" % (self.targetdir,) + err = os.system(cmdline) + if err != 0: + raise OSError("failed (see output): " + cmdline) + return str(self.getccompiler().outputfilename) assert self.c_source_filename assert not self._compiled eci = self.eci.merge(ExternalCompilationInfo(includes= @@ -360,7 +367,7 @@ print >> f if self.config.translation.asmgcroot: print >> f, 'TRACKGCROOT="%s"' % (os.path.join(autopath.this_dir, - 'trackgcroot.py'),) + 'gcc', 'trackgcroot.py'),) print >> f args = ['-l'+libname for libname in self.eci.libraries] print >> f, 'LIBS =', ' '.join(args) From arigo at codespeak.net Wed Jan 23 16:23:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 16:23:17 +0100 (CET) Subject: [pypy-svn] r50926 - pypy/branch/asmgcroot/pypy/translator/c/gcc/test Message-ID: <20080123152317.23745168433@codespeak.net> Author: arigo Date: Wed Jan 23 16:23:16 2008 New Revision: 50926 Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py Log: Fix test. Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py Wed Jan 23 16:23:16 2008 @@ -14,8 +14,12 @@ def getcompiled(self, func): def main(argv): - res = func() - print 'Result:', res + try: + res = func() + except MemoryError: + print 'Result: MemoryError' + else: + print 'Result:', res return 0 from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) @@ -37,17 +41,21 @@ def run(): lines = [] - print 'RUN: starting', exe_name + print >> sys.stderr, 'RUN: starting', exe_name g = os.popen("'%s'" % (exe_name,), 'r') for line in g: - print 'RUN:', line.rstrip() + print >> sys.stderr, 'RUN:', line.rstrip() lines.append(line) g.close() if not lines: py.test.fail("no output from subprocess") if not lines[-1].startswith('Result:'): py.test.fail("unexpected output from subprocess") - return int(lines[-1][len('Result:'):].strip()) + result = lines[-1][len('Result:'):].strip() + if result == 'MemoryError': + raise MemoryError("subprocess got an RPython MemoryError") + else: + return int(result) return run From arigo at codespeak.net Wed Jan 23 16:47:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 16:47:57 +0100 (CET) Subject: [pypy-svn] r50927 - in pypy/branch/asmgcroot/pypy/translator/c/gcc: . test Message-ID: <20080123154757.5DB1C168456@codespeak.net> Author: arigo Date: Wed Jan 23 16:47:54 2008 New Revision: 50927 Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track0.s Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py Log: Starting real trackgcroot tests. Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py Wed Jan 23 16:47:54 2008 @@ -1,9 +1,11 @@ import py -import sys +import sys, re from pypy.translator.c.gcc.trackgcroot import GcRootTracker from pypy.translator.c.gcc.trackgcroot import FunctionGcRootTracker from StringIO import StringIO +this_dir = py.path.local(__file__).dirpath() + def test_find_functions(): source = """\ @@ -28,3 +30,50 @@ assert parts[2] == (False, lines[5:8]) assert parts[3] == (True, lines[8:11]) assert parts[4] == (False, lines[11:]) + + +def test_computegcmaptable(): + tests = [] + for path in this_dir.listdir("track*.s"): + n = path.purebasename[5:] + try: + n = int(n) + except ValueError: + pass + tests.append((n, path)) + tests.sort() + for _, path in tests: + yield check_computegcmaptable, path + +r_globallabel = re.compile(r"([\w]+)[:]") +r_expected = re.compile(r"\s*;;\s*expected\s*([(][-\d\s,+]+[)])") + +def check_computegcmaptable(path): + print + print path.basename + lines = path.readlines() + tracker = FunctionGcRootTracker(lines) + table = tracker.computegcmaptable(verbose=sys.maxint) + tabledict = {} + seen = {} + for entry in table: + print entry + tabledict[entry[0]] = entry[1] + # find the ";; expected" lines + prevline = "" + for line in lines: + match = r_expected.match(line) + if match: + expected = eval(match.group(1)) + assert isinstance(expected, tuple) + prevmatch = r_globallabel.match(prevline) + assert prevmatch, "the computed table is not complete" + label = prevmatch.group(1) + assert label in tabledict + got = tabledict[label] + assert got == expected + seen[label] = True + prevline = line + assert len(seen) == len(tabledict), ( + "computed table contains unexpected entries:\n%r" % + [key for key in tabledict if key not in seen]) Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track0.s ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track0.s Wed Jan 23 16:47:54 2008 @@ -0,0 +1,79 @@ + .type pypy_g_clear_large_memory_chunk, @function +pypy_g_clear_large_memory_chunk: +.L271: + pushl %ebp + xorl %eax, %eax + movl $420, %edx + pushl %edi + pushl %esi + pushl %ebx + subl $12, %esp + movl 36(%esp), %ebp + movl %edx, 8(%esp) + movl %eax, 4(%esp) + movl %ebp, %ebx + movl $pypy_g_array_16, (%esp) + call open + ;; expected (32, -16, -12, -8, -4) + cmpl $-1, %eax + movl %eax, %edi + movl 32(%esp), %esi + jne .L273 + jmp .L287 + .p2align 4,,7 +.L282: + movl %eax, 8(%esp) + movl %esi, 4(%esp) + movl %edi, (%esp) + call read + ;; expected (32, -16, -12, -8, -4) + testl %eax, %eax + jle .L280 +.L285: +.L288: + subl %eax, %ebx + addl %eax, %esi +.L273: + testl %ebx, %ebx + jle .L280 +.L279: + cmpl $536870912, %ebx + movl $536870912, %eax + jg .L282 +.L283: + movl %esi, 4(%esp) + movl %ebx, %eax + movl %eax, 8(%esp) + movl %edi, (%esp) + call read + ;; expected (32, -16, -12, -8, -4) + testl %eax, %eax + jg .L288 +.L280: + movl %edi, (%esp) + call close + ;; expected (32, -16, -12, -8, -4) + movl %ebx, %eax +.L286: +.L274: + testl %eax, %eax + jle .L270 +.L277: +.L276: + movl %eax, 8(%esp) + xorl %ecx, %ecx + movl %ecx, 4(%esp) + movl %esi, (%esp) + call memset + ;; expected (32, -16, -12, -8, -4) +.L270: + addl $12, %esp + popl %ebx + popl %esi + popl %edi + popl %ebp + ret +.L287: + movl %ebp, %eax + jmp .L286 + .size pypy_g_clear_large_memory_chunk, .-pypy_g_clear_large_memory_chunk Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py Wed Jan 23 16:47:54 2008 @@ -755,6 +755,8 @@ 'abort': None, '_exit': None, '__assert_fail': None, + 'RPyAbort': None, + 'RPyAssertFailed': None, } CALLEE_SAVE_REGISTERS_NOEBP = ['%ebx', '%esi', '%edi'] From arigo at codespeak.net Wed Jan 23 17:01:01 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 17:01:01 +0100 (CET) Subject: [pypy-svn] r50928 - pypy/branch/asmgcroot/pypy/translator/c Message-ID: <20080123160101.1822C168469@codespeak.net> Author: arigo Date: Wed Jan 23 17:01:00 2008 New Revision: 50928 Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py Log: Fix this logic. Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/genc.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/genc.py Wed Jan 23 17:01:00 2008 @@ -281,25 +281,25 @@ self.eci, compiler_exe = cc, profbased = profbased) def compile(self): + assert self.c_source_filename + assert not self._compiled + compiler = self.getccompiler() if self.config.translation.asmgcroot: # as we are gcc-only anyway, let's just use the Makefile. cmdline = "make -C '%s'" % (self.targetdir,) err = os.system(cmdline) if err != 0: raise OSError("failed (see output): " + cmdline) - return str(self.getccompiler().outputfilename) - assert self.c_source_filename - assert not self._compiled - eci = self.eci.merge(ExternalCompilationInfo(includes= - [str(self.targetdir)])) - compiler = self.getccompiler() - if sys.platform == 'darwin': - compiler.compile_extra.append('-mdynamic-no-pic') - if self.config.translation.compilerflags: - compiler.compile_extra.append(self.config.translation.compilerflags) - if self.config.translation.linkerflags: - compiler.link_extra.append(self.config.translation.linkerflags) - compiler.build() + else: + eci = self.eci.merge(ExternalCompilationInfo(includes= + [str(self.targetdir)])) + if sys.platform == 'darwin': + compiler.compile_extra.append('-mdynamic-no-pic') + if self.config.translation.compilerflags: + compiler.compile_extra.append(self.config.translation.compilerflags) + if self.config.translation.linkerflags: + compiler.link_extra.append(self.config.translation.linkerflags) + compiler.build() self.executable_name = str(compiler.outputfilename) self._compiled = True return self.executable_name From arigo at codespeak.net Wed Jan 23 17:01:06 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 17:01:06 +0100 (CET) Subject: [pypy-svn] r50929 - pypy/branch/asmgcroot/pypy/translator/c/gcc/test Message-ID: <20080123160106.7B46C168472@codespeak.net> Author: arigo Date: Wed Jan 23 17:01:05 2008 New Revision: 50929 Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track1.s pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track2.s pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track3.s Log: More tests. Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track1.s ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track1.s Wed Jan 23 17:01:05 2008 @@ -0,0 +1,151 @@ + .type pypy_g_clear_large_memory_chunk, @function +pypy_g_clear_large_memory_chunk: +.LFB41: + .loc 2 1513 0 + pushl %ebp +.LCFI87: + movl %esp, %ebp +.LCFI88: + subl $72, %esp +.LCFI89: +.L543: + .loc 2 1521 0 + movl $420, 8(%esp) + movl $0, 4(%esp) + movl $pypy_g_array_16, (%esp) + call open + ;; expected (80, 1, 3, 5, -4) + movl %eax, -12(%ebp) + .loc 2 1522 0 + cmpl $-1, -12(%ebp) + setne %al + movb %al, -21(%ebp) + .loc 2 1523 0 + cmpb $0, -21(%ebp) + je .L544 + .loc 2 1524 0 + movl 12(%ebp), %eax + movl %eax, -16(%ebp) + .loc 2 1525 0 + movl 8(%ebp), %eax + movl %eax, -4(%ebp) + .loc 2 1526 0 + jmp .L545 +.L544: + .loc 2 1528 0 + movl 12(%ebp), %eax + movl %eax, -20(%ebp) + .loc 2 1529 0 + movl 8(%ebp), %eax + movl %eax, -8(%ebp) +.L546: + .loc 2 1533 0 + cmpl $0, -20(%ebp) + setg %al + movb %al, -22(%ebp) + .loc 2 1534 0 + cmpb $0, -22(%ebp) + je .L542 +.L549: +.L548: + .loc 2 1544 0 + movl -20(%ebp), %eax + movl %eax, 8(%esp) + movl $0, 4(%esp) + movl -8(%ebp), %eax + movl %eax, (%esp) + call memset + ;; expected (80, 1, 3, 5, -4) + .loc 2 1545 0 + jmp .L542 +.L545: + .loc 2 1548 0 + cmpl $0, -16(%ebp) + setg %al + movb %al, -23(%ebp) + .loc 2 1549 0 + cmpb $0, -23(%ebp) + je .L552 + .loc 2 1550 0 + jmp .L551 +.L552: + .loc 2 1555 0 + movl -12(%ebp), %eax + movl %eax, (%esp) + call close + ;; expected (80, 1, 3, 5, -4) + movl %eax, -36(%ebp) + .loc 2 1556 0 + movl -16(%ebp), %eax + movl %eax, -20(%ebp) + .loc 2 1557 0 + movl -4(%ebp), %eax + movl %eax, -8(%ebp) + .loc 2 1558 0 + jmp .L546 +.L551: + .loc 2 1561 0 + cmpl $536870912, -16(%ebp) + setg %al + movb %al, -24(%ebp) + .loc 2 1562 0 + cmpb $0, -24(%ebp) + je .L555 + .loc 2 1563 0 + movl $536870912, -52(%ebp) + .loc 2 1564 0 + jmp .L554 +.L555: + .loc 2 1569 0 + movl -16(%ebp), %eax + movl %eax, -44(%ebp) + .loc 2 1570 0 + movl -44(%ebp), %eax + movl %eax, -52(%ebp) +.L554: + .loc 2 1574 0 + movl -52(%ebp), %eax + movl %eax, 8(%esp) + movl -4(%ebp), %eax + movl %eax, 4(%esp) + movl -12(%ebp), %eax + movl %eax, (%esp) + call read + ;; expected (80, 1, 3, 5, -4) + movl %eax, -48(%ebp) + .loc 2 1575 0 + movl -48(%ebp), %eax + movl %eax, -32(%ebp) + .loc 2 1576 0 + cmpl $0, -32(%ebp) + setle %al + movb %al, -25(%ebp) + .loc 2 1577 0 + cmpb $0, -25(%ebp) + je .L557 + .loc 2 1578 0 + jmp .L552 +.L557: + .loc 2 1583 0 + movl -32(%ebp), %edx + movl -16(%ebp), %eax + subl %edx, %eax + movl %eax, -40(%ebp) + .loc 2 1584 0 + movl -32(%ebp), %eax + addl -4(%ebp), %eax + movl %eax, -56(%ebp) + .loc 2 1585 0 + movl -40(%ebp), %eax + movl %eax, -16(%ebp) + .loc 2 1586 0 + movl -56(%ebp), %eax + movl %eax, -4(%ebp) + .loc 2 1587 0 + jmp .L545 +.L542: + .loc 2 1588 0 + leave + ret +.LFE41: + .size pypy_g_clear_large_memory_chunk, .-pypy_g_clear_large_memory_chunk Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track2.s ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track2.s Wed Jan 23 17:01:05 2008 @@ -0,0 +1,183 @@ + .type pypy_g_populate, @function +pypy_g_populate: + pushl %esi + pushl %ebx + subl $20, %esp + movl 32(%esp), %esi + movl 36(%esp), %ebx + jmp .L1387 + .p2align 4,,7 +.L1416: +.L1371: +.L1374: + movl $31, 4(%edx) + leal 24(%edx), %eax + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, %ecx + movl %eax, 12(%ecx) + movl %edx, %eax +.L1375: +#APP + /* GCROOT %ebx */ +#NO_APP + testl %eax, %eax + je .L1345 +.L1377: + movl $0, 12(%eax) + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %edx + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+72, %ecx + movl $pypy_g_pypy_translator_goal_gcbench_Node_vtable, 8(%eax) + movl $0, 16(%eax) + subl %edx, %ecx + cmpl $23, %ecx + movl %eax, 12(%ebx) + jle .L1415 +.L1417: +.L1380: +.L1383: + movl $31, 4(%edx) + leal 24(%edx), %eax + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, %ecx + movl %eax, 12(%ecx) + movl %edx, %eax +.L1384: +#APP + /* GCROOT %ebx */ +#NO_APP + testl %eax, %eax + je .L1345 +.L1386: + movl $0, 12(%eax) + movl 12(%ebx), %edx + movl $0, 16(%eax) + movl $pypy_g_pypy_translator_goal_gcbench_Node_vtable, 8(%eax) + movl %eax, 16(%ebx) + movl %edx, 4(%esp) + movl %esi, (%esp) + call pypy_g_populate + ;; expected (32, -8, -4, 5, 7, 1) + movl %ebx, %eax +#APP + /* GCROOT %eax */ +#NO_APP + movl pypy_g_ExcData, %ebx + testl %ebx, %ebx + jne .L1345 +.L1389: + movl 16(%eax), %ebx +.L1387: +.L1346: + testl %esi, %esi + jle .L1345 +.L1349: +.L1350: +.L1351: +.L1352: + call LL_stack_too_big + ;; expected (32, -8, -4, 5, 7, 1) + testl %eax, %eax + jne .L1418 +.L1361: +.L1363: +.L1365: +.L1357: +#APP + /* GCROOT %ebx */ +#NO_APP + movl pypy_g_ExcData, %ecx + testl %ecx, %ecx + jne .L1345 +.L1368: + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %edx + decl %esi + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+72, %eax + subl %edx, %eax + cmpl $23, %eax + jg .L1416 +.L1373: +.L1370: +.L1402: + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, (%esp) + movl $24, %edx + movl %edx, 4(%esp) + call pypy_g_SemiSpaceGC_try_obtain_free_space + ;; expected (32, -8, -4, 5, 7, 1) + movl pypy_g_ExcData, %edx + xorl %ecx, %ecx + testl %edx, %edx + je .L1419 +.L1404: + xorl %eax, %eax + testl %edx, %edx + jne .L1375 + movl %ecx, %edx + jmp .L1416 +.L1348: +.L1382: + .p2align 4,,7 +.L1415: +.L1379: +.L1390: + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, (%esp) + movl $24, %ecx + movl %ecx, 4(%esp) + call pypy_g_SemiSpaceGC_try_obtain_free_space + ;; expected (32, -8, -4, 5, 7, 1) + movl pypy_g_ExcData, %edx + xorl %ecx, %ecx + testl %edx, %edx + je .L1420 +.L1392: + xorl %eax, %eax + testl %edx, %edx + jne .L1384 + movl %ecx, %edx + jmp .L1417 +.L1345: + addl $20, %esp + popl %ebx + popl %esi + ret +.L1356: +.L1355: +.L1358: +.L1359: +.L1360: +.L1418: + movl $pypy_g_exceptions_RuntimeError_vtable, %edx + movl $pypy_g_exceptions_RuntimeError, %eax + movl %edx, pypy_g_ExcData + movl %eax, pypy_g_ExcData+4 + jmp .L1357 +.L1419: +.L1405: + testb %al, %al + je .L1421 +.L1407: + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %ecx + jmp .L1404 +.L1420: +.L1393: + testb %al, %al + je .L1422 +.L1395: + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %ecx + jmp .L1392 +.L1408: +.L1409: +.L1421: +.L1410: + movl $pypy_g_exceptions_MemoryError_vtable, %edx + movl $pypy_g_exceptions_MemoryError_1, %eax + movl %edx, pypy_g_ExcData + movl %eax, pypy_g_ExcData+4 + jmp .L1404 +.L1396: +.L1397: +.L1422: +.L1398: + movl $pypy_g_exceptions_MemoryError_vtable, %edx + movl $pypy_g_exceptions_MemoryError_1, %eax + movl %edx, pypy_g_ExcData + movl %eax, pypy_g_ExcData+4 + jmp .L1392 + .size pypy_g_populate, .-pypy_g_populate Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track3.s ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track3.s Wed Jan 23 17:01:05 2008 @@ -0,0 +1,186 @@ + .type pypy_g_populate, @function +pypy_g_populate: + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %ebx + subl $16, %esp + movl 8(%ebp), %esi + movl 12(%ebp), %ebx + jmp .L1386 + .p2align 4,,7 +.L1415: +.L1370: +.L1373: + movl $31, 4(%edx) + leal 24(%edx), %eax + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, %ecx + movl %eax, 12(%ecx) + movl %edx, %eax +.L1374: +#APP + /* GCROOT %ebx */ +#NO_APP + testl %eax, %eax + je .L1344 +.L1376: + movl $0, 12(%eax) + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %edx + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+72, %ecx + movl $pypy_g_pypy_translator_goal_gcbench_Node_vtable, 8(%eax) + movl $0, 16(%eax) + subl %edx, %ecx + cmpl $23, %ecx + movl %eax, 12(%ebx) + jle .L1414 +.L1416: +.L1379: +.L1382: + movl $31, 4(%edx) + leal 24(%edx), %eax + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, %ecx + movl %eax, 12(%ecx) + movl %edx, %eax +.L1383: +#APP + /* GCROOT %ebx */ +#NO_APP + testl %eax, %eax + je .L1344 +.L1385: + movl $0, 12(%eax) + movl 12(%ebx), %edx + movl $0, 16(%eax) + movl $pypy_g_pypy_translator_goal_gcbench_Node_vtable, 8(%eax) + movl %eax, 16(%ebx) + movl %edx, 4(%esp) + movl %esi, (%esp) + call pypy_g_populate + ;; expected (32, -12, -8, 5, -4, 1) + movl %ebx, %eax +#APP + /* GCROOT %eax */ +#NO_APP + movl pypy_g_ExcData, %ebx + testl %ebx, %ebx + jne .L1344 +.L1388: + movl 16(%eax), %ebx +.L1386: +.L1345: + testl %esi, %esi + jle .L1344 +.L1348: +.L1349: +.L1350: +.L1351: + call LL_stack_too_big + ;; expected (32, -12, -8, 5, -4, 1) + testl %eax, %eax + jne .L1417 +.L1360: +.L1362: +.L1364: +.L1356: +#APP + /* GCROOT %ebx */ +#NO_APP + movl pypy_g_ExcData, %ecx + testl %ecx, %ecx + jne .L1344 +.L1367: + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %edx + decl %esi + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+72, %eax + subl %edx, %eax + cmpl $23, %eax + jg .L1415 +.L1372: +.L1369: +.L1401: + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, (%esp) + movl $24, %edx + movl %edx, 4(%esp) + call pypy_g_SemiSpaceGC_try_obtain_free_space + ;; expected (32, -12, -8, 5, -4, 1) + movl pypy_g_ExcData, %edx + xorl %ecx, %ecx + testl %edx, %edx + je .L1418 +.L1403: + xorl %eax, %eax + testl %edx, %edx + jne .L1374 + movl %ecx, %edx + jmp .L1415 +.L1347: +.L1381: + .p2align 4,,7 +.L1414: +.L1378: +.L1389: + movl $pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC, (%esp) + movl $24, %ecx + movl %ecx, 4(%esp) + call pypy_g_SemiSpaceGC_try_obtain_free_space + ;; expected (32, -12, -8, 5, -4, 1) + movl pypy_g_ExcData, %edx + xorl %ecx, %ecx + testl %edx, %edx + je .L1419 +.L1391: + xorl %eax, %eax + testl %edx, %edx + jne .L1383 + movl %ecx, %edx + jmp .L1416 +.L1344: + addl $16, %esp + popl %ebx + popl %esi + popl %ebp + ret +.L1355: +.L1354: +.L1357: +.L1358: +.L1359: +.L1417: + movl $pypy_g_exceptions_RuntimeError_vtable, %edx + movl $pypy_g_exceptions_RuntimeError, %eax + movl %edx, pypy_g_ExcData + movl %eax, pypy_g_ExcData+4 + jmp .L1356 +.L1418: +.L1404: + testb %al, %al + je .L1420 +.L1406: + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %ecx + jmp .L1403 +.L1419: +.L1392: + testb %al, %al + je .L1421 +.L1394: + movl pypy_g_pypy_rpython_memory_gc_semispace_SemiSpaceGC+12, %ecx + jmp .L1391 +.L1407: +.L1408: +.L1420: +.L1409: + movl $pypy_g_exceptions_MemoryError_vtable, %edx + movl $pypy_g_exceptions_MemoryError_1, %eax + movl %edx, pypy_g_ExcData + movl %eax, pypy_g_ExcData+4 + jmp .L1403 +.L1395: +.L1396: +.L1421: +.L1397: + movl $pypy_g_exceptions_MemoryError_vtable, %edx + movl $pypy_g_exceptions_MemoryError_1, %eax + movl %edx, pypy_g_ExcData + movl %eax, pypy_g_ExcData+4 + jmp .L1391 + .size pypy_g_populate, .-pypy_g_populate From antocuni at codespeak.net Wed Jan 23 17:30:27 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 23 Jan 2008 17:30:27 +0100 (CET) Subject: [pypy-svn] r50935 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20080123163027.6ACB116845E@codespeak.net> Author: antocuni Date: Wed Jan 23 17:30:27 2008 New Revision: 50935 Modified: pypy/dist/pypy/translator/cli/query.py pypy/dist/pypy/translator/cli/test/test_dotnet.py Log: add support to access classes defined in pypylib from rpython Modified: pypy/dist/pypy/translator/cli/query.py ============================================================================== --- pypy/dist/pypy/translator/cli/query.py (original) +++ pypy/dist/pypy/translator/cli/query.py Wed Jan 23 17:30:27 2008 @@ -13,10 +13,30 @@ Types = {} # TypeName -> ClassDesc Namespaces = set() mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +pypylib = 'pypylib, Version=0.0.0.0, Culture=neutral' #_______________________________________________________________________________ # This is the public interface of query.py +def get_cli_class(name): + desc = get_class_desc(name) + return desc.get_cliclass() + +#_______________________________________________________________________________ + +def load_pypylib(): + from pypy.translator.cli.rte import get_pypy_dll + dll = get_pypy_dll() + try: + import clr + from System.Reflection import Assembly + except ImportError: + pass + else: + Assembly.LoadFrom(dll) + clr.AddReference(pypylib) + load_assembly(pypylib) + def load_assembly(name): if name in Assemblies: return @@ -41,13 +61,6 @@ Types.update(types) -def get_cli_class(name): - desc = get_class_desc(name) - return desc.get_cliclass() - -#_______________________________________________________________________________ - - def get_cachedir(): import pypy _cache = py.path.local(pypy.__file__).new(basename='_cache').ensure(dir=1) @@ -128,13 +141,18 @@ if self._cliclass is not None: return self._cliclass - - assert self.Assembly.startswith('mscorlib') # TODO: support external assemblies + + if self.Assembly == mscorlib: + assembly = '[mscorlib]' + elif self.Assembly == pypylib: + assembly = '[pypylib]' + else: + assert False, 'TODO: support external assemblies' namespace, name = self.FullName.rsplit('.', 1) # construct OOTYPE and CliClass # no superclass for now, will add it later - TYPE = NativeInstance('[mscorlib]', namespace, name, None, {}, {}) + TYPE = NativeInstance(assembly, namespace, name, None, {}, {}) TYPE._is_value_type = self.IsValueType Class = CliClass(TYPE, {}, {}) self._cliclass = Class @@ -194,6 +212,7 @@ assert self._name is None, '_buildtree can be called only on top-level CLR, not on namespaces' from pypy.translator.cli.support import getattr_ex load_assembly(mscorlib) + load_pypylib() for fullname in sorted(list(Namespaces)): if '.' in fullname: parent, name = fullname.rsplit('.', 1) Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Wed Jan 23 17:30:27 2008 @@ -440,6 +440,12 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == 'add' + def test_pypylib(self): + def fn(): + return CLR.pypy.runtime.Utils.OOString(42, -1) + res = self.interpret(fn, []) + assert self.ll_to_string(res) == '42' + class TestPythonnet(TestDotnetRtyping): # don't interpreter functions but execute them directly through pythonnet def interpret(self, f, args, backendopt='ignored'): From arigo at codespeak.net Wed Jan 23 17:38:25 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 17:38:25 +0100 (CET) Subject: [pypy-svn] r50938 - pypy/branch/asmgcroot/pypy/translator/c/gcc/test Message-ID: <20080123163825.6CE0C168460@codespeak.net> Author: arigo Date: Wed Jan 23 17:38:24 2008 New Revision: 50938 Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track4.s Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py Log: A hand-constructed example. Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_trackgcroot.py Wed Jan 23 17:38:24 2008 @@ -53,6 +53,7 @@ print path.basename lines = path.readlines() tracker = FunctionGcRootTracker(lines) + tracker.is_main = tracker.funcname == 'main' table = tracker.computegcmaptable(verbose=sys.maxint) tabledict = {} seen = {} Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track4.s ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track4.s Wed Jan 23 17:38:24 2008 @@ -0,0 +1,52 @@ + .type main, @function +main: + ;; this is an artificial example showing what kind of code gcc + ;; can produce for main() + pushl %ebp + movl %eax, $globalptr1 + movl %esp, %ebp + pushl %edi + subl $8, %esp + andl $-15, %esp + movl %ebx, -8(%ebp) + movl 8(%ebp), %edi + call foobar + ;; expected (20, -12, 3, -8, -4, 5) +.L1: + cmpl $0, %eax + je .L3 +.L2: + ;; inlined function here with -fomit-frame-pointer + movl %eax, -12(%ebp) + movl %edi, %edx + subl $16, %esp + movl %eax, (%esp) + movl $42, %edi + movl %edx, 4(%esp) + movl %esi, %ebx + movl $nonsense, %esi + call foobar + ;; expected (36, -12, 1, -8, -4, -28, -16) + addl %edi, %eax + movl 4(%esp), %eax + movl %ebx, %esi + addl $16, %esp + movl %eax, %edi + movl -12(%ebp), %eax +#APP + /* GCROOT %eax */ +#NO_APP + ;; end of inlined function +.L3: + call foobar + ;; expected (20, -12, 3, -8, -4, 5) +#APP + /* GCROOT %edi */ +#NO_APP + movl -8(%ebp), %ebx + movl -4(%ebp), %edi + movl %ebp, %esp + popl %ebp + ret + + .size main, .-main From arigo at codespeak.net Wed Jan 23 17:42:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 23 Jan 2008 17:42:10 +0100 (CET) Subject: [pypy-svn] r50939 - in pypy/branch/asmgcroot/pypy/translator/c/gcc: . test Message-ID: <20080123164210.30655168425@codespeak.net> Author: arigo Date: Wed Jan 23 17:42:08 2008 New Revision: 50939 Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track5.s Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py Log: Test and fix. GCC doesn't know that RPyAbort cannot return. Added: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track5.s ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/track5.s Wed Jan 23 17:42:08 2008 @@ -0,0 +1,55 @@ + .type pypy_g_SemiSpaceGC_scan_copied, @function +pypy_g_SemiSpaceGC_scan_copied: +.L1215: + pushl %esi + pushl %ebx + subl $20, %esp + movl 32(%esp), %esi + movl 36(%esp), %ebx + testl %esi, %esi + jne .L1216 + jmp .L1227 +.L1220: +.L1231: + movl %ebx, 4(%esp) + movl %esi, 8(%esp) + movl %esi, (%esp) + call pypy_g_trace___trace_copy + ;; expected (32, -8, -4, 5, 7) + movl %ebx, 4(%esp) + movl %esi, (%esp) + call pypy_g_SemiSpaceGC_get_size + ;; expected (32, -8, -4, 5, 7) + addl %eax, %ebx +.L1216: + cmpl 12(%esi), %ebx + jb .L1231 +.L1221: + addl $20, %esp + movl %ebx, %eax + popl %ebx + popl %esi + ret + .p2align 4,,7 +.L1229: + movl %ebx, 4(%esp) + movl %esi, 8(%esp) + movl %esi, (%esp) + call pypy_g_trace___trace_copy + ;; expected (32, -8, -4, 5, 7) + movl %ebx, 4(%esp) + movl %esi, (%esp) + call pypy_g_SemiSpaceGC_get_size + ;; expected (32, -8, -4, 5, 7) + addl %eax, %ebx +.L1227: + call RPyAbort + ;; expected (32, -8, -4, 5, 7) + cmpl 12(%esi), %ebx + jb .L1229 + addl $20, %esp + movl %ebx, %eax + popl %ebx + popl %esi + ret + .size pypy_g_SemiSpaceGC_scan_copied, .-pypy_g_SemiSpaceGC_scan_copied Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/trackgcroot.py Wed Jan 23 17:42:08 2008 @@ -755,8 +755,6 @@ 'abort': None, '_exit': None, '__assert_fail': None, - 'RPyAbort': None, - 'RPyAssertFailed': None, } CALLEE_SAVE_REGISTERS_NOEBP = ['%ebx', '%esi', '%edi'] From exarkun at codespeak.net Wed Jan 23 18:34:02 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 23 Jan 2008 18:34:02 +0100 (CET) Subject: [pypy-svn] r50940 - pypy/build/buildbot Message-ID: <20080123173402.52820168451@codespeak.net> Author: exarkun Date: Wed Jan 23 18:34:00 2008 New Revision: 50940 Modified: pypy/build/buildbot/netstring-conftest.py pypy/build/buildbot/netstring.py Log: handle the case where the outcome's excinfo is None; handle windows-style newlines (probably) :/ Modified: pypy/build/buildbot/netstring-conftest.py ============================================================================== --- pypy/build/buildbot/netstring-conftest.py (original) +++ pypy/build/buildbot/netstring-conftest.py Wed Jan 23 18:34:00 2008 @@ -15,6 +15,10 @@ # py.test just how I run py.test, sorry. -exarkun self.name = filter(None, sys.argv[-1].split('/')[:-1]) + # Marker so the peer can recognize our newline convention. >< + # -exarkun + self.out('\n') + def report_unknown(self, event): pass @@ -30,9 +34,11 @@ netstring(self.out, name, 'passed') elif event.outcome.skipped: netstring(self.out, name, 'skipped') - else: + elif event.outcome.excinfo is not None: netstring(self.out, name, 'failed', event.outcome.excinfo.value) + else: + netstring(self.out, name, 'failed', "no reason given") def report_ItemStart(self, event): self.name.append(event.item.name) Modified: pypy/build/buildbot/netstring.py ============================================================================== --- pypy/build/buildbot/netstring.py (original) +++ pypy/build/buildbot/netstring.py Wed Jan 23 18:34:00 2008 @@ -4,7 +4,9 @@ fObj.write('%d:%s\n' % (len(s), s)) def netstringparser(netstrings): - position = 0 + if netstrings.startswith('\r\n'): + netstrings = netstrings.replace('\r\n', '\n') + position = 1 while True: lengthEnd = netstrings.find(':', position) if lengthEnd == -1: @@ -13,5 +15,8 @@ yield netstrings[lengthEnd + 1:lengthEnd + 1 + length] position = lengthEnd + length + 2 -s = "1:x\n2:ab\n3:123\n" -assert map(str, netstringparser(s)) == ["x", "ab", "123"] +input = "\n1:x\n2:ab\n3:123\n3:\nxy\n4:a\nb\n\n1:a\n" +output = ["x", "ab", "123", "\nxy", "a\nb\n", "a"] +assert map(str, netstringparser(input)) == output +input = input.replace('\n', '\r\n') +assert map(str, netstringparser(input)) == output From exarkun at codespeak.net Wed Jan 23 18:35:12 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 23 Jan 2008 18:35:12 +0100 (CET) Subject: [pypy-svn] r50941 - pypy/build/buildbot Message-ID: <20080123173512.D1653168451@codespeak.net> Author: exarkun Date: Wed Jan 23 18:35:12 2008 New Revision: 50941 Modified: pypy/build/buildbot/master.cfg Log: --boxed on 64 bit, maybe help with memory issues Modified: pypy/build/buildbot/master.cfg ============================================================================== --- pypy/build/buildbot/master.cfg (original) +++ pypy/build/buildbot/master.cfg Wed Jan 23 18:35:12 2008 @@ -55,7 +55,7 @@ {"name": "pypy-c-allworkingmodules-faassen-64", "slavenames": ["linux-dvs0"], "builddir": "pypy-c-allworkingmodules-faassen-64", - "factory": PyPyBuildFactory([], + "factory": PyPyBuildFactory(["--boxed"], [], ["--allworkingmodules", "--faassen"])}, From cfbolz at codespeak.net Wed Jan 23 19:07:42 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 19:07:42 +0100 (CET) Subject: [pypy-svn] r50942 - pypy/dist/pypy/objspace/test Message-ID: <20080123180742.7BDB416844E@codespeak.net> Author: cfbolz Date: Wed Jan 23 19:07:41 2008 New Revision: 50942 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: improve the autocurrying to work with keyword arguments Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 19:07:41 2008 @@ -120,12 +120,37 @@ def __call__(self, *args, **kwargs): args, kwargs = self.combine_args(args, kwargs) return self.callable(*args, **kwargs) + def enough_args(func, args, kwargs): + code = func.func_code + needed = code.co_varnames[:code.co_argcount] + needed_set = set(needed) + argnames = set(needed) + defaults = func.func_defaults + has_varargs = bool(code.co_flags & 4) + for i in range(min(len(args), len(needed))): + name = needed[i] + needed_set.remove(name) + for key, value in kwargs.iteritems(): + if key not in needed_set: + if key not in argnames: + raise TypeError( + "%s() got an unexpected keyword argument %r" % ( + func.func_name, key)) + else: + raise TypeError( + "%s() got multiple values for keyword argument %r" % ( + func.func_name, key)) + needed_set.remove(key) + if defaults is not None: + for i in range(len(defaults)): + default_name = needed[-1 - i] + needed_set.discard(default_name) + return len(needed_set) == 0 + import types class Space: def call_args(self, space, callable, *args, **kwargs): print callable, args, kwargs - if len(kwargs) != 0: # XXX for now - return space.call_args(callable, *args, **kwargs) if isinstance(callable, partial): args, kwargs = callable.combine_args(args, kwargs) func = callable.func @@ -141,12 +166,7 @@ return space.call_args(callable, *args, **kwargs) else: func = callable - defaults = func.func_defaults - if defaults is None: - defaults = () - argcount = func.func_code.co_argcount - minargs = argcount - len(defaults) - if len(args) >= minargs: + if enough_args(func, args, kwargs): return space.call_args(callable, *args, **kwargs) return partial(func, callable, *args, **kwargs) def f(x, y, z): @@ -166,3 +186,6 @@ a = A(3) assert a.func()(5, 6) == f(3, 5, 6) assert A.func()(a)(5)(6) == f(3, 5, 6) + def f(x, y=1): + return x + y * 2 + f(y=2)(3) == 7 From cfbolz at codespeak.net Wed Jan 23 19:10:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 19:10:10 +0100 (CET) Subject: [pypy-svn] r50943 - pypy/dist/pypy/objspace/test Message-ID: <20080123181010.326B916844E@codespeak.net> Author: cfbolz Date: Wed Jan 23 19:10:09 2008 New Revision: 50943 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: small improvement to work with functions that have **kwargs Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 19:10:09 2008 @@ -126,21 +126,16 @@ needed_set = set(needed) argnames = set(needed) defaults = func.func_defaults - has_varargs = bool(code.co_flags & 4) for i in range(min(len(args), len(needed))): name = needed[i] needed_set.remove(name) for key, value in kwargs.iteritems(): if key not in needed_set: - if key not in argnames: - raise TypeError( - "%s() got an unexpected keyword argument %r" % ( - func.func_name, key)) - else: + if key in argnames: raise TypeError( "%s() got multiple values for keyword argument %r" % ( func.func_name, key)) - needed_set.remove(key) + needed_set.discard(key) if defaults is not None: for i in range(len(defaults)): default_name = needed[-1 - i] @@ -189,3 +184,6 @@ def f(x, y=1): return x + y * 2 f(y=2)(3) == 7 + def f(x, **kwds): + return x + kwds['y'] * 2 + f(y=2)(3) == 7 From cfbolz at codespeak.net Wed Jan 23 19:45:59 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 19:45:59 +0100 (CET) Subject: [pypy-svn] r50944 - in pypy/dist/pypy/objspace: . test Message-ID: <20080123184559.03187168458@codespeak.net> Author: cfbolz Date: Wed Jan 23 19:45:58 2008 New Revision: 50944 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: hook into the type unwrapped methods (_w). Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Wed Jan 23 19:45:58 2008 @@ -38,8 +38,8 @@ return args def make_space_access_method(name, wrappedfn, parentfn): - if name.startswith("new"): - # those options cannot call back to applevel, so no need to expose them + if name.startswith("new") or name.endswith("_w"): + # those methods cannot call back to applevel, so no need to expose them return if name == "call_args": def func(self, space, w_func, args): @@ -88,12 +88,6 @@ DontWrapMe = [ 'wrap', - 'str_w', - 'int_w', - 'float_w', - 'uint_w', - 'bigint_w', - 'unicode_w', 'interpclass_w', 'unwrap', 'is_true', @@ -105,7 +99,7 @@ def proxymaker(space, opname, parentfn): if opname in DontWrapMe: return None - want_spaceaccess = not opname.startswith("new") + want_spaceaccess = True # changed below def user_hook(*args_w): w_rspace = get_reflective_space(space) if w_rspace is not None: @@ -133,6 +127,7 @@ if w_newobj is not None: return w_newobj return w_obj + want_spaceaccess = False elif opname.startswith("new"): def fn(*args): w_obj = parentfn(*args) @@ -140,6 +135,14 @@ if w_newobj is not None: return w_newobj return w_obj + want_spaceaccess = False + elif opname.endswith("_w"): + def fn(w_obj): + w_newobj = user_hook(w_obj) + if w_newobj is not None: + w_obj = w_newobj + return parentfn(w_obj) + want_spaceaccess = False elif opname == "call_args": def fn(w_callable, args): w_rspace = get_reflective_space(space) Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 19:45:58 2008 @@ -101,6 +101,17 @@ set_reflectivespace(Space()) assert a.f() == 2 + def test_typed_unwrap(self): + from __pypy__ import set_reflectivespace + class Space: + def int_w(self, i): + if isinstance(i, basestring): + return int(i) + return i + set_reflectivespace(Space()) + assert chr("123") == chr(123) + + def test_autocurry(self): # rather simplified for now from __pypy__ import set_reflectivespace From cfbolz at codespeak.net Wed Jan 23 20:38:48 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 20:38:48 +0100 (CET) Subject: [pypy-svn] r50945 - in pypy/dist/pypy/objspace: . test Message-ID: <20080123193848.3B0EE168465@codespeak.net> Author: cfbolz Date: Wed Jan 23 20:38:41 2008 New Revision: 50945 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: make sure that the reflective space does not contain the is_w shortcut Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Wed Jan 23 20:38:41 2008 @@ -91,7 +91,6 @@ 'interpclass_w', 'unwrap', 'is_true', - 'is_w', 'marshal_w', ] @@ -136,6 +135,9 @@ return w_newobj return w_obj want_spaceaccess = False + elif opname == "is_w": + def fn(w_obj1, w_obj2): + return space.is_true(space.is_(w_obj1, w_obj2)) elif opname.endswith("_w"): def fn(w_obj): w_newobj = user_hook(w_obj) Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 20:38:41 2008 @@ -111,6 +111,35 @@ set_reflectivespace(Space()) assert chr("123") == chr(123) + def test_is(self): + from __pypy__ import set_reflectivespace + IAmNone = object() + class Space: + def replace(self, obj): + if obj is IAmNone: + return None + return obj + def is_(self, space, a, b): + return self.replace(a) is self.replace(b) + def __getattr__(self, name): + if name in ["repr", "type"]: + def f(space, *args): + newargs = [] + for arg in args: + newargs.append(self.replace(arg)) + return getattr(space, name)(*newargs) + return f + raise AttributeError + set_reflectivespace(Space()) + assert IAmNone is None + assert type(IAmNone) is type(None) + # check that space.is_w is not using a fast path + class A(object): + x = property(lambda self: 1, IAmNone) + a = A() + assert a.x == 1 + raises(AttributeError, "a.x = 2") + def test_autocurry(self): # rather simplified for now From cfbolz at codespeak.net Wed Jan 23 20:43:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 20:43:45 +0100 (CET) Subject: [pypy-svn] r50946 - pypy/dist/pypy/objspace/test Message-ID: <20080123194345.64365168451@codespeak.net> Author: cfbolz Date: Wed Jan 23 20:43:44 2008 New Revision: 50946 Modified: pypy/dist/pypy/objspace/test/test_reflective.py Log: simplify test Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 20:43:44 2008 @@ -121,15 +121,8 @@ return obj def is_(self, space, a, b): return self.replace(a) is self.replace(b) - def __getattr__(self, name): - if name in ["repr", "type"]: - def f(space, *args): - newargs = [] - for arg in args: - newargs.append(self.replace(arg)) - return getattr(space, name)(*newargs) - return f - raise AttributeError + def type(self, space, a): + return type(self.replace(a)) set_reflectivespace(Space()) assert IAmNone is None assert type(IAmNone) is type(None) @@ -139,6 +132,7 @@ a = A() assert a.x == 1 raises(AttributeError, "a.x = 2") + set_reflectivespace(None) def test_autocurry(self): From cfbolz at codespeak.net Wed Jan 23 21:12:12 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 21:12:12 +0100 (CET) Subject: [pypy-svn] r50947 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080123201212.4B08216845A@codespeak.net> Author: cfbolz Date: Wed Jan 23 21:12:10 2008 New Revision: 50947 Modified: pypy/dist/pypy/objspace/std/booltype.py pypy/dist/pypy/objspace/std/test/test_boolobject.py Log: remove XXX and add test that bools can't be subclassed Modified: pypy/dist/pypy/objspace/std/booltype.py ============================================================================== --- pypy/dist/pypy/objspace/std/booltype.py (original) +++ pypy/dist/pypy/objspace/std/booltype.py Wed Jan 23 21:12:10 2008 @@ -1,9 +1,6 @@ from pypy.objspace.std.stdtypedef import * from pypy.objspace.std.inttype import int_typedef -# XXX should forbit subclassing of 'bool' - - def descr__new__(space, w_booltype, w_obj=None): space.w_bool.check_user_subclass(w_booltype) if space.is_true(w_obj): Modified: pypy/dist/pypy/objspace/std/test/test_boolobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_boolobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_boolobject.py Wed Jan 23 21:12:10 2008 @@ -44,3 +44,6 @@ assert bool.__new__(bool, "") is False raises(TypeError, bool.__new__, int) raises(TypeError, bool.__new__, 42) + + def test_cant_subclass_bool(self): + raises(TypeError, "class b(bool): pass") From exarkun at codespeak.net Wed Jan 23 21:31:50 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 23 Jan 2008 21:31:50 +0100 (CET) Subject: [pypy-svn] r50948 - pypy/build/buildbot Message-ID: <20080123203150.9E20916845E@codespeak.net> Author: exarkun Date: Wed Jan 23 21:31:49 2008 New Revision: 50948 Modified: pypy/build/buildbot/pypybuilders.py Log: Translate before testing (scary) Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Wed Jan 23 21:31:49 2008 @@ -132,6 +132,11 @@ slavedest="netstring.py", workdir="build/pypy-src") + self.addStep( + Translate, + translationArgs=translationArguments, + targetArgs=targetArguments) + if pytestArguments is not None: self.addStep( PyTest, @@ -139,12 +144,6 @@ testArguments=pytestArguments, timeout=60 * 60) - self.addStep( - Translate, - translationArgs=translationArguments, - targetArgs=targetArguments) - - if pytestArguments is not None: self.addStep( PyTest, python="pypy/translator/goal/pypy-c", From cfbolz at codespeak.net Wed Jan 23 23:53:22 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 23 Jan 2008 23:53:22 +0100 (CET) Subject: [pypy-svn] r50949 - in pypy/dist/pypy/objspace: . test Message-ID: <20080123225322.35433168454@codespeak.net> Author: cfbolz Date: Wed Jan 23 23:53:20 2008 New Revision: 50949 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: allow reflective space to handle is_true. Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Wed Jan 23 23:53:20 2008 @@ -36,6 +36,8 @@ for opname, _, args, _ in ObjSpace.MethodTable: if opname == name: return args + if opname == "is_true": + return 1 def make_space_access_method(name, wrappedfn, parentfn): if name.startswith("new") or name.endswith("_w"): @@ -50,6 +52,17 @@ finally: reset_reflective_space(space, w_old_reflectivespace) unwrap_spec = ['self', ObjSpace, W_Root, argument.Arguments] + elif name == "is_true": + def func(self, space, w_obj): + w_old_reflectivespace = get_reflective_space(space) + set_reflectivespace(space, self.w_reflectivespace) + try: + if parentfn(w_obj): + return space.w_True + return space.w_False + finally: + reset_reflective_space(space, w_old_reflectivespace) + unwrap_spec = ['self', ObjSpace, W_Root] else: args = get_spaceop_args(name) if args == 1: @@ -90,8 +103,8 @@ 'wrap', 'interpclass_w', 'unwrap', - 'is_true', 'marshal_w', + 'nonzero', # maps to is_true anyway ] @@ -175,6 +188,17 @@ space.wrap("space.type must return a type object!")) return w_obj return parentfn(*args_w) + elif opname == "is_true": + def fn(w_obj): + w_newobj = user_hook(w_obj) + if w_newobj is not None: + if w_newobj is space.w_True: + return True + elif w_newobj is space.w_False: + return False + raise OperationError(space.w_TypeError, + space.wrap("is_true must return True or False")) + return parentfn(w_obj) else: def fn(*args_w): w_obj = user_hook(*args_w) Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Wed Jan 23 23:53:20 2008 @@ -134,6 +134,25 @@ raises(AttributeError, "a.x = 2") set_reflectivespace(None) + def test_is_true(self): + from __pypy__ import set_reflectivespace + class Space: + def is_true(self, space, obj): + print "is_true", obj + if type(obj) == int: + # confusity + return bool(obj % 13) + return space.is_true(bool) + set_reflectivespace(Space()) + bool(13) + if 13: + assert False, "should not get here" + if "abc": + pass + else: + assert False, "should not get here" + set_reflectivespace(None) + def test_autocurry(self): # rather simplified for now From exarkun at codespeak.net Thu Jan 24 01:52:29 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Thu, 24 Jan 2008 01:52:29 +0100 (CET) Subject: [pypy-svn] r50953 - pypy/build/buildbot Message-ID: <20080124005229.4EF10168469@codespeak.net> Author: exarkun Date: Thu Jan 24 01:52:28 2008 New Revision: 50953 Modified: pypy/build/buildbot/netstring-conftest.py Log: Oops Hey kids, this is what happens when you don't do TDD. You get crappy code that is broken in the most trivial ways and you lose a night's worth of test results. Remember, only you can prevent forest fires. Modified: pypy/build/buildbot/netstring-conftest.py ============================================================================== --- pypy/build/buildbot/netstring-conftest.py (original) +++ pypy/build/buildbot/netstring-conftest.py Thu Jan 24 01:52:28 2008 @@ -17,7 +17,7 @@ # Marker so the peer can recognize our newline convention. >< # -exarkun - self.out('\n') + self.out.write('\n') def report_unknown(self, event): pass From fijal at codespeak.net Thu Jan 24 11:51:31 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 11:51:31 +0100 (CET) Subject: [pypy-svn] r50954 - pypy/dist/pypy/module/struct Message-ID: <20080124105131.EF565168462@codespeak.net> Author: fijal Date: Thu Jan 24 11:51:30 2008 New Revision: 50954 Modified: pypy/dist/pypy/module/struct/nativefmttable.py Log: Use single buffer instead of allocating one per-cast. (I want to have cast_int_to_float operation anyway) Modified: pypy/dist/pypy/module/struct/nativefmttable.py ============================================================================== --- pypy/dist/pypy/module/struct/nativefmttable.py (original) +++ pypy/dist/pypy/module/struct/nativefmttable.py Thu Jan 24 11:51:30 2008 @@ -16,51 +16,38 @@ # ____________________________________________________________ +double_buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', immortal=True) +float_buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw', immortal=True) + def pack_double(fmtiter): doubleval = fmtiter.accept_float_arg() - buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') - try: - buf[0] = doubleval - p = rffi.cast(rffi.CCHARP, buf) - for i in range(sizeof_double): - fmtiter.result.append(p[i]) - finally: - lltype.free(buf, flavor='raw') + double_buf[0] = doubleval + p = rffi.cast(rffi.CCHARP, double_buf) + for i in range(sizeof_double): + fmtiter.result.append(p[i]) def unpack_double(fmtiter): input = fmtiter.read(sizeof_double) - buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw') - try: - p = rffi.cast(rffi.CCHARP, buf) - for i in range(sizeof_double): - p[i] = input[i] - doubleval = buf[0] - finally: - lltype.free(buf, flavor='raw') + p = rffi.cast(rffi.CCHARP, double_buf) + for i in range(sizeof_double): + p[i] = input[i] + doubleval = double_buf[0] fmtiter.appendobj(doubleval) def pack_float(fmtiter): doubleval = fmtiter.accept_float_arg() floatval = r_singlefloat(doubleval) - buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw') - try: - buf[0] = floatval - p = rffi.cast(rffi.CCHARP, buf) - for i in range(sizeof_float): - fmtiter.result.append(p[i]) - finally: - lltype.free(buf, flavor='raw') + float_buf[0] = floatval + p = rffi.cast(rffi.CCHARP, float_buf) + for i in range(sizeof_float): + fmtiter.result.append(p[i]) def unpack_float(fmtiter): input = fmtiter.read(sizeof_float) - buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw') - try: - p = rffi.cast(rffi.CCHARP, buf) - for i in range(sizeof_float): - p[i] = input[i] - floatval = buf[0] - finally: - lltype.free(buf, flavor='raw') + p = rffi.cast(rffi.CCHARP, float_buf) + for i in range(sizeof_float): + p[i] = input[i] + floatval = float_buf[0] doubleval = float(floatval) fmtiter.appendobj(doubleval) From fijal at codespeak.net Thu Jan 24 13:34:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 13:34:37 +0100 (CET) Subject: [pypy-svn] r50960 - pypy/dist/pypy/config Message-ID: <20080124123437.666641684C5@codespeak.net> Author: fijal Date: Thu Jan 24 13:34:36 2008 New Revision: 50960 Modified: pypy/dist/pypy/config/pypyoption.py Log: Remove zipimporter from allworkingmodules, distutils tend to choke on lack of undocumented features. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Thu Jan 24 13:34:36 2008 @@ -24,7 +24,7 @@ working_modules.update(dict.fromkeys( ["_socket", "unicodedata", "mmap", "fcntl", "rctime", "select", "crypt", "signal", "dyngram", "readline", "termios", "zlib", - "struct", "md5", "sha", "bz2", "zipimport", + "struct", "md5", "sha", "bz2", ] )) From cfbolz at codespeak.net Thu Jan 24 13:50:16 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 24 Jan 2008 13:50:16 +0100 (CET) Subject: [pypy-svn] r50961 - in pypy/branch/asmgcroot/pypy/config: . test Message-ID: <20080124125016.0904B168480@codespeak.net> Author: cfbolz Date: Thu Jan 24 13:50:15 2008 New Revision: 50961 Modified: pypy/branch/asmgcroot/pypy/config/config.py pypy/branch/asmgcroot/pypy/config/test/test_config.py Log: allow suggestions for choice options to Modified: pypy/branch/asmgcroot/pypy/config/config.py ============================================================================== --- pypy/branch/asmgcroot/pypy/config/config.py (original) +++ pypy/branch/asmgcroot/pypy/config/config.py Thu Jan 24 13:50:15 2008 @@ -218,13 +218,16 @@ opt_type = 'string' def __init__(self, name, doc, values, default=None, requires=None, - cmdline=DEFAULT_OPTION_NAME): + suggests=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 + if suggests is None: + suggests = {} + self._suggests = suggests def setoption(self, config, value, who): name = self._name @@ -232,6 +235,15 @@ toplevel = config._cfgimpl_get_toplevel() homeconfig, name = toplevel._cfgimpl_get_home_by_path(path) homeconfig.setoption(name, reqvalue, who) + for path, reqvalue in self._suggests.get(value, []): + toplevel = config._cfgimpl_get_toplevel() + homeconfig, name = toplevel._cfgimpl_get_home_by_path(path) + try: + homeconfig.setoption(name, reqvalue, "suggested") + except ValueError: + # setting didn't work, but that is fine, since it is + # suggested only + pass super(ChoiceOption, self).setoption(config, value, who) def validate(self, value): Modified: pypy/branch/asmgcroot/pypy/config/test/test_config.py ============================================================================== --- pypy/branch/asmgcroot/pypy/config/test/test_config.py (original) +++ pypy/branch/asmgcroot/pypy/config/test/test_config.py Thu Jan 24 13:50:15 2008 @@ -447,7 +447,7 @@ assert c2.s1.a c2.int = 44 # does not crash -def test_suggests(): +def test_bool_suggests(): descr = OptionDescription("test", '', [ BoolOption("toplevel", "", default=False), BoolOption("opt", "", default=False, @@ -504,6 +504,30 @@ assert not c.t2 +def test_choice_suggests(): + descr = OptionDescription("test", '', [ + BoolOption("toplevel", "", default=False), + ChoiceOption("opt", "", ["a", "b", "c"], + "a", + suggests={"b": [("toplevel", True)]}) + ]) + c = Config(descr) + assert not c.toplevel + assert c.opt == "a" + c.opt = "b" + assert c.opt == "b" + assert c.toplevel + # does not crash + c.toplevel = False + assert not c.toplevel + + c = Config(descr) + c.toplevel = False + assert not c.toplevel + # does not crash + c.opt = "b" + assert c.opt == "b" + assert not c.toplevel def test_delattr(): From fijal at codespeak.net Thu Jan 24 14:20:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 14:20:36 +0100 (CET) Subject: [pypy-svn] r50962 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080124132036.AE86916847F@codespeak.net> Author: fijal Date: Thu Jan 24 14:20:36 2008 New Revision: 50962 Added: pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py Log: A bit of special-logic and 3 more tests pass. Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Thu Jan 24 14:20:36 2008 @@ -53,6 +53,25 @@ return self(*value) return _CDataMeta.from_param(self, value) +def array_get_slice_params(self, index): + if index.step is not None: + raise TypeError("3 arg slices not supported (for no reason)") + start = index.start or 0 + stop = index.stop or self._length_ + return start, stop + +def array_slice_setitem(self, index, value): + start, stop = self._get_slice_params(index) + for i in range(start, stop): + self[i] = value[i - start] + +def array_slice_getitem(self, index): + start, stop = self._get_slice_params(index) + l = [self[i] for i in range(start, stop)] + if getattr(self._type_, '_type_', None) == 'c': + return "".join(l) + return l + class Array(_CData): __metaclass__ = ArrayMeta _ffiletter = 'P' @@ -70,24 +89,9 @@ else: raise IndexError - def _get_slice_params(self, index): - if index.step is not None: - raise TypeError("3 arg slices not supported (for no reason)") - start = index.start or 0 - stop = index.stop or self._length_ - return start, stop - - def _slice_setitem(self, index, value): - start, stop = self._get_slice_params(index) - for i in range(start, stop): - self[i] = value[i - start] - - def _slice_getitem(self, index): - start, stop = self._get_slice_params(index) - l = [self[i] for i in range(start, stop)] - if getattr(self._type_, '_type_', None) == 'c': - return "".join(l) - return l + _get_slice_params = array_get_slice_params + _slice_getitem = array_slice_getitem + _slice_setitem = array_slice_setitem def _subarray(self, index): """Return a _rawffi array of length 1 whose address is the same as Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Thu Jan 24 14:20:36 2008 @@ -2,7 +2,8 @@ import _rawffi from _ctypes.basics import _CData, _CDataMeta, cdata_from_address from _ctypes.basics import sizeof, byref -from _ctypes.array import Array +from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\ + array_slice_setitem DEFAULT_VALUE = object() @@ -78,14 +79,19 @@ value = value._buffer self._buffer[0] = value + _get_slice_params = array_get_slice_params + _slice_getitem = array_slice_getitem + def _subarray(self, index=0): """Return a _rawffi array of length 1 whose address is the same as the index'th item to which self is pointing.""" address = self._buffer[0] address += index * sizeof(self._type_) - return self._type_._ffiarray.fromaddress(address, 1) + return self._type_.from_address(address)._buffer def __getitem__(self, index): + if isinstance(index, slice): + return self._slice_getitem(index) return self._type_._CData_output(self._subarray(index)) def __setitem__(self, index, value): @@ -100,12 +106,17 @@ def _cast_addr(obj, _, tp): - if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): - raise TypeError("cast() argument 1 must be a pointer, not %s" - % (type(obj),)) if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()): raise TypeError("cast() argument 2 must be a pointer type, not %s" % (tp,)) + if isinstance(obj, Array): + ptr = tp.__new__(tp) + ptr._buffer = tp._ffiarray(1) + ptr._buffer[0] = obj._buffer + return ptr + if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): + raise TypeError("cast() argument 1 must be a pointer, not %s" + % (type(obj),)) result = tp() result._buffer[0] = obj._buffer[0] return result Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 24 14:20:36 2008 @@ -117,7 +117,6 @@ return self._ffistruct.alignment def _CData_output(self, resarray): - assert isinstance(resarray, _rawffi.ArrayInstance) res = self.__new__(self) ffistruct = self._ffistruct.fromaddress(resarray.buffer) res.__dict__['_buffer'] = ffistruct Added: pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py Thu Jan 24 14:20:36 2008 @@ -0,0 +1,63 @@ +from ctypes import * +from binascii import hexlify +import re +import _rawffi + +def dump(obj): + # helper function to dump memory contents in hex, with a hyphen + # between the bytes. + # cast it to the raw buffer + size = sizeof(obj) + a = _rawffi.Array('c').fromaddress(obj._buffer.buffer, size) + h = hexlify([a[i] for i in range(len(a))]) + return re.sub(r"(..)", r"\1-", h)[:-1] + +class Value(Structure): + _fields_ = [("val", c_byte)] + +class Container(Structure): + _fields_ = [("pvalues", POINTER(Value))] + +class TestOne: + def test(self): + # create an array of 4 values + val_array = (Value * 4)() + + # create a container, which holds a pointer to the pvalues array. + c = Container() + c.pvalues = val_array + + # memory contains 4 NUL bytes now, that's correct + assert "00-00-00-00" == dump(val_array) + + # set the values of the array through the pointer: + for i in range(4): + c.pvalues[i].val = i + 1 + + values = [c.pvalues[i].val for i in range(4)] + + # These are the expected results: here s the bug! + assert ( + (values, dump(val_array))) == ( + ([1, 2, 3, 4], "01-02-03-04") + ) + + def test_2(self): + + val_array = (Value * 4)() + + # memory contains 4 NUL bytes now, that's correct + assert "00-00-00-00" == dump(val_array) + + ptr = cast(val_array, POINTER(Value)) + # set the values of the array through the pointer: + for i in range(4): + ptr[i].val = i + 1 + + values = [ptr[i].val for i in range(4)] + + # These are the expected results: here s the bug! + assert ( + (values, dump(val_array))) == ( + ([1, 2, 3, 4], "01-02-03-04") + ) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py Thu Jan 24 14:20:36 2008 @@ -27,7 +27,6 @@ assert string_at(a, 20) == "xxxxxxxxxxxxxxxx\0\0\0\0" def test_cast(self): - py.test.skip("I'm not sure I understood") a = (c_ubyte * 32)(*map(ord, "abcdef")) assert cast(a, c_char_p).value == "abcdef" assert cast(a, POINTER(c_byte))[:7] == ( From fijal at codespeak.net Thu Jan 24 14:48:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 14:48:03 +0100 (CET) Subject: [pypy-svn] r50963 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080124134803.891501684D4@codespeak.net> Author: fijal Date: Thu Jan 24 14:48:02 2008 New Revision: 50963 Added: pypy/dist/pypy/lib/app_test/ctypes/test_anon.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/_ctypes/union.py Log: Anonymous structures. VERY custom logic. Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 24 14:48:02 2008 @@ -22,13 +22,12 @@ size = round_up(size, alignment) return size, alignment, pos - def struct_getattr(self, name): if hasattr(self, '_fieldtypes') and name in self._fieldtypes: return self._fieldtypes[name] return _CDataMeta.__getattribute__(self, name) -def names_and_fields(_fields_, superclass, zero_offset=False): +def names_and_fields(_fields_, superclass, zero_offset=False, anon=None): for _, tp in _fields_: if not isinstance(tp, _CDataMeta): raise TypeError("Expected CData subclass, got %s" % (tp,)) @@ -46,6 +45,19 @@ fields = {} for i, (name, ctype) in enumerate(all_fields): fields[name] = Field(name, pos[i], ctypes.sizeof(ctype), ctype) + if anon: + resnames = [] + for i, (name, value) in enumerate(all_fields): + if name in anon: + for subname in value._names: + resnames.append(subname) + relpos = pos[i] + value._fieldtypes[subname].offset + subvalue = value._fieldtypes[subname].ctype + fields[subname] = Field(subname, relpos, + ctypes.sizeof(subvalue), subvalue) + else: + resnames.append(name) + names = resnames return names, rawfields, fields class Field(object): @@ -64,8 +76,14 @@ def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: + if not hasattr(typedict.get('_anonymous_', []), '__iter__'): + raise TypeError("Anonymous field must be iterable") + for item in typedict.get('_anonymous_', []): + if item not in dict(typedict['_fields_']): + raise AttributeError("Anonymous field not found") res._names, rawfields, res._fieldtypes = names_and_fields( - typedict['_fields_'], cls[0]) + typedict['_fields_'], cls[0], False, + typedict.get('_anonymous_', None)) res._ffistruct = _rawffi.Structure(rawfields) res._ffishape = res._ffistruct.gettypecode() Modified: pypy/dist/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/union.py (original) +++ pypy/dist/pypy/lib/_ctypes/union.py Thu Jan 24 14:48:02 2008 @@ -10,7 +10,8 @@ res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: res._names, rawfields, res._fieldtypes = names_and_fields( - typedict['_fields_'], cls[0], True) + typedict['_fields_'], cls[0], True, + typedict.get('_anonymous_', None)) res._ffishape = (res._sizeofinstances(), res._alignmentofinstances()) # we need to create an array of size one for each Added: pypy/dist/pypy/lib/app_test/ctypes/test_anon.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_anon.py Thu Jan 24 14:48:02 2008 @@ -0,0 +1,57 @@ +from ctypes import * + +class TestAnon: + + def test_anon(self): + class ANON(Union): + _fields_ = [("a", c_int), + ("b", c_int)] + + class Y(Structure): + _fields_ = [("x", c_int), + ("_", ANON), + ("y", c_int)] + _anonymous_ = ["_"] + + assert Y.a.offset == sizeof(c_int) + assert Y.b.offset == sizeof(c_int) + + assert ANON.a.offset == 0 + assert ANON.b.offset == 0 + + def test_anon_nonseq(self): + # TypeError: _anonymous_ must be a sequence + raises(TypeError, + lambda: type(Structure)("Name", + (Structure,), + {"_fields_": [], "_anonymous_": 42})) + + def test_anon_nonmember(self): + # AttributeError: type object 'Name' has no attribute 'x' + raises(AttributeError, + lambda: type(Structure)("Name", + (Structure,), + {"_fields_": [], + "_anonymous_": ["x"]})) + + def test_nested(self): + class ANON_S(Structure): + _fields_ = [("a", c_int)] + + class ANON_U(Union): + _fields_ = [("_", ANON_S), + ("b", c_int)] + _anonymous_ = ["_"] + + class Y(Structure): + _fields_ = [("x", c_int), + ("_", ANON_U), + ("y", c_int)] + _anonymous_ = ["_"] + + assert Y.x.offset == 0 + assert Y.a.offset == sizeof(c_int) + assert Y.b.offset == sizeof(c_int) + assert Y._.offset == sizeof(c_int) + assert Y.y.offset == sizeof(c_int) * 2 + From fijal at codespeak.net Thu Jan 24 14:54:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 14:54:35 +0100 (CET) Subject: [pypy-svn] r50964 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080124135435.6508A1684D7@codespeak.net> Author: fijal Date: Thu Jan 24 14:54:35 2008 New Revision: 50964 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/_ctypes/union.py Log: A bit of custom union support (no test this time) Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Thu Jan 24 14:54:35 2008 @@ -27,6 +27,21 @@ return self._fieldtypes[name] return _CDataMeta.__getattribute__(self, name) +def struct_setattr(self, name, value): + if name == '_fields_': + if self.__dict__.get('_fields_', None): + raise AttributeError("_fields_ is final") + if self in [v for k, v in value]: + raise AttributeError("Structure or union cannot contain itself") + self._names, rawfields, self._fieldtypes = names_and_fields( + value, self.__bases__[0], self._is_union, + self.__dict__.get('_anonymous_', None)) + self._ffistruct = _rawffi.Structure(rawfields) + _CDataMeta.__setattr__(self, '_fields_', value) + self._ffishape = self._ffistruct.gettypecode() + return + _CDataMeta.__setattr__(self, name, value) + def names_and_fields(_fields_, superclass, zero_offset=False, anon=None): for _, tp in _fields_: if not isinstance(tp, _CDataMeta): @@ -73,6 +88,8 @@ self.size) class StructureMeta(_CDataMeta): + _is_union = False + def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: @@ -106,20 +123,7 @@ return res __getattr__ = struct_getattr - - def __setattr__(self, name, value): - if name == '_fields_': - if self.__dict__.get('_fields_', None): - raise AttributeError("_fields_ is final") - if self in [v for k, v in value]: - raise AttributeError("Structure or union cannot contain itself") - self._names, rawfields, self._fieldtypes = names_and_fields( - value, self.__bases__[0]) - self._ffistruct = _rawffi.Structure(rawfields) - _CDataMeta.__setattr__(self, '_fields_', value) - self._ffishape = self._ffistruct.gettypecode() - return - _CDataMeta.__setattr__(self, name, value) + __setattr__ = struct_setattr def from_address(self, address): instance = self.__new__(self) Modified: pypy/dist/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/union.py (original) +++ pypy/dist/pypy/lib/_ctypes/union.py Thu Jan 24 14:54:35 2008 @@ -2,10 +2,13 @@ import _rawffi from _ctypes.basics import _CData, _CDataMeta -from _ctypes.structure import round_up, names_and_fields, struct_getattr +from _ctypes.structure import round_up, names_and_fields, struct_getattr,\ + struct_setattr import inspect class UnionMeta(_CDataMeta): + _is_union = True + def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: @@ -38,7 +41,8 @@ self._alignment_ = max([alignment(field.ctype) for field in self._fieldtypes.values()] + [1]) return self._alignment_ - + + __setattr__ = struct_setattr __getattr__ = struct_getattr class Union(_CData): From fijal at codespeak.net Thu Jan 24 15:12:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 15:12:24 +0100 (CET) Subject: [pypy-svn] r50967 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080124141224.8B10E168466@codespeak.net> Author: fijal Date: Thu Jan 24 15:12:23 2008 New Revision: 50967 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Some support for UniChar in ll2ctypes Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Thu Jan 24 15:12:23 2008 @@ -41,6 +41,7 @@ rffi.LONGLONG: ctypes.c_longlong, rffi.ULONGLONG: ctypes.c_ulonglong, rffi.SIZE_T: ctypes.c_size_t, + lltype.UniChar: ctypes.c_wchar, }) def build_ctypes_struct(S, delayed_builders, max_n=None): @@ -443,7 +444,7 @@ else: raise NotImplementedError(llobj) # don't know about symbolic value - if T is lltype.Char: + if T is lltype.Char or T is lltype.UniChar: return ord(llobj) if T is lltype.SingleFloat: @@ -480,6 +481,8 @@ llobj = lltype._ptr(T, container, solid=True) elif T is lltype.Char: llobj = chr(cobj) + elif T is lltype.UniChar: + llobj = unichr(cobj) elif T is lltype.Signed: llobj = cobj elif T is lltype.SingleFloat: Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Thu Jan 24 15:12:23 2008 @@ -1774,7 +1774,7 @@ return _ptr(PTRTYPE, oddint, solid=True) def cast_float_to_int(val): - return struct.unpack('i', struct.pack('f', val))[0] + return struct.unpack('i', struct.pack('d', val))[0] def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): if not isinstance(GCSTRUCT, RttiStruct): Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Jan 24 15:12:23 2008 @@ -23,9 +23,11 @@ assert lltype2ctypes('\xE0') == 0xE0 assert ctypes2lltype(lltype.Signed, 5) == 5 assert ctypes2lltype(lltype.Char, ord('a')) == 'a' + assert ctypes2lltype(lltype.UniChar, ord(u'x')) == u'x' assert ctypes2lltype(lltype.Char, 0xFF) == '\xFF' assert lltype2ctypes(5.25) == 5.25 assert ctypes2lltype(lltype.Float, 5.25) == 5.25 + assert lltype2ctypes(u'x') == ord(u'x') res = lltype2ctypes(rffi.r_singlefloat(-3.5)) assert isinstance(res, ctypes.c_float) assert res.value == -3.5 From fijal at codespeak.net Thu Jan 24 15:20:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 15:20:26 +0100 (CET) Subject: [pypy-svn] r50968 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080124142026.85E9716847B@codespeak.net> Author: fijal Date: Thu Jan 24 15:20:26 2008 New Revision: 50968 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: A failing unicharp test. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Jan 24 15:20:26 2008 @@ -142,6 +142,21 @@ rffi.free_charp(s) assert not ALLOCATED # detects memory leaks in the test + def test_unicharp(self): + py.test.skip("Unsupported") + SP = rffi.CArrayPtr(lltype.UniChar) + s = lltype.malloc(SP.TO, 3, flavor='raw') + s[0] = u'x' + s[1] = u'y' + s[2] = u'z' + sc = lltype2ctypes(s, normalize=False) + assert sc.contents.items[0] == u'x' + assert sc.contents.items[1] == u'y' + assert sc.contents.items[2] == u'z' + assert not hasattr(sc.contents, 'length') + lltype.free(s, flavor='raw') + assert not ALLOCATED + def test_strlen(self): eci = ExternalCompilationInfo(includes=['string.h']) strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T, From arigo at codespeak.net Thu Jan 24 16:01:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 24 Jan 2008 16:01:02 +0100 (CET) Subject: [pypy-svn] r50969 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080124150102.3E25916847F@codespeak.net> Author: arigo Date: Thu Jan 24 16:01:00 2008 New Revision: 50969 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: fijal: please adapt these tests for floating-point instructions if you plan to work more on them 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 Thu Jan 24 16:01:00 2008 @@ -282,6 +282,8 @@ #print name if name in ('CMOVPE', 'CMOVPO'): py.test.skip("why doesn't 'as' know about CMOVPE/CMOVPO?") + if name in ('FADD', 'FLD'): + py.test.skip("XXX TEST ME: " + name) complete_test(name, insn) items = all_instructions.items() From fijal at codespeak.net Thu Jan 24 16:54:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 16:54:26 +0100 (CET) Subject: [pypy-svn] r50970 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080124155426.3F8A3168460@codespeak.net> Author: fijal Date: Thu Jan 24 16:54:24 2008 New Revision: 50970 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: I still don't understand why it's failing, will look later, but don't raise string exception anyway/ 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 Thu Jan 24 16:54:24 2008 @@ -158,7 +158,7 @@ try: f = open(FILENAME, 'rb') except IOError: - raise "Assembler error" + raise Exception("Assembler error") data = f.read() f.close() ## os.unlink(FILENAME) From fijal at codespeak.net Thu Jan 24 17:11:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 17:11:08 +0100 (CET) Subject: [pypy-svn] r50974 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080124161108.25408168460@codespeak.net> Author: fijal Date: Thu Jan 24 17:11:07 2008 New Revision: 50974 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Add obscure specialcase. I couldn't find better way of handling it, because .items seems to be immutable however hard I try. Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Thu Jan 24 17:11:07 2008 @@ -234,9 +234,14 @@ carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): - for i in range(container.getlength()): - item_value = container.items[i] # fish fish - carray.items[i] = lltype2ctypes(item_value) + # XXX obscure case when array.items is not modifiable + if isinstance(carray.items, unicode): + carray.items = u''.join([container.items[i] for i in + range(container.getlength())]) + else: + for i in range(container.getlength()): + item_value = container.items[i] # fish fish + carray.items[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Jan 24 17:11:07 2008 @@ -143,7 +143,6 @@ assert not ALLOCATED # detects memory leaks in the test def test_unicharp(self): - py.test.skip("Unsupported") SP = rffi.CArrayPtr(lltype.UniChar) s = lltype.malloc(SP.TO, 3, flavor='raw') s[0] = u'x' From fijal at codespeak.net Thu Jan 24 17:25:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 17:25:22 +0100 (CET) Subject: [pypy-svn] r50978 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080124162522.D7A37168462@codespeak.net> Author: fijal Date: Thu Jan 24 17:25:22 2008 New Revision: 50978 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Log: Kill obscurity (not sure if wchar is always the size of unsigned short) Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Thu Jan 24 17:25:22 2008 @@ -41,7 +41,7 @@ rffi.LONGLONG: ctypes.c_longlong, rffi.ULONGLONG: ctypes.c_ulonglong, rffi.SIZE_T: ctypes.c_size_t, - lltype.UniChar: ctypes.c_wchar, + lltype.UniChar: ctypes.c_ushort, }) def build_ctypes_struct(S, delayed_builders, max_n=None): @@ -234,14 +234,9 @@ carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): - # XXX obscure case when array.items is not modifiable - if isinstance(carray.items, unicode): - carray.items = u''.join([container.items[i] for i in - range(container.getlength())]) - else: - for i in range(container.getlength()): - item_value = container.items[i] # fish fish - carray.items[i] = lltype2ctypes(item_value) + for i in range(container.getlength()): + item_value = container.items[i] # fish fish + carray.items[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Jan 24 17:25:22 2008 @@ -21,6 +21,7 @@ assert lltype2ctypes(5) == 5 assert lltype2ctypes('?') == ord('?') assert lltype2ctypes('\xE0') == 0xE0 + assert lltype2ctypes(unichr(1234)) == 1234 assert ctypes2lltype(lltype.Signed, 5) == 5 assert ctypes2lltype(lltype.Char, ord('a')) == 'a' assert ctypes2lltype(lltype.UniChar, ord(u'x')) == u'x' @@ -144,14 +145,15 @@ def test_unicharp(self): SP = rffi.CArrayPtr(lltype.UniChar) - s = lltype.malloc(SP.TO, 3, flavor='raw') + s = lltype.malloc(SP.TO, 4, flavor='raw') s[0] = u'x' s[1] = u'y' s[2] = u'z' + s[3] = u'\x00' sc = lltype2ctypes(s, normalize=False) - assert sc.contents.items[0] == u'x' - assert sc.contents.items[1] == u'y' - assert sc.contents.items[2] == u'z' + assert sc.contents.items[0] == ord(u'x') + assert sc.contents.items[1] == ord(u'y') + assert sc.contents.items[2] == ord(u'z') assert not hasattr(sc.contents, 'length') lltype.free(s, flavor='raw') assert not ALLOCATED From fijal at codespeak.net Thu Jan 24 17:28:52 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 17:28:52 +0100 (CET) Subject: [pypy-svn] r50979 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080124162852.20A79168466@codespeak.net> Author: fijal Date: Thu Jan 24 17:28:51 2008 New Revision: 50979 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: * Support for wide chars * Accept 'Z' as synonym to 'P' Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Thu Jan 24 17:28:51 2008 @@ -30,6 +30,7 @@ 'b' : ffi_type_schar, 'B' : ffi_type_uchar, 'h' : ffi_type_sshort, + 'u' : ffi_type_ushort, # XXX alias for wide-character 'H' : ffi_type_ushort, 'i' : ffi_type_sint, 'I' : ffi_type_uint, @@ -45,6 +46,7 @@ 'P' : ffi_type_pointer, 'z' : ffi_type_pointer, 'O' : ffi_type_pointer, + 'Z' : ffi_type_pointer, } TYPEMAP_PTR_LETTERS = "POsz" @@ -55,6 +57,7 @@ LL_TYPEMAP = { 'c' : rffi.CHAR, + 'u' : lltype.UniChar, 'b' : rffi.SIGNEDCHAR, 'B' : rffi.UCHAR, 'h' : rffi.SHORT, @@ -227,6 +230,13 @@ "Expected string of length one as character")) val = s[0] push_func(add_arg, argdesc, val) + elif letter == 'u': + s = space.unicode_w(w_arg) + if len(s) != 1: + raise OperationError(space.w_TypeError, w( + "Expected unicode string og length one as wide character")) + val = s[0] + push_func(add_arg, argdesc, val) else: for c in unroll_letters_for_numbers: if letter == c: @@ -251,7 +261,7 @@ elif c == 'v': func(add_arg, argdesc, ll_type) return space.w_None - elif c == 'q' or c == 'Q' or c == 'L' or c == 'c': + elif c == 'q' or c == 'Q' or c == 'L' or c == 'c' or c == 'u': return space.wrap(func(add_arg, argdesc, ll_type)) elif c == 'f' or c == 'd': return space.wrap(float(func(add_arg, argdesc, ll_type))) Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Thu Jan 24 17:28:51 2008 @@ -497,6 +497,14 @@ len(a)) a.free() + def test_wide_char(self): + import _rawffi + A = _rawffi.Array('u') + a = A(1) + a[0] = u'x' + assert a[0] == u'x' + a.free() + def test_truncate(self): import _rawffi, struct a = _rawffi.Array('b')(1) From antocuni at codespeak.net Thu Jan 24 18:25:19 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 24 Jan 2008 18:25:19 +0100 (CET) Subject: [pypy-svn] r50983 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20080124172519.6022C16844B@codespeak.net> Author: antocuni Date: Thu Jan 24 18:25:17 2008 New Revision: 50983 Modified: pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/rte.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/test_dotnet.py Log: whack until dynami method creation/invocation works in rpython Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Thu Jan 24 18:25:17 2008 @@ -207,11 +207,14 @@ self.opcode('ldarg', repr(v.name)) def load_local(self, v): - TYPE = v.concretetype - if getattr(TYPE, '_is_value_type', False): - self.opcode('ldloca', repr(v.name)) - else: - self.opcode('ldloc', repr(v.name)) + self.opcode('ldloc', repr(v.name)) +## # the code commented out is needed to pass test_static_fields, +## # but breaks other tests +## TYPE = v.concretetype +## if getattr(TYPE, '_is_value_type', False): +## self.opcode('ldloca', repr(v.name)) +## else: +## self.opcode('ldloc', repr(v.name)) def switch(self, targets): cmd = 'switch(%s)' % ', '.join(targets) Modified: pypy/dist/pypy/translator/cli/rte.py ============================================================================== --- pypy/dist/pypy/translator/cli/rte.py (original) +++ pypy/dist/pypy/translator/cli/rte.py Thu Jan 24 18:25:17 2008 @@ -82,6 +82,13 @@ FLAGS = ['/t:library', '/unsafe', '/r:main.exe'] DEPENDENCIES = [MainStub] + def compile(cls, sources, out): + from pypy.translator.cli.query import pypylib + remove_cache_for_assembly(pypylib) + Target.compile.im_func(cls, sources, out) + compile = classmethod(compile) + + class RPythonNetModule(Target): SOURCES = [] OUTPUT = 'rpython.netmodule' @@ -95,10 +102,9 @@ def compile(cls, sources, out): # assume that if query.exe need to be recompiled the descriptions cache is invalid - from pypy.translator.cli.query import get_cachedir, mscorlib - mscorlib_cache = get_cachedir().join(mscorlib + '.pickle') - if mscorlib_cache.check(): - mscorlib_cache.remove() + from pypy.translator.cli.query import mscorlib, pypylib + remove_cache_for_assembly(mscorlib) + remove_cache_for_assembly(pypylib) Target.compile.im_func(cls, sources, out) compile = classmethod(compile) @@ -110,5 +116,11 @@ def get_pypy_dll(): return PyPyLibDLL.get() +def remove_cache_for_assembly(ass): + from pypy.translator.cli.query import get_cachedir + cache = get_cachedir().join(ass + '.pickle') + if cache.check(): + cache.remove() + if __name__ == '__main__': get_pypy_dll() Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Thu Jan 24 18:25:17 2008 @@ -3,6 +3,7 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; using System.IO; +using System.Reflection.Emit; using pypy.runtime; namespace pypy.test @@ -52,8 +53,15 @@ namespace pypy.runtime { + public delegate int DelegateType_int__int_int(int a, int b); + public class Utils { + public static DynamicMethod CreateDynamicMethod(string name, Type res, Type[] args) + { + return new DynamicMethod(name, res, args, typeof(Utils).Module); + } + public static object RuntimeNew(Type t) { return t.GetConstructor(new Type[0]).Invoke(new object[0]); Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/dist/pypy/translator/cli/test/test_dotnet.py Thu Jan 24 18:25:17 2008 @@ -11,6 +11,8 @@ System = CLR.System ArrayList = CLR.System.Collections.ArrayList +OpCodes = System.Reflection.Emit.OpCodes +DynamicMethod = System.Reflection.Emit.DynamicMethod class TestDotnetAnnotation(object): @@ -349,7 +351,7 @@ def test_typeof(self): def fn(): x = box(42) - return x.GetType() == typeof(System.Int32) + return x.GetType() == typeof(System.Int32) res = self.interpret(fn, []) assert res is True @@ -433,7 +435,7 @@ assert res == 42 def test_static_fields(self): - OpCodes = System.Reflection.Emit.OpCodes + py.test.skip("does not work, and no need to implement") def fn(): op = OpCodes.Add return op.get_Name() @@ -446,6 +448,28 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == '42' + def test_dynamic_method(self): + from pypy.rpython.ootypesystem import ootype + self._skip_pythonnet("does not work") + DelegateType = CLR.pypy.runtime.DelegateType_int__int_int + DELEGATETYPE = DelegateType._INSTANCE + Utils = CLR.pypy.runtime.Utils + def fn(): + tInt = typeof(System.Int32) + args = init_array(System.Type, tInt, tInt) + meth = Utils.CreateDynamicMethod("add", tInt, args) + il = meth.GetILGenerator() + il.Emit(OpCodes.Ldarg_0) + il.Emit(OpCodes.Ldarg_1) + il.Emit(OpCodes.Add) + il.Emit(OpCodes.Ret) + myfunc = meth.CreateDelegate(typeof(DelegateType)) + myfunc = ootype.oodowncast(DELEGATETYPE, myfunc) # XXX messy + return myfunc.Invoke(30, 12) + res = self.interpret(fn, []) + assert res == 42 + + class TestPythonnet(TestDotnetRtyping): # don't interpreter functions but execute them directly through pythonnet def interpret(self, f, args, backendopt='ignored'): @@ -456,3 +480,4 @@ def test_whitout_box(self): pass # it makes sense only during translation + From cfbolz at codespeak.net Thu Jan 24 19:34:29 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 24 Jan 2008 19:34:29 +0100 (CET) Subject: [pypy-svn] r50987 - in pypy/branch/asmgcroot/pypy: config config/test doc/config translator/c translator/c/gcc/test translator/llvm Message-ID: <20080124183429.280CB168457@codespeak.net> Author: cfbolz Date: Thu Jan 24 19:34:28 2008 New Revision: 50987 Added: pypy/branch/asmgcroot/pypy/doc/config/translation.gcrootfinder.txt (contents, props changed) Modified: pypy/branch/asmgcroot/pypy/config/test/test_pypyoption.py pypy/branch/asmgcroot/pypy/config/translationoption.py pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py pypy/branch/asmgcroot/pypy/translator/c/genc.py pypy/branch/asmgcroot/pypy/translator/llvm/codewriter.py Log: unify the various options for chosing a GC root finding algorithm Modified: pypy/branch/asmgcroot/pypy/config/test/test_pypyoption.py ============================================================================== --- pypy/branch/asmgcroot/pypy/config/test/test_pypyoption.py (original) +++ pypy/branch/asmgcroot/pypy/config/test/test_pypyoption.py Thu Jan 24 19:34:28 2008 @@ -18,14 +18,14 @@ def test_stacklessgc_required(): conf = get_pypy_config() - conf.translation.stacklessgc = True + conf.translation.gcrootfinder = "stackless" assert conf.translation.stackless assert conf.translation.type_system == "lltype" assert conf.translation.gctransformer == "framework" - assert conf.translation.gc == "marksweep" + assert conf.translation.gc == "generation" conf = get_pypy_config() conf.translation.gc = "boehm" - py.test.raises(ValueError, "conf.translation.stacklessgc = True") + py.test.raises(ValueError, "conf.translation.gcrootfinder = 'stackless'") def test_frameworkgc(): Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py ============================================================================== --- pypy/branch/asmgcroot/pypy/config/translationoption.py (original) +++ pypy/branch/asmgcroot/pypy/config/translationoption.py Thu Jan 24 19:34:28 2008 @@ -56,19 +56,27 @@ ChoiceOption("gctransformer", "GC transformer that is used - internal", ["boehm", "ref", "framework", "none"], default="ref", cmdline=None), - - BoolOption("stacklessgc", "Use stackless to find roots in a framework GC", - default=False, cmdline="--stacklessgc", - requires=[("translation.gctransformer", "framework"), - ("translation.stackless", True)], - suggests=[("translation.gc", "marksweep")]), - BoolOption("llvmgcroot", "Use the 'llvm.gcroot' primitive to find roots", - default=False, cmdline="--llvmgcroot", - requires=[("translation.gctransformer", "framework"), - ("translation.backend", "llvm")]), - BoolOption("asmgcroot", "Use the 'trackgcroot' asm hack to find roots", - default=False, cmdline="--asmgcroot", - requires=[("translation.gctransformer", "framework")]), + ChoiceOption("gcrootfinder", "Strategy for finding GC Roots", + ["ref", "boehm", "shadowstack", "stackless", "llvmgc", + "asmgcc"], "ref", + cmdline="--gcrootfinder", + requires={ + "ref": [("translation.gc", "ref")], + "boehm": [("translation.gc", "boehm")], + "shadowstack": [("translation.gctransformer", "framework")], + "stackless": [("translation.gctransformer", "framework"), + ("translation.stackless", True)], + "llvmgc": [("translation.gctransformer", "framework"), + ("translation.backend", "llvm")], + "asmgcc": [("translation.gctransformer", "framework"), + ("translation.backend", "c")], + }, + suggests={ + "shadowstack": [("translation.gc", "generation")], + "stackless": [("translation.gc", "generation")], + "llvmgc": [("translation.gc", "generation")], + "asmgcc": [("translation.gc", "generation")], + }), BoolOption("thread", "enable use of threading primitives", default=False, cmdline="--thread", requires=[("translation.gc", "boehm")]), Added: pypy/branch/asmgcroot/pypy/doc/config/translation.gcrootfinder.txt ============================================================================== --- (empty file) +++ pypy/branch/asmgcroot/pypy/doc/config/translation.gcrootfinder.txt Thu Jan 24 19:34:28 2008 @@ -0,0 +1,13 @@ +Choose method how to find roots in the GC. Boehm and refcounting have their own +methods, this is mostly only interesting for framework GCs. For those you have +a choice of various alternatives: + + - use a shadow stack (XXX link to paper), e.g. explicitely maintaining a stack + of roots + + - use stackless to find roots by unwinding the stack + + - use GCC and i386 specific assembler hackery to find the roots on the stack. + This is fastest but platform specific. + + - Use LLVM's GC facilities to find the roots. Modified: pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/gcc/test/test_asmgcroot.py Thu Jan 24 19:34:28 2008 @@ -24,7 +24,7 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy - config.translation.asmgcroot = True + config.translation.gcrootfinder = "asmgcc" t = TranslationContext(config=config) self.t = t a = t.buildannotator() Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/genc.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/genc.py Thu Jan 24 19:34:28 2008 @@ -41,9 +41,9 @@ gcpolicyclass = self.get_gcpolicyclass() - if self.config.translation.asmgcroot: + if self.config.translation.gcrootfinder == "asmgcc": if not self.standalone: - raise NotImplementedError("--asmgcroot requires standalone") + raise NotImplementedError("--gcrootfinder=asmgcc requires standalone") if self.config.translation.stackless: if not self.standalone: @@ -95,11 +95,11 @@ def get_gcpolicyclass(self): if self.gcpolicy is None: name = self.config.translation.gctransformer - if self.config.translation.stacklessgc: + if self.config.translation.gcrootfinder == "stackless": name = "%s+stacklessgc" % (name,) - if self.config.translation.llvmgcroot: + elif self.config.translation.gcrootfinder == "llvmgc": name = "%s+llvmgcroot" % (name,) - if self.config.translation.asmgcroot: + elif self.config.translation.gcrootfinder == "asmgcc": name = "%s+asmgcroot" % (name,) return gc.name_to_gcpolicy[name] return self.gcpolicy @@ -284,7 +284,7 @@ assert self.c_source_filename assert not self._compiled compiler = self.getccompiler() - if self.config.translation.asmgcroot: + if self.config.translation.gcrootfinder == "asmgcc": # as we are gcc-only anyway, let's just use the Makefile. cmdline = "make -C '%s'" % (self.targetdir,) err = os.system(cmdline) @@ -327,7 +327,7 @@ compiler.compile_extra.append(self.config.translation.compilerflags) if self.config.translation.linkerflags: compiler.link_extra.append(self.config.translation.linkerflags) - assert not self.config.translation.llvmgcroot + assert self.config.translation.gcrootfinder != "llvmgc" cfiles = [] ofiles = [] for fn in compiler.cfilenames: @@ -338,7 +338,7 @@ assert fn.dirpath().dirpath() == udir name = '../' + fn.relto(udir) cfiles.append(name) - if self.config.translation.asmgcroot: + if self.config.translation.gcrootfinder == "asmgcc": ofiles.append(name[:-2] + '.s') else: ofiles.append(name[:-2] + '.o') @@ -359,13 +359,13 @@ print >> f write_list(cfiles, 'SOURCES =') print >> f - if self.config.translation.asmgcroot: + if self.config.translation.gcrootfinder == "asmgcc": write_list(ofiles, 'ASMFILES =') print >> f, 'OBJECTS = $(ASMFILES) gcmaptable.s' else: write_list(ofiles, 'OBJECTS =') print >> f - if self.config.translation.asmgcroot: + if self.config.translation.gcrootfinder == "asmgcc": print >> f, 'TRACKGCROOT="%s"' % (os.path.join(autopath.this_dir, 'gcc', 'trackgcroot.py'),) print >> f Modified: pypy/branch/asmgcroot/pypy/translator/llvm/codewriter.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/llvm/codewriter.py (original) +++ pypy/branch/asmgcroot/pypy/translator/llvm/codewriter.py Thu Jan 24 19:34:28 2008 @@ -178,7 +178,7 @@ # Special support for llvm.gcroot def declare_gcroots(self, gcrootscount): - assert self.db.genllvm.config.translation.llvmgcroot + assert self.db.genllvm.config.translation.gcrootfinder == "llvmgc" for i in range(gcrootscount): self._indent("%%gcroot%d = alloca i8*" % i) for i in range(gcrootscount): From cfbolz at codespeak.net Thu Jan 24 19:50:35 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 24 Jan 2008 19:50:35 +0100 (CET) Subject: [pypy-svn] r50988 - in pypy/branch/asmgcroot/pypy: rpython/memory/test translator/c/test Message-ID: <20080124185035.C8A32168466@codespeak.net> Author: cfbolz Date: Thu Jan 24 19:50:34 2008 New Revision: 50988 Modified: pypy/branch/asmgcroot/pypy/rpython/memory/test/test_transformed_gc.py pypy/branch/asmgcroot/pypy/translator/c/test/test_boehm.py pypy/branch/asmgcroot/pypy/translator/c/test/test_stackless.py Log: missed some places Modified: pypy/branch/asmgcroot/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/asmgcroot/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/asmgcroot/pypy/rpython/memory/test/test_transformed_gc.py Thu Jan 24 19:50:34 2008 @@ -21,7 +21,8 @@ t = TranslationContext() # XXX XXX XXX mess t.config.translation.gc = gcname - t.config.translation.stacklessgc = stacklessgc + if stacklessgc: + t.config.translation.gcrootfinder = "stackless" t.config.set(**extraconfigopts) t.buildannotator().build_types(func, inputtypes) if specialize: Modified: pypy/branch/asmgcroot/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/test/test_boehm.py Thu Jan 24 19:50:34 2008 @@ -26,7 +26,8 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy - config.translation.stacklessgc = self.stacklessgc + if self.stacklessgc: + config.translation.gcrootfinder = "stackless" config.translation.simplifying = True t = TranslationContext(config=config) self.t = t Modified: pypy/branch/asmgcroot/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/branch/asmgcroot/pypy/translator/c/test/test_stackless.py (original) +++ pypy/branch/asmgcroot/pypy/translator/c/test/test_stackless.py Thu Jan 24 19:50:34 2008 @@ -33,7 +33,8 @@ config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy config.translation.stackless = True - config.translation.stacklessgc = self.stacklessgc + if self.stacklessgc: + config.translation.gcrootfinder = "stackless" t = TranslationContext(config=config) self.t = t t.buildannotator().build_types(entry_point, [s_list_of_strings]) From cfbolz at codespeak.net Thu Jan 24 19:57:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 24 Jan 2008 19:57:10 +0100 (CET) Subject: [pypy-svn] r50989 - in pypy/dist/pypy/objspace: . test Message-ID: <20080124185710.D10F316846C@codespeak.net> Author: cfbolz Date: Thu Jan 24 19:57:10 2008 New Revision: 50989 Modified: pypy/dist/pypy/objspace/reflective.py pypy/dist/pypy/objspace/test/test_reflective.py Log: make the interface more uniform: always pass in a space. Modified: pypy/dist/pypy/objspace/reflective.py ============================================================================== --- pypy/dist/pypy/objspace/reflective.py (original) +++ pypy/dist/pypy/objspace/reflective.py Thu Jan 24 19:57:10 2008 @@ -111,7 +111,6 @@ def proxymaker(space, opname, parentfn): if opname in DontWrapMe: return None - want_spaceaccess = True # changed below def user_hook(*args_w): w_rspace = get_reflective_space(space) if w_rspace is not None: @@ -122,12 +121,9 @@ if not e.match(space, space.w_AttributeError): raise else: - if want_spaceaccess: - spaceaccess = W_SpaceAccess(space, w_rspace) - w_spaceaccess = space.wrap(spaceaccess) - return space.call_function(w_f, w_spaceaccess, *args_w) - else: - return space.call_function(w_f, *args_w) + spaceaccess = W_SpaceAccess(space, w_rspace) + w_spaceaccess = space.wrap(spaceaccess) + return space.call_function(w_f, w_spaceaccess, *args_w) finally: reset_reflective_space(space, w_rspace) return None @@ -139,7 +135,6 @@ if w_newobj is not None: return w_newobj return w_obj - want_spaceaccess = False elif opname.startswith("new"): def fn(*args): w_obj = parentfn(*args) @@ -147,7 +142,6 @@ if w_newobj is not None: return w_newobj return w_obj - want_spaceaccess = False elif opname == "is_w": def fn(w_obj1, w_obj2): return space.is_true(space.is_(w_obj1, w_obj2)) @@ -157,7 +151,6 @@ if w_newobj is not None: w_obj = w_newobj return parentfn(w_obj) - want_spaceaccess = False elif opname == "call_args": def fn(w_callable, args): w_rspace = get_reflective_space(space) Modified: pypy/dist/pypy/objspace/test/test_reflective.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_reflective.py (original) +++ pypy/dist/pypy/objspace/test/test_reflective.py Thu Jan 24 19:57:10 2008 @@ -51,7 +51,7 @@ def test_newdict(self): from __pypy__ import set_reflectivespace class Space: - def newdict(self, d): + def newdict(self, space, d): d['surprise'] = 42 return d @@ -64,7 +64,7 @@ def test_newlist(self): from __pypy__ import set_reflectivespace class Space: - def newlist(self, l): + def newlist(self, space, l): l.append(len(l)) return l @@ -104,7 +104,7 @@ def test_typed_unwrap(self): from __pypy__ import set_reflectivespace class Space: - def int_w(self, i): + def int_w(self, space, i): if isinstance(i, basestring): return int(i) return i @@ -240,3 +240,31 @@ def f(x, **kwds): return x + kwds['y'] * 2 f(y=2)(3) == 7 + + def test_logicspace(self): + from __pypy__ import set_reflectivespace + NotBound = object() + class Var(object): + def __init__(self): + self.boundto = NotBound + def bind(var, obj): + XXX # never called? :-) + forcing_args = { + 'setattr': 2, + 'setitem': 2, + 'get': 2, + } + class UnboundVariable(Exception): + pass + class Space(object): + def convert(self, obj): + if isinstance(obj, Var): + if obj.boundto is not NotBound: + return obj + raise UnboundVariable + def __getattr__(self, name): + if name.startswith("new"): + raise AttributeError + def f(self, space, *args): + pass + From fijal at codespeak.net Thu Jan 24 20:54:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 20:54:43 +0100 (CET) Subject: [pypy-svn] r50992 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080124195443.30BF5168449@codespeak.net> Author: fijal Date: Thu Jan 24 20:54:42 2008 New Revision: 50992 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: Map UniChar to unsigned int (always) Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Thu Jan 24 20:54:42 2008 @@ -41,7 +41,7 @@ rffi.LONGLONG: ctypes.c_longlong, rffi.ULONGLONG: ctypes.c_ulonglong, rffi.SIZE_T: ctypes.c_size_t, - lltype.UniChar: ctypes.c_ushort, + lltype.UniChar: ctypes.c_uint, }) def build_ctypes_struct(S, delayed_builders, max_n=None): From fijal at codespeak.net Thu Jan 24 20:57:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 20:57:08 +0100 (CET) Subject: [pypy-svn] r50993 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080124195708.70C28168449@codespeak.net> Author: fijal Date: Thu Jan 24 20:57:08 2008 New Revision: 50993 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: Map unicode to 4 byte. Obscure, platform dependant test. Will at least explode when things will not fit. Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Thu Jan 24 20:57:08 2008 @@ -30,7 +30,7 @@ 'b' : ffi_type_schar, 'B' : ffi_type_uchar, 'h' : ffi_type_sshort, - 'u' : ffi_type_ushort, # XXX alias for wide-character + 'u' : ffi_type_uint, # XXX think deeper how to map it properly 'H' : ffi_type_ushort, 'i' : ffi_type_sint, 'I' : ffi_type_uint, Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Thu Jan 24 20:57:08 2008 @@ -500,9 +500,17 @@ def test_wide_char(self): import _rawffi A = _rawffi.Array('u') - a = A(1) + a = A(3) a[0] = u'x' + a[1] = u'y' + a[2] = u'z' assert a[0] == u'x' + b = _rawffi.Array('c').fromaddress(a.buffer, 38) + assert b[0] == 'x' + assert b[1] == '\x00' + assert b[2] == '\x00' + assert b[3] == '\x00' + assert b[4] == 'y' a.free() def test_truncate(self): From fijal at codespeak.net Thu Jan 24 22:01:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 22:01:37 +0100 (CET) Subject: [pypy-svn] r50997 - pypy/dist/pypy/module/marshal Message-ID: <20080124210137.9E030168436@codespeak.net> Author: fijal Date: Thu Jan 24 22:01:37 2008 New Revision: 50997 Modified: pypy/dist/pypy/module/marshal/interp_marshal.py Log: Update comment Modified: pypy/dist/pypy/module/marshal/interp_marshal.py ============================================================================== --- pypy/dist/pypy/module/marshal/interp_marshal.py (original) +++ pypy/dist/pypy/module/marshal/interp_marshal.py Thu Jan 24 22:01:37 2008 @@ -10,8 +10,7 @@ # already implemented, but for compatibility, # we default to version 1. Version 2 can be # tested, anyway, by using the optional parameter. -# XXX auto-configure this by inspecting the -# Python version we emulate. How to do this? +# XXX make it 2 when used with --pyversion=2.5 translation Py_MARSHAL_VERSION = 1 def dump(space, w_data, w_f, w_version=Py_MARSHAL_VERSION): From fijal at codespeak.net Thu Jan 24 22:02:14 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 24 Jan 2008 22:02:14 +0100 (CET) Subject: [pypy-svn] r50998 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080124210214.E7D07168436@codespeak.net> Author: fijal Date: Thu Jan 24 22:02:14 2008 New Revision: 50998 Modified: pypy/dist/pypy/lib/_ctypes/__init__.py pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/_ctypes/builtin.py pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Some support for w_char (setencoding does nothing for example) Modified: pypy/dist/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/__init__.py (original) +++ pypy/dist/pypy/lib/_ctypes/__init__.py Thu Jan 24 22:02:14 2008 @@ -7,7 +7,8 @@ from _ctypes.dll import dlopen from _ctypes.structure import Structure from _ctypes.array import Array -from _ctypes.builtin import _memmove_addr, _string_at_addr, _memset_addr +from _ctypes.builtin import _memmove_addr, _string_at_addr, _memset_addr,\ + set_conversion_mode, _wstring_at_addr from _ctypes.union import Union __version__ = '1.0.2' Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Thu Jan 24 22:02:14 2008 @@ -3,13 +3,22 @@ from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof +def _create_unicode(buffer, maxlength): + res = [] + for i in range(maxlength): + if buffer[i] == '\x00': + break + res.append(buffer[i]) + return u''.join(res) + class ArrayMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_type_' in typedict: ffiarray = _rawffi.Array(typedict['_type_']._ffishape) res._ffiarray = ffiarray - if getattr(typedict['_type_'], '_type_', None) == 'c': + subletter = getattr(typedict['_type_'], '_type_', None) + if subletter == 'c': def getvalue(self): return _rawffi.charp2string(self._buffer.buffer, self._length_) @@ -30,6 +39,21 @@ for i in range(len(buffer)): self[i] = buffer[i] res.raw = property(getraw, setraw) + elif subletter == 'u': + def getvalue(self): + # rawffi support anyone? + return _create_unicode(self._buffer, self._length_) + + def setvalue(self, val): + # we don't want to have buffers here + if len(val) > self._length_: + raise ValueError("%r too long" % (val,)) + for i in range(len(val)): + self[i] = val[i] + if len(val) < self._length_: + self[len(val)] = '\x00' + res.value = property(getvalue, setvalue) + if '_length_' in typedict: res._ffishape = ffiarray.gettypecode(typedict['_length_']) else: @@ -47,11 +71,14 @@ def from_param(self, value): # check for iterable - if hasattr(value, '__iter__'): + try: + iter(value) + except ValueError: + return _CDataMeta.from_param(self, value) + else: if len(value) > self._length_: raise ValueError("%s too long" % (value,)) return self(*value) - return _CDataMeta.from_param(self, value) def array_get_slice_params(self, index): if index.step is not None: @@ -68,8 +95,11 @@ def array_slice_getitem(self, index): start, stop = self._get_slice_params(index) l = [self[i] for i in range(start, stop)] - if getattr(self._type_, '_type_', None) == 'c': + letter = getattr(self._type_, '_type_', None) + if letter == 'c': return "".join(l) + if letter == 'u': + return u"".join(l) return l class Array(_CData): Modified: pypy/dist/pypy/lib/_ctypes/builtin.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/builtin.py (original) +++ pypy/dist/pypy/lib/_ctypes/builtin.py Thu Jan 24 22:02:14 2008 @@ -10,3 +10,19 @@ obj = ctypes.c_char_p._CData_input(addr)[0] return _rawffi.charp2rawstring(obj, lgt) +def set_conversion_mode(one, two): + pass + +def _wstring_at_addr(addr, lgt): + import ctypes + obj = ctypes.c_wchar_p._CData_input(addr)[0] + # XXX purely applevel + if lgt == -1: + lgt = sys.maxint + a = _rawffi.Array('u').fromaddress(obj, lgt) + res = [] + for i in xrange(lgt): + if lgt == sys.maxint and a[i] == '\x00': + break + res.append(a[i]) + return u''.join(res) Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Thu Jan 24 22:02:14 2008 @@ -10,6 +10,7 @@ TP_TO_DEFAULT = { 'c': 0, + 'u': 0, 'b': 0, 'B': 0, 'h': 0, @@ -26,6 +27,7 @@ # not part of struct 'O': NULL, 'z': None, + 'Z': None, } DEFAULT_VALUE = object() @@ -83,7 +85,7 @@ self._buffer[0] = value result.value = property(_getvalue, _setvalue) - if tp == 'z': + if tp in 'zZ': from _ctypes import Array, _Pointer # c_char_p def from_param(self, value): @@ -95,9 +97,8 @@ type(value)._type_ in 'zP': return value if isinstance(value, (Array, _Pointer)): - from ctypes import c_char, c_byte - if type(value)._type_ == c_char or \ - type(value)._type_ == c_byte: + from ctypes import c_char, c_byte, c_wchar + if type(value)._type_ in [c_char, c_byte, c_wchar]: return value return SimpleType.from_param(self, value) result.from_param = classmethod(from_param) @@ -113,9 +114,8 @@ type(value)._type_ in 'zP': return value if isinstance(value, Array): - from ctypes import c_char, c_byte - if type(value)._type_ == c_char or \ - type(value)._type_ == c_byte: + from ctypes import c_char, c_byte, c_wchar + if type(value)._type_ in [c_char, c_byte, c_wchar]: return value if isinstance(value, _Pointer): return self.from_address(value._buffer.buffer) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Thu Jan 24 22:02:14 2008 @@ -265,6 +265,7 @@ assert p.age == 5 def test_structures_with_wchar(self): + py.test.skip("Inlined array") try: c_wchar except NameError: From fijal at codespeak.net Fri Jan 25 01:22:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 01:22:56 +0100 (CET) Subject: [pypy-svn] r51003 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080125002256.E06B3168462@codespeak.net> Author: fijal Date: Fri Jan 25 01:22:55 2008 New Revision: 51003 Modified: pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py Log: Make this test run on top of cpython as well Modified: pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py Fri Jan 25 01:22:55 2008 @@ -1,15 +1,20 @@ from ctypes import * from binascii import hexlify import re -import _rawffi +import py def dump(obj): # helper function to dump memory contents in hex, with a hyphen # between the bytes. # cast it to the raw buffer - size = sizeof(obj) - a = _rawffi.Array('c').fromaddress(obj._buffer.buffer, size) - h = hexlify([a[i] for i in range(len(a))]) + try: + import _rawffi + except ImportError: + h = hexlify(buffer(obj)) + else: + size = sizeof(obj) + a = _rawffi.Array('c').fromaddress(obj._buffer.buffer, size) + h = hexlify([a[i] for i in range(len(a))]) return re.sub(r"(..)", r"\1-", h)[:-1] class Value(Structure): From fijal at codespeak.net Fri Jan 25 01:24:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 01:24:09 +0100 (CET) Subject: [pypy-svn] r51004 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080125002409.C2D3F168462@codespeak.net> Author: fijal Date: Fri Jan 25 01:24:09 2008 New Revision: 51004 Modified: pypy/dist/pypy/lib/_ctypes/function.py pypy/dist/pypy/lib/app_test/ctypes/test_functions.py Log: Another patological case, when there are some arguments for function specified, but not enough Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Fri Jan 25 01:24:09 2008 @@ -67,6 +67,13 @@ argtypes = self._argtypes_ if argtypes is None: argtypes = self._guess_argtypes(args) + else: + dif = len(args) - len(argtypes) + if dif < 0: + raise TypeError("Not enough arguments") + if dif > 0: + cut = len(args) - dif + argtypes = argtypes[:] + self._guess_argtypes(args[cut:]) restype = self._restype_ funcptr = self._getfuncptr(argtypes, restype) resarray = funcptr(*self._wrap_args(argtypes, args)) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_functions.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_functions.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_functions.py Fri Jan 25 01:24:09 2008 @@ -388,6 +388,13 @@ assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == ( (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + def test_call_some_args(self): + f = dll.my_strchr + f.argtypes = [c_char_p] + f.restype = c_char_p + result = f("abcd", ord("b")) + assert result == "bcd" + def test_sf1651235(self): py.test.skip("???") # see http://www.python.org/sf/1651235 From fijal at codespeak.net Fri Jan 25 01:38:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 01:38:58 +0100 (CET) Subject: [pypy-svn] r51005 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080125003858.B3ABF168462@codespeak.net> Author: fijal Date: Fri Jan 25 01:38:56 2008 New Revision: 51005 Modified: pypy/dist/pypy/lib/_ctypes/primitive.py Log: Try to share some code Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Fri Jan 25 01:38:56 2008 @@ -32,6 +32,17 @@ DEFAULT_VALUE = object() +def generic_xxx_p_from_param(self, value): + from _ctypes import Array, _Pointer + if value is None: + return self(None) + if isinstance(value, basestring): + return self(value) + if isinstance(value, _SimpleCData) and \ + type(value)._type_ in 'zP': + return value + return None # eventually raise + class SimpleType(_CDataMeta): def __new__(self, name, bases, dct): tp = dct['_type_'] @@ -89,13 +100,9 @@ from _ctypes import Array, _Pointer # c_char_p def from_param(self, value): - if value is None: - return self(None) - if isinstance(value, basestring): - return self(value) - if isinstance(value, _SimpleCData) and \ - type(value)._type_ in 'zP': - return value + res = generic_xxx_p_from_param(self, value) + if res is not None: + return res if isinstance(value, (Array, _Pointer)): from ctypes import c_char, c_byte, c_wchar if type(value)._type_ in [c_char, c_byte, c_wchar]: @@ -106,13 +113,9 @@ from _ctypes import Array, _Pointer # c_void_p def from_param(self, value): - if value is None: - return self(None) - if isinstance(value, basestring): - return self(value) - if isinstance(value, _SimpleCData) and \ - type(value)._type_ in 'zP': - return value + res = generic_xxx_p_from_param(self, value) + if res is not None: + return res if isinstance(value, Array): from ctypes import c_char, c_byte, c_wchar if type(value)._type_ in [c_char, c_byte, c_wchar]: From fijal at codespeak.net Fri Jan 25 01:39:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 01:39:18 +0100 (CET) Subject: [pypy-svn] r51006 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080125003918.1B908168462@codespeak.net> Author: fijal Date: Fri Jan 25 01:39:18 2008 New Revision: 51006 Modified: pypy/dist/pypy/lib/_ctypes/structure.py pypy/dist/pypy/lib/_ctypes/union.py Log: Late binding of Union _fields_ (not too much tests for that, need to write some) Modified: pypy/dist/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/structure.py (original) +++ pypy/dist/pypy/lib/_ctypes/structure.py Fri Jan 25 01:39:18 2008 @@ -34,7 +34,7 @@ if self in [v for k, v in value]: raise AttributeError("Structure or union cannot contain itself") self._names, rawfields, self._fieldtypes = names_and_fields( - value, self.__bases__[0], self._is_union, + value, self.__bases__[0], False, self.__dict__.get('_anonymous_', None)) self._ffistruct = _rawffi.Structure(rawfields) _CDataMeta.__setattr__(self, '_fields_', value) @@ -70,6 +70,7 @@ subvalue = value._fieldtypes[subname].ctype fields[subname] = Field(subname, relpos, ctypes.sizeof(subvalue), subvalue) + # XXX we never set rawfields here, let's wait for a test else: resnames.append(name) names = resnames @@ -88,8 +89,6 @@ self.size) class StructureMeta(_CDataMeta): - _is_union = False - def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: Modified: pypy/dist/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/union.py (original) +++ pypy/dist/pypy/lib/_ctypes/union.py Fri Jan 25 01:39:18 2008 @@ -7,8 +7,6 @@ import inspect class UnionMeta(_CDataMeta): - _is_union = True - def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) if '_fields_' in typedict: @@ -22,11 +20,13 @@ res._ffiarrays = {} for name, field in res._fieldtypes.iteritems(): res._ffiarrays[name] = _rawffi.Array(field.ctype._ffishape) - def __init__(self): # don't allow arguments by now - # malloc size - size = self.__class__._sizeofinstances() - self.__dict__['_buffer'] = _rawffi.Array('c')(size) - res.__init__ = __init__ + def __init__(self): # don't allow arguments by now + if not hasattr(self, '_ffiarrays'): + raise TypeError("Cannot instantiate union, has no type") + # malloc size + size = self.__class__._sizeofinstances() + self.__dict__['_buffer'] = _rawffi.Array('c')(size) + res.__init__ = __init__ return res def _sizeofinstances(self): @@ -42,9 +42,26 @@ self._fieldtypes.values()] + [1]) return self._alignment_ - __setattr__ = struct_setattr __getattr__ = struct_getattr + def __setattr__(self, name, value): + if name == '_fields_': + if self.__dict__.get('_fields_', None): + raise AttributeError("_fields_ is final") + if self in [v for k, v in value]: + raise AttributeError("Union cannot contain itself") + self._names, rawfields, self._fieldtypes = names_and_fields( + value, self.__bases__[0], True, + self.__dict__.get('_anonymous_', None)) + self._ffiarrays = {} + for name, field in self._fieldtypes.iteritems(): + self._ffiarrays[name] = _rawffi.Array(field.ctype._ffishape) + _CDataMeta.__setattr__(self, '_fields_', value) + self._ffishape = (self._sizeofinstances(), + self._alignmentofinstances()) + return + _CDataMeta.__setattr__(self, name, value) + class Union(_CData): __metaclass__ = UnionMeta _ffiletter = 'P' From fijal at codespeak.net Fri Jan 25 01:43:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 01:43:10 +0100 (CET) Subject: [pypy-svn] r51007 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080125004310.9AB1B168462@codespeak.net> Author: fijal Date: Fri Jan 25 01:43:10 2008 New Revision: 51007 Modified: pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/app_test/ctypes/test_extra.py Log: A test and a fix. Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Fri Jan 25 01:43:10 2008 @@ -117,9 +117,7 @@ if res is not None: return res if isinstance(value, Array): - from ctypes import c_char, c_byte, c_wchar - if type(value)._type_ in [c_char, c_byte, c_wchar]: - return value + return value if isinstance(value, _Pointer): return self.from_address(value._buffer.buffer) return SimpleType.from_param(self, value) Modified: pypy/dist/pypy/lib/app_test/ctypes/test_extra.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_extra.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_extra.py Fri Jan 25 01:43:10 2008 @@ -222,3 +222,7 @@ # T.argtypes and T.restype don't work, must use a dummy instance assert list(T().argtypes) == [c_ubyte] assert T().restype == c_int + +def test_from_param(): + # other working cases of from_param + assert isinstance(c_void_p.from_param((c_int * 4)()), c_int*4) From fijal at codespeak.net Fri Jan 25 01:47:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 01:47:30 +0100 (CET) Subject: [pypy-svn] r51008 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080125004730.8FC4C168462@codespeak.net> Author: fijal Date: Fri Jan 25 01:47:29 2008 New Revision: 51008 Modified: pypy/dist/pypy/lib/_ctypes/function.py Log: Small tweak Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Fri Jan 25 01:47:29 2008 @@ -100,10 +100,10 @@ res.append(c_void_p) elif arg == 0: res.append(c_void_p) - elif isinstance(arg, int): + elif isinstance(arg, (int, long)): res.append(c_int) else: - raise TypeError("Dont know how to handle %s" % (arg,)) + raise TypeError("Don't know how to handle %s" % (arg,)) return res def _wrap_args(self, argtypes, args): From pypy-svn at codespeak.net Fri Jan 25 08:25:09 2008 From: pypy-svn at codespeak.net (pypy-svn at codespeak.net) Date: Fri, 25 Jan 2008 08:25:09 +0100 (CET) Subject: [pypy-svn] January 77% OFF Message-ID: <20080125052502.80167.qmail@VDSL-130-13-135-245.PHNX.QWEST.NET> An HTML attachment was scrubbed... URL: From fijal at codespeak.net Fri Jan 25 10:31:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 10:31:54 +0100 (CET) Subject: [pypy-svn] r51011 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080125093154.6237416844D@codespeak.net> Author: fijal Date: Fri Jan 25 10:31:53 2008 New Revision: 51011 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Log: Kill this hack. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Fri Jan 25 10:31:53 2008 @@ -1773,9 +1773,6 @@ assert oddint & 1, "only odd integers can be cast back to ptr" return _ptr(PTRTYPE, oddint, solid=True) -def cast_float_to_int(val): - return struct.unpack('i', struct.pack('d', val))[0] - def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): if not isinstance(GCSTRUCT, RttiStruct): raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Fri Jan 25 10:31:53 2008 @@ -696,9 +696,6 @@ assert cast_ptr_to_int(t) == 21 assert s == cast_pointer(Ptr(S), t) -def test_cast_float(): - assert cast_float_to_int(2.3) == 0x40133333 - def test_str_of_dead_ptr(): S = Struct('S', ('x', Signed)) T = GcStruct('T', ('s', S)) From fijal at codespeak.net Fri Jan 25 11:25:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 11:25:13 +0100 (CET) Subject: [pypy-svn] r51016 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080125102513.1F2D9168461@codespeak.net> Author: fijal Date: Fri Jan 25 11:25:12 2008 New Revision: 51016 Modified: pypy/dist/pypy/jit/codegen/i386/ri386.py Log: Add floating registers and MODRM64 (feel free to remove it if needed) 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 Fri Jan 25 11:25:12 2008 @@ -18,12 +18,30 @@ else: raise ValueError +class FLOATREG(OPERAND): + width = 4 + + def __repr__(self): + return '' % self.num + + def assembler(self): + raise TypeError("Float registers should not appear in assembler") + +class ST0(FLOATREG): num=0 +class ST1(FLOATREG): num=1 +class ST2(FLOATREG): num=2 +class ST3(FLOATREG): num=3 +class ST4(FLOATREG): num=4 +class ST5(FLOATREG): num=5 +class ST6(FLOATREG): num=6 +class ST7(FLOATREG): num=7 + class REG8(OPERAND): width = 1 def __repr__(self): return '<%s>' % self.__class__.__name__.lower() def assembler(self): - return '%' + self.__class__.__name__.lower() + return '%' + self.__class__.__name__.lower() class EAX(REG): op=0 class ECX(REG): op=1 @@ -160,6 +178,9 @@ else: return rm == ECX.op +class MODRM64(MODRM): + width = 8 + # XXX some logic that it cannot be register class MODRM8(MODRM): width = 1 From fijal at codespeak.net Fri Jan 25 11:25:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 11:25:28 +0100 (CET) Subject: [pypy-svn] r51017 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080125102528.7D545168461@codespeak.net> Author: fijal Date: Fri Jan 25 11:25:27 2008 New Revision: 51017 Modified: pypy/dist/pypy/jit/codegen/i386/ri386setup.py Log: update float instructions 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 Fri Jan 25 11:25:27 2008 @@ -434,11 +434,16 @@ BREAKPOINT.as_alias = "INT3" # ------------------------- floating point instructions ------------------ + FLD = Instruction() -FLD.mode1(MODRM, ['\xDD', modrm(1)]) +FLD.mode1(MODRM64, ['\xDD', modrm(1)]) FADD = Instruction() -FADD.mode1(MODRM, ['\xDC', modrm(1)]) +#FADD.mode1(MODRM64, ['\xDC', modrm(1)]) +FADD.mode0(['\xDE\xC1']) + +#FISTP = Instruction() +#FISTP.mode1(MODRM64, ['\xDF', modrm(1)]) # ------------------------- end of floating point ------------------------ From fijal at codespeak.net Fri Jan 25 11:25:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 11:25:58 +0100 (CET) Subject: [pypy-svn] r51018 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080125102558.CB92A168461@codespeak.net> Author: fijal Date: Fri Jan 25 11:25:58 2008 New Revision: 51018 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: Fix one test. Second one still fails, no idea why 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 Fri Jan 25 11:25:58 2008 @@ -34,6 +34,7 @@ i386.REG: 4, i386.MODRM: 4, + i386.MODRM64: 8, i386.IMM32: 4, i386.REG8: 1, i386.MODRM8: 1, @@ -84,6 +85,9 @@ def modrm_tests(): return i386.registers + [pick1(i386.memSIB) for i in range(COUNT2)] +def modrm64_tests(): + return [pick1(i386.memSIB) for i in range(COUNT2)] + def modrm8_tests(): return i386.registers8 + [pick1(i386.memSIB8) for i in range(COUNT2)] @@ -108,6 +112,7 @@ i386.REG: reg_tests, i386.MODRM: modrm_tests, + i386.MODRM64: modrm64_tests, i386.IMM32: imm32_tests, i386.REG8: reg8_tests, i386.MODRM8: modrm8_tests, @@ -282,8 +287,8 @@ #print name if name in ('CMOVPE', 'CMOVPO'): py.test.skip("why doesn't 'as' know about CMOVPE/CMOVPO?") - if name in ('FADD', 'FLD'): - py.test.skip("XXX TEST ME: " + name) + if name == 'FLD': + py.test.skip("XXX") complete_test(name, insn) items = all_instructions.items() From cfbolz at codespeak.net Fri Jan 25 11:35:01 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 25 Jan 2008 11:35:01 +0100 (CET) Subject: [pypy-svn] r51019 - pypy/dist/pypy/rlib Message-ID: <20080125103501.64728168461@codespeak.net> Author: cfbolz Date: Fri Jan 25 11:35:01 2008 New Revision: 51019 Modified: pypy/dist/pypy/rlib/libffi.py Log: set the buffers to NULL after having freed them from the __del__. Add a comment about why one of the buffer doesn't need to be freed. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Fri Jan 25 11:35:01 2008 @@ -209,8 +209,10 @@ def __del__(self): if self.ll_cif: lltype.free(self.ll_cif, flavor='raw') + self.ll_cif = lltype.nullptr(FFI_CIFP.TO) if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor='raw') + self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) USERDATA_P = lltype.Ptr(lltype.GcForwardReference()) CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP, USERDATA_P], @@ -242,6 +244,9 @@ AbstractFuncPtr.__del__(self) if self.ll_closure: lltype.free(self.ll_closure, flavor='raw') + self.ll_closure = lltype.nullptr(FFI_CLOSUREP.TO) + # note that ll_userdata is a GC object and therefore does not need to + # be explicitely freed class RawFuncPtr(AbstractFuncPtr): @@ -330,8 +335,10 @@ if self.ll_args[i]: lltype.free(self.ll_args[i], flavor='raw') lltype.free(self.ll_args, flavor='raw') + self.ll_args = lltype.nullptr(rffi.VOIDPP.TO) if self.ll_result: lltype.free(self.ll_result, flavor='raw') + self.ll_result = lltype.nullptr(rffi.VOIDP.TO) AbstractFuncPtr.__del__(self) class CDLL: @@ -344,8 +351,10 @@ def __del__(self): if self.lib: c_dlclose(self.lib) + self.lib = lltype.nullptr(rffi.CCHARP.TO) if self.ll_libname: lltype.free(self.ll_libname, flavor='raw') + self.ll_libname = lltype.nullptr(rffi.CCHARP.TO) def getpointer(self, name, argtypes, restype): # these arguments are already casted to proper ffi From fijal at codespeak.net Fri Jan 25 11:39:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 11:39:05 +0100 (CET) Subject: [pypy-svn] r51020 - in pypy/dist/pypy/jit/codegen/i386: . test Message-ID: <20080125103905.1BF86168461@codespeak.net> Author: fijal Date: Fri Jan 25 11:39:03 2008 New Revision: 51020 Modified: pypy/dist/pypy/jit/codegen/i386/ri386.py pypy/dist/pypy/jit/codegen/i386/ri386setup.py pypy/dist/pypy/jit/codegen/i386/test/test_auto_encoding.py Log: * Adapt the test and fix few things. * Introduce memSIB64 which is the same as memSIB, but for 64 bit. 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 Fri Jan 25 11:39:03 2008 @@ -250,6 +250,9 @@ def memSIB(base, index, scaleshift, offset): return _SIBencode(MODRM, base, index, scaleshift, offset) +def memSIB64(base, index, scaleshift, offset): + return _SIBencode(MODRM64, base, index, scaleshift, offset) + def memregister8(register): assert register.width == 1 return MODRM8(0xC0 | register.op, '') 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 Fri Jan 25 11:39:03 2008 @@ -42,8 +42,9 @@ REL32: [(REL32, None)], - MODRM: [(MODRM, None)], - MODRM8: [(MODRM8, None)], + MODRM: [(MODRM, None)], + MODRM8: [(MODRM8, None)], + MODRM64: [(MODRM64, None)], MISSING: [(MISSING, None)], # missing operands } @@ -436,7 +437,7 @@ # ------------------------- floating point instructions ------------------ FLD = Instruction() -FLD.mode1(MODRM64, ['\xDD', modrm(1)]) +FLD.mode1(MODRM64, ['\xD9', modrm(1)]) FADD = Instruction() #FADD.mode1(MODRM64, ['\xDC', modrm(1)]) 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 Fri Jan 25 11:39:03 2008 @@ -86,7 +86,7 @@ return i386.registers + [pick1(i386.memSIB) for i in range(COUNT2)] def modrm64_tests(): - return [pick1(i386.memSIB) for i in range(COUNT2)] + return [pick1(i386.memSIB64) for i in range(COUNT2)] def modrm8_tests(): return i386.registers8 + [pick1(i386.memSIB8) for i in range(COUNT2)] @@ -287,8 +287,6 @@ #print name if name in ('CMOVPE', 'CMOVPO'): py.test.skip("why doesn't 'as' know about CMOVPE/CMOVPO?") - if name == 'FLD': - py.test.skip("XXX") complete_test(name, insn) items = all_instructions.items() From fijal at codespeak.net Fri Jan 25 12:41:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 12:41:11 +0100 (CET) Subject: [pypy-svn] r51021 - pypy/branch/jit-float-support Message-ID: <20080125114111.493DD168469@codespeak.net> Author: fijal Date: Fri Jan 25 12:41:09 2008 New Revision: 51021 Added: pypy/branch/jit-float-support/ - copied from r51020, pypy/dist/ Log: A branch to experiment with floats on the jit. From fijal at codespeak.net Fri Jan 25 12:46:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 12:46:09 +0100 (CET) Subject: [pypy-svn] r51022 - in pypy/dist/pypy/jit/hintannotator: . test Message-ID: <20080125114609.825BF168466@codespeak.net> Author: fijal Date: Fri Jan 25 12:46:08 2008 New Revision: 51022 Modified: pypy/dist/pypy/jit/hintannotator/model.py pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Log: Support to pass float_add through hintannotator Modified: pypy/dist/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/model.py (original) +++ pypy/dist/pypy/jit/hintannotator/model.py Fri Jan 25 12:46:08 2008 @@ -44,7 +44,7 @@ uint_gt uint_lt uint_le uint_ge uint_eq uint_ne getarrayitem setarrayitem getarraysubstruct - ptr_eq ptr_ne""".split() + ptr_eq ptr_ne float_add""".split() class HintError(Exception): pass 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 Jan 25 12:46:08 2008 @@ -99,6 +99,14 @@ assert len(hs.origins) == 3 assert hs.concretetype == lltype.Signed + def test_simple_float(self): + def ll_function(x, y): + return x + y + hs = self.hannotate(ll_function, [float, float]) + assert isinstance(hs, SomeLLAbstractConstant) + assert len(hs.origins) == 3 + assert hs.concretetype == lltype.Float + def test_join(self): def ll_function(cond, x,y): if cond: From fijal at codespeak.net Fri Jan 25 12:46:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 12:46:46 +0100 (CET) Subject: [pypy-svn] r51023 - in pypy/dist/pypy/jit/codegen: llgraph test Message-ID: <20080125114646.B3AA4168466@codespeak.net> Author: fijal Date: Fri Jan 25 12:46:46 2008 New Revision: 51023 Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Log: Tests for float_add + llgraph support 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 Jan 25 12:46:46 2008 @@ -43,6 +43,7 @@ gv_Void = gv_TYPE(lltype.Void) gv_Signed = gv_TYPE(lltype.Signed) +gv_Double = gv_TYPE(lltype.Float) gv_Bool = gv_TYPE(lltype.Bool) gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder) gv_flavor_gc = LLConst(llimpl.placeholder({'flavor': 'gc'})) Modified: pypy/dist/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/dist/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Fri Jan 25 12:46:46 2008 @@ -10,6 +10,7 @@ rtyper = None GENOP_POLICY = MixLevelAnnotatorPolicy(PseudoAnnhelper()) +FLOATFUNC = lltype.FuncType([lltype.Float], lltype.Float) FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) FUNC2 = lltype.FuncType([lltype.Signed]*2, lltype.Signed) FUNC3 = lltype.FuncType([lltype.Signed]*3, lltype.Signed) @@ -26,6 +27,19 @@ builder.end() return gv_add_one +def make_float_adder(rgenop, n): + # 'return x+n' + sigtoken = rgenop.sigToken(FLOATFUNC) + import pdb + pdb.set_trace() + builder, gv_add_one, [gv_x] = rgenop.newgraph(sigtoken, "float_adder") + builder.start_writing() + c2 = rgenop.genconst(n) + gv_result = builder.genop2("float_add", gv_x, c2) + builder.finish_and_return(sigtoken, gv_result) + builder.end() + return gv_add_one + def get_adder_runner(RGenOp): def runner(x, y): rgenop = RGenOp() @@ -36,6 +50,16 @@ return res return runner +def get_float_adder_runner(RGenOp): + def runner(x, y): + rgenop = RGenOp() + gv_add_x = make_float_adder(rgenop, x) + add_x = gv_add_x.revealconst(lltype.Ptr(FLOATFUNC)) + res = add_x(y) + keepalive_until_here(rgenop) + return res + return runner + def make_dummy(rgenop): # 'return x - (y - (x-1))' signed_kind = rgenop.kindToken(lltype.Signed) @@ -846,6 +870,10 @@ F1 = lltype.FuncType([lltype.Signed] * nb_args, lltype.Signed) return self.RGenOp.get_python_callable(lltype.Ptr(F1), gv) + def cast_float(self, gv, nb_args): + F1 = lltype.FuncType([lltype.Float] * nb_args, lltype.Float) + return self.RGenOp.get_python_callable(lltype.Ptr(F1), gv) + def directtesthelper(self, FUNCTYPE, func): # for machine code backends: build a ctypes function pointer # (with a real physical address) that will call back our 'func' @@ -890,11 +918,23 @@ res = fnptr(37) assert res == 42 + def test_float_adder(self): + rgenop = self.RGenOp() + gv_add_5 = make_float_adder(rgenop, 3.2) + fnptr = self.cast_float(gv_add_5, 1) + res = fnptr(1.2) + assert res == 4.4 + def test_adder_compile(self): fn = self.compile(get_adder_runner(self.RGenOp), [int, int]) res = fn(9080983, -9080941) assert res == 42 + def test_float_adder_compile(self): + fn = self.compile(get_float_adder_runner(self.RGenOp), [float, float]) + res = fn(1.2, 3.4) + assert res == 4.6 + def test_dummy_direct(self): rgenop = self.RGenOp() gv_dummyfn = make_dummy(rgenop) From fijal at codespeak.net Fri Jan 25 12:47:25 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 12:47:25 +0100 (CET) Subject: [pypy-svn] r51024 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080125114725.34C99168462@codespeak.net> Author: fijal Date: Fri Jan 25 12:47:24 2008 New Revision: 51024 Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py Log: Float constant specialization Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/rgenop.py Fri Jan 25 12:47:24 2008 @@ -18,15 +18,11 @@ # ____________________________________________________________ -class IntConst(GenConst): +class AbstractConst(GenConst): def __init__(self, value): self.value = value - @specialize.arg(1) - def revealconst(self, T): - return cast_int_to_whatever(T, self.value) - def __repr__(self): "NOT_RPYTHON" try: @@ -37,6 +33,16 @@ def repr(self): return "const=$%s" % (self.value,) +class IntConst(AbstractConst): + @specialize.arg(1) + def revealconst(self, T): + return cast_int_to_whatever(T, self.value) + +class FloatConst(AbstractConst): + @specialize.arg(1) + def revealconst(self, T): + return cast_float_to_whatever(T, self.value) + class AddrConst(GenConst): def __init__(self, addr): @@ -63,6 +69,15 @@ return lltype.cast_primitive(T, value) @specialize.arg(0) +def cast_float_to_whatever(T, value): + if T is lltype.Signed: + return lltype.cast_float_to_int(value) + elif T is lltype.Float: + return value + else: + raise NotImplementedError + + at specialize.arg(0) def cast_whatever_to_int(T, value): if isinstance(T, lltype.Ptr): return lltype.cast_ptr_to_int(value) @@ -653,6 +668,8 @@ T = lltype.typeOf(llvalue) if T is llmemory.Address: return AddrConst(llvalue) + elif T is lltype.Float: + return FloatConst(lltype.cast_primitive(lltype.Float, llvalue)) elif isinstance(T, lltype.Primitive): return IntConst(lltype.cast_primitive(lltype.Signed, llvalue)) elif isinstance(T, lltype.Ptr): From cfbolz at codespeak.net Fri Jan 25 13:27:15 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 25 Jan 2008 13:27:15 +0100 (CET) Subject: [pypy-svn] r51028 - pypy/dist/pypy/module/_rawffi Message-ID: <20080125122715.22B7C1684D3@codespeak.net> Author: cfbolz Date: Fri Jan 25 13:27:14 2008 New Revision: 51028 Modified: pypy/dist/pypy/module/_rawffi/callback.py Log: remove __del__ (which is never called anyway). Leave a comment, this is what the eventual free method should look like. Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Fri Jan 25 13:27:14 2008 @@ -53,8 +53,8 @@ callback, number) self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) - def __del__(self): - del self.global_counter.CallbackPtr_by_number[self.number] + #def free(self): + # del self.global_counter.CallbackPtr_by_number[self.number] def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result): return W_CallbackPtr(space, w_callable, w_args, w_result) From cfbolz at codespeak.net Fri Jan 25 14:38:16 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 25 Jan 2008 14:38:16 +0100 (CET) Subject: [pypy-svn] r51031 - in pypy/dist/pypy: module/_rawffi module/_rawffi/test rlib Message-ID: <20080125133816.EF643168461@codespeak.net> Author: cfbolz Date: Fri Jan 25 14:38:03 2008 New Revision: 51031 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py pypy/dist/pypy/rlib/libffi.py Log: add a way to read arbitrary data from a dll to _rawffi Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Fri Jan 25 14:38:03 2008 @@ -135,6 +135,14 @@ "No symbol %s found in library %s" % (name, self.name))) ptr.unwrap_spec = ['self', ObjSpace, str, W_Root, W_Root] + def getprimitive(self, space, letter, name): + from pypy.module._rawffi.array import get_array_cache + cache = get_array_cache(space) + w_array = cache.get_array_type(letter2tp(space, letter)) + address_as_uint = rffi.cast(lltype.Unsigned, self.cdll.getaddressindll(name)) + return w_array.fromaddress(space, address_as_uint, 1) + getprimitive.unwrap_spec = ['self', ObjSpace, str, str] + def descr_new_cdll(space, w_type, name): try: return space.wrap(W_CDLL(space, name)) @@ -146,6 +154,7 @@ 'CDLL', __new__ = interp2app(descr_new_cdll), ptr = interp2app(W_CDLL.ptr), + getprimitive= interp2app(W_CDLL.getprimitive), __doc__ = """ C Dynamically loaded library use CDLL(libname) to create a handle to a C library (the argument is processed the same way as dlopen processes it). On such a library you can call: Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Fri Jan 25 14:38:03 2008 @@ -54,6 +54,8 @@ } const char *static_str = "xxxxxx"; + const long static_int = 42; + const double static_double = 42.42; unsigned short add_shorts(short one, short two) { @@ -574,3 +576,12 @@ a[0] = -2 assert a[0] == maxptr - 1 a.free() + + def test_getprimitive(self): + import _rawffi + lib = _rawffi.CDLL(self.lib_name) + a = lib.getprimitive("l", "static_int") + assert a[0] == 42 + a = lib.getprimitive("d", "static_double") + assert a[0] == 42.42 + Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Fri Jan 25 14:38:03 2008 @@ -365,3 +365,6 @@ # these arguments are already casted to proper ffi # structures! return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name)) + + def getaddressindll(self, name): + return dlsym(self.lib, name) From fijal at codespeak.net Fri Jan 25 18:17:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 18:17:08 +0100 (CET) Subject: [pypy-svn] r51036 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080125171708.ABDDE1684F3@codespeak.net> Author: fijal Date: Fri Jan 25 18:17:08 2008 New Revision: 51036 Added: pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/basics.py Log: Support for in_dll Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Fri Jan 25 18:17:08 2008 @@ -43,6 +43,12 @@ def _is_pointer_like(self): return False + def in_dll(self, dll, name): + buffer = dll._handle.getprimitive(self._ffishape, name) + val = self.__new__(self) + val._buffer = buffer + return val + class _CData(object): """ The most basic object for all ctypes types """ Added: pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py Fri Jan 25 18:17:08 2008 @@ -0,0 +1,200 @@ +# A lot of failures in these tests on Mac OS X. +# Byte order related? + +from ctypes import * +import py + +def setup_module(mod): + import conftest + mod._ctypes_test = str(conftest.sofile) + # this means you cannot run tests directly without invoking this + mod.TestCFunctions._dll = CDLL(_ctypes_test) + +class TestCFunctions: + + def S(self): + return c_longlong.in_dll(self._dll, "last_tf_arg_s").value + def U(self): + return c_ulonglong.in_dll(self._dll, "last_tf_arg_u").value + + def test_byte(self): + self._dll.tf_b.restype = c_byte + self._dll.tf_b.argtypes = (c_byte,) + assert self._dll.tf_b(-126) == -42 + assert self.S() == -126 + + def test_byte_plus(self): + self._dll.tf_bb.restype = c_byte + self._dll.tf_bb.argtypes = (c_byte, c_byte) + assert self._dll.tf_bb(0, -126) == -42 + assert self.S() == -126 + + def test_ubyte(self): + self._dll.tf_B.restype = c_ubyte + self._dll.tf_B.argtypes = (c_ubyte,) + assert self._dll.tf_B(255) == 85 + assert self.U() == 255 + + def test_ubyte_plus(self): + self._dll.tf_bB.restype = c_ubyte + self._dll.tf_bB.argtypes = (c_byte, c_ubyte) + assert self._dll.tf_bB(0, 255) == 85 + assert self.U() == 255 + + def test_short(self): + self._dll.tf_h.restype = c_short + self._dll.tf_h.argtypes = (c_short,) + assert self._dll.tf_h(-32766) == -10922 + assert self.S() == -32766 + + def test_short_plus(self): + self._dll.tf_bh.restype = c_short + self._dll.tf_bh.argtypes = (c_byte, c_short) + assert self._dll.tf_bh(0, -32766) == -10922 + assert self.S() == -32766 + + def test_ushort(self): + self._dll.tf_H.restype = c_ushort + self._dll.tf_H.argtypes = (c_ushort,) + assert self._dll.tf_H(65535) == 21845 + assert self.U() == 65535 + + def test_ushort_plus(self): + self._dll.tf_bH.restype = c_ushort + self._dll.tf_bH.argtypes = (c_byte, c_ushort) + assert self._dll.tf_bH(0, 65535) == 21845 + assert self.U() == 65535 + + def test_int(self): + self._dll.tf_i.restype = c_int + self._dll.tf_i.argtypes = (c_int,) + assert self._dll.tf_i(-2147483646) == -715827882 + assert self.S() == -2147483646 + + def test_int_plus(self): + self._dll.tf_bi.restype = c_int + self._dll.tf_bi.argtypes = (c_byte, c_int) + assert self._dll.tf_bi(0, -2147483646) == -715827882 + assert self.S() == -2147483646 + + def test_uint(self): + self._dll.tf_I.restype = c_uint + self._dll.tf_I.argtypes = (c_uint,) + assert self._dll.tf_I(4294967295) == 1431655765 + assert self.U() == 4294967295 + + def test_uint_plus(self): + self._dll.tf_bI.restype = c_uint + self._dll.tf_bI.argtypes = (c_byte, c_uint) + assert self._dll.tf_bI(0, 4294967295) == 1431655765 + assert self.U() == 4294967295 + + def test_long(self): + self._dll.tf_l.restype = c_long + self._dll.tf_l.argtypes = (c_long,) + assert self._dll.tf_l(-2147483646) == -715827882 + assert self.S() == -2147483646 + + def test_long_plus(self): + self._dll.tf_bl.restype = c_long + self._dll.tf_bl.argtypes = (c_byte, c_long) + assert self._dll.tf_bl(0, -2147483646) == -715827882 + assert self.S() == -2147483646 + + def test_ulong(self): + self._dll.tf_L.restype = c_ulong + self._dll.tf_L.argtypes = (c_ulong,) + assert self._dll.tf_L(4294967295) == 1431655765 + assert self.U() == 4294967295 + + def test_ulong_plus(self): + self._dll.tf_bL.restype = c_ulong + self._dll.tf_bL.argtypes = (c_char, c_ulong) + assert self._dll.tf_bL(' ', 4294967295) == 1431655765 + assert self.U() == 4294967295 + + def test_longlong(self): + self._dll.tf_q.restype = c_longlong + self._dll.tf_q.argtypes = (c_longlong, ) + assert self._dll.tf_q(-9223372036854775806) == -3074457345618258602 + assert self.S() == -9223372036854775806 + + def test_longlong_plus(self): + self._dll.tf_bq.restype = c_longlong + self._dll.tf_bq.argtypes = (c_byte, c_longlong) + assert self._dll.tf_bq(0, -9223372036854775806) == -3074457345618258602 + assert self.S() == -9223372036854775806 + + def test_ulonglong(self): + self._dll.tf_Q.restype = c_ulonglong + self._dll.tf_Q.argtypes = (c_ulonglong, ) + assert self._dll.tf_Q(18446744073709551615) == 6148914691236517205 + assert self.U() == 18446744073709551615 + + def test_ulonglong_plus(self): + self._dll.tf_bQ.restype = c_ulonglong + self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong) + assert self._dll.tf_bQ(0, 18446744073709551615) == 6148914691236517205 + assert self.U() == 18446744073709551615 + + def test_float(self): + self._dll.tf_f.restype = c_float + self._dll.tf_f.argtypes = (c_float,) + assert self._dll.tf_f(-42.) == -14. + assert self.S() == -42 + + def test_float_plus(self): + self._dll.tf_bf.restype = c_float + self._dll.tf_bf.argtypes = (c_byte, c_float) + assert self._dll.tf_bf(0, -42.) == -14. + assert self.S() == -42 + + def test_double(self): + self._dll.tf_d.restype = c_double + self._dll.tf_d.argtypes = (c_double,) + assert self._dll.tf_d(42.) == 14. + assert self.S() == 42 + + def test_double_plus(self): + self._dll.tf_bd.restype = c_double + self._dll.tf_bd.argtypes = (c_byte, c_double) + assert self._dll.tf_bd(0, 42.) == 14. + assert self.S() == 42 + + def test_callwithresult(self): + py.test.skip("function as restype unsupported") + def process_result(result): + return result * 2 + self._dll.tf_i.restype = process_result + self._dll.tf_i.argtypes = (c_int,) + assert self._dll.tf_i(42) == 28 + assert self.S() == 42 + assert self._dll.tf_i(-42) == -28 + assert self.S() == -42 + + def test_void(self): + self._dll.tv_i.restype = None + self._dll.tv_i.argtypes = (c_int,) + assert self._dll.tv_i(42) == None + assert self.S() == 42 + assert self._dll.tv_i(-42) == None + assert self.S() == -42 + +# The following repeates the above tests with stdcall functions (where +# they are available) +try: + WinDLL +except NameError: + pass +else: + class stdcall_dll(WinDLL): + def __getattr__(self, name): + if name[:2] == '__' and name[-2:] == '__': + raise AttributeError, name + func = self._FuncPtr(("s_" + name, self)) + setattr(self, name, func) + return func + + class stdcallCFunctions(CFunctions): + _dll = stdcall_dll(_ctypes_test.__file__) + pass From fijal at codespeak.net Fri Jan 25 18:21:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 18:21:47 +0100 (CET) Subject: [pypy-svn] r51037 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080125172147.21FB61684F3@codespeak.net> Author: fijal Date: Fri Jan 25 18:21:46 2008 New Revision: 51037 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: Fix for in_dll and a test. Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Fri Jan 25 18:21:46 2008 @@ -139,7 +139,12 @@ from pypy.module._rawffi.array import get_array_cache cache = get_array_cache(space) w_array = cache.get_array_type(letter2tp(space, letter)) - address_as_uint = rffi.cast(lltype.Unsigned, self.cdll.getaddressindll(name)) + try: + address_as_uint = rffi.cast(lltype.Unsigned, + self.cdll.getaddressindll(name)) + except KeyError: + raise OperationError(space.w_ValueError, + space.wrap("Cannot find symbol %s" % (name,))) return w_array.fromaddress(space, address_as_uint, 1) getprimitive.unwrap_spec = ['self', ObjSpace, str, str] Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Fri Jan 25 18:21:46 2008 @@ -584,4 +584,6 @@ assert a[0] == 42 a = lib.getprimitive("d", "static_double") assert a[0] == 42.42 + raises(ValueError, lib.getprimitive, 'z', 'ddddddd') + raises(ValueError, lib.getprimitive, 'zzz', 'static_int') From fijal at codespeak.net Fri Jan 25 18:22:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 18:22:35 +0100 (CET) Subject: [pypy-svn] r51040 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080125172235.7D7941684F4@codespeak.net> Author: fijal Date: Fri Jan 25 18:22:35 2008 New Revision: 51040 Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Log: Unskip bogus test. Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py Fri Jan 25 18:22:35 2008 @@ -341,7 +341,6 @@ assert (cls, msg) == (TypeError, "abstract class") def test_methods(self): - py.test.skip("???") ## class X(Structure): ## _fields_ = [] From fijal at codespeak.net Fri Jan 25 18:49:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 18:49:11 +0100 (CET) Subject: [pypy-svn] r51042 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080125174911.5E9DB168443@codespeak.net> Author: fijal Date: Fri Jan 25 18:49:10 2008 New Revision: 51042 Added: pypy/dist/pypy/lib/app_test/ctypes/test_as_parameter.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/function.py Log: Some tests and a fix. Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Fri Jan 25 18:49:10 2008 @@ -92,6 +92,8 @@ from ctypes import c_char_p, c_void_p, c_int, Array, Structure res = [] for arg in args: + if hasattr(arg, '_as_parameter_'): + arg = arg._as_parameter_ if isinstance(arg, str): res.append(c_char_p) elif isinstance(arg, _CData): Added: pypy/dist/pypy/lib/app_test/ctypes/test_as_parameter.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_as_parameter.py Fri Jan 25 18:49:10 2008 @@ -0,0 +1,218 @@ +from ctypes import * +import py + +def setup_module(mod): + import conftest + _ctypes_test = str(conftest.sofile) + mod.dll = CDLL(_ctypes_test) + +try: + CALLBACK_FUNCTYPE = WINFUNCTYPE +except NameError: + # fake to enable this test on Linux + CALLBACK_FUNCTYPE = CFUNCTYPE + +class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] + +class BasicTestWrap: + def wrap(self, param): + return param + + def test_wchar_parm(self): + try: + c_wchar + except NameError: + return + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] + result = f(self.wrap(1), self.wrap(u"x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0)) + assert result == 139 + assert type(result), int + + def test_pointers(self): + f = dll._testfunc_p_p + f.restype = POINTER(c_int) + f.argtypes = [POINTER(c_int)] + + # This only works if the value c_int(42) passed to the + # function is still alive while the pointer (the result) is + # used. + + v = c_int(42) + + assert pointer(v).contents.value == 42 + result = f(self.wrap(pointer(v))) + assert type(result) == POINTER(c_int) + assert result.contents.value == 42 + + # This on works... + result = f(self.wrap(pointer(v))) + assert result.contents.value == v.value + + p = pointer(c_int(99)) + result = f(self.wrap(p)) + assert result.contents.value == 99 + + def test_shorts(self): + f = dll._testfunc_callback_i_if + + args = [] + expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] + + def callback(v): + args.append(v) + return v + + CallBack = CFUNCTYPE(c_int, c_int) + + cb = CallBack(callback) + f(self.wrap(2**18), self.wrap(cb)) + assert args == expected + + ################################################################ + + def test_callbacks(self): + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + def callback(value): + #print "called back with", value + return value + + cb = MyCallback(callback) + + result = f(self.wrap(-10), self.wrap(cb)) + assert result == -18 + + # test with prototype + f.argtypes = [c_int, MyCallback] + cb = MyCallback(callback) + + result = f(self.wrap(-10), self.wrap(cb)) + assert result == -18 + + result = f(self.wrap(-10), self.wrap(cb)) + assert result == -18 + + AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int) + + # check that the prototype works: we call f with wrong + # argument types + cb = AnotherCallback(callback) + raises(ArgumentError, f, self.wrap(-10), self.wrap(cb)) + + def test_callbacks_2(self): + # Can also use simple datatypes as argument type specifiers + # for the callback function. + # In this case the call receives an instance of that type + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + f.argtypes = [c_int, MyCallback] + + def callback(value): + #print "called back with", value + assert type(value) == int + return value + + cb = MyCallback(callback) + result = f(self.wrap(-10), self.wrap(cb)) + assert result == -18 + + def test_longlong_callbacks(self): + + f = dll._testfunc_callback_q_qf + f.restype = c_longlong + + MyCallback = CFUNCTYPE(c_longlong, c_longlong) + + f.argtypes = [c_longlong, MyCallback] + + def callback(value): + assert isinstance(value, (int, long)) + return value & 0x7FFFFFFF + + cb = MyCallback(callback) + + assert 13577625587 == int(f(self.wrap(1000000000000), self.wrap(cb))) + + def test_byval(self): + py.test.skip("Structure by value") + # without prototype + ptin = POINT(1, 2) + ptout = POINT() + # EXPORT int _testfunc_byval(point in, point *pout) + result = dll._testfunc_byval(ptin, byref(ptout)) + got = result, ptout.x, ptout.y + expected = 3, 1, 2 + assert got == expected + + # with prototype + ptin = POINT(101, 102) + ptout = POINT() + dll._testfunc_byval.argtypes = (POINT, POINTER(POINT)) + dll._testfunc_byval.restype = c_int + result = dll._testfunc_byval(self.wrap(ptin), byref(ptout)) + got = result, ptout.x, ptout.y + expected = 203, 101, 102 + assert got == expected + + def test_struct_return_2H(self): + py.test.skip("Structure by value") + class S2H(Structure): + _fields_ = [("x", c_short), + ("y", c_short)] + dll.ret_2h_func.restype = S2H + dll.ret_2h_func.argtypes = [S2H] + inp = S2H(99, 88) + s2h = dll.ret_2h_func(self.wrap(inp)) + assert (s2h.x, s2h.y) == (99*2, 88*3) + + def test_struct_return_8H(self): + py.test.skip("Structure by value") + class S8I(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int), + ("d", c_int), + ("e", c_int), + ("f", c_int), + ("g", c_int), + ("h", c_int)] + dll.ret_8i_func.restype = S8I + dll.ret_8i_func.argtypes = [S8I] + inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) + s8i = dll.ret_8i_func(self.wrap(inp)) + assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == ( + (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AsParamWrapper(object): + def __init__(self, param): + self._as_parameter_ = param + +class TestWrap(BasicTestWrap): + wrap = AsParamWrapper + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AsParamPropertyWrapper(object): + def __init__(self, param): + self._param = param + + def getParameter(self): + return self._param + _as_parameter_ = property(getParameter) + +class TestAsParam(BasicTestWrap): + wrap = AsParamPropertyWrapper + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + From fijal at codespeak.net Fri Jan 25 18:50:40 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 18:50:40 +0100 (CET) Subject: [pypy-svn] r51043 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080125175040.AE64E1684E7@codespeak.net> Author: fijal Date: Fri Jan 25 18:50:34 2008 New Revision: 51043 Added: pypy/dist/pypy/lib/app_test/ctypes/test_buffers.py (contents, props changed) Log: This test passes out of the box. Added: pypy/dist/pypy/lib/app_test/ctypes/test_buffers.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_buffers.py Fri Jan 25 18:50:34 2008 @@ -0,0 +1,51 @@ +from ctypes import * + +class TestStringBuffer: + + def test_buffer(self): + b = create_string_buffer(32) + assert len(b) == 32 + assert sizeof(b) == 32 * sizeof(c_char) + assert type(b[0]) is str + + b = create_string_buffer("abc") + assert len(b) == 4 # trailing nul char + assert sizeof(b) == 4 * sizeof(c_char) + assert type(b[0]) is str + assert b[0] == "a" + assert b[:] == "abc\0" + + def test_string_conversion(self): + b = create_string_buffer(u"abc") + assert len(b) == 4 # trailing nul char + assert sizeof(b) == 4 * sizeof(c_char) + assert type(b[0]) is str + assert b[0] == "a" + assert b[:] == "abc\0" + + try: + c_wchar + except NameError: + pass + else: + def test_unicode_buffer(self): + b = create_unicode_buffer(32) + assert len(b) == 32 + assert sizeof(b) == 32 * sizeof(c_wchar) + assert type(b[0]) is unicode + + b = create_unicode_buffer(u"abc") + assert len(b) == 4 # trailing nul char + assert sizeof(b) == 4 * sizeof(c_wchar) + assert type(b[0]) is unicode + assert b[0] == u"a" + assert b[:] == "abc\0" + + def test_unicode_conversion(self): + b = create_unicode_buffer("abc") + assert len(b) == 4 # trailing nul char + assert sizeof(b) == 4 * sizeof(c_wchar) + assert type(b[0]) is unicode + assert b[0] == u"a" + assert b[:] == "abc\0" + From fijal at codespeak.net Fri Jan 25 18:56:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 18:56:57 +0100 (CET) Subject: [pypy-svn] r51044 - pypy/dist/pypy/lib/app_test/ctypes Message-ID: <20080125175657.2E1471684EA@codespeak.net> Author: fijal Date: Fri Jan 25 18:56:56 2008 New Revision: 51044 Added: pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py (contents, props changed) Log: This one passes Added: pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_callbacks.py Fri Jan 25 18:56:56 2008 @@ -0,0 +1,135 @@ +from ctypes import * +import py + +class TestCallbacks: + functype = CFUNCTYPE + +## def tearDown(self): +## import gc +## gc.collect() + + def callback(self, *args): + self.got_args = args + return args[-1] + + def check_type(self, typ, arg): + PROTO = self.functype.im_func(typ, typ) + result = PROTO(self.callback)(arg) + if typ == c_float: + assert abs(result - arg) < 0.000001 + else: + assert self.got_args == (arg,) + assert result == arg + + PROTO = self.functype.im_func(typ, c_byte, typ) + result = PROTO(self.callback)(-3, arg) + if typ == c_float: + assert abs(result - arg) < 0.000001 + else: + assert self.got_args == (-3, arg) + assert result == arg + + ################ + + def test_byte(self): + self.check_type(c_byte, 42) + self.check_type(c_byte, -42) + + def test_ubyte(self): + self.check_type(c_ubyte, 42) + + def test_short(self): + self.check_type(c_short, 42) + self.check_type(c_short, -42) + + def test_ushort(self): + self.check_type(c_ushort, 42) + + def test_int(self): + self.check_type(c_int, 42) + self.check_type(c_int, -42) + + def test_uint(self): + self.check_type(c_uint, 42) + + def test_long(self): + self.check_type(c_long, 42) + self.check_type(c_long, -42) + + def test_ulong(self): + self.check_type(c_ulong, 42) + + def test_longlong(self): + self.check_type(c_longlong, 42) + self.check_type(c_longlong, -42) + + def test_ulonglong(self): + self.check_type(c_ulonglong, 42) + + def test_float(self): + # only almost equal: double -> float -> double + import math + self.check_type(c_float, math.e) + self.check_type(c_float, -math.e) + + def test_double(self): + self.check_type(c_double, 3.14) + self.check_type(c_double, -3.14) + + def test_char(self): + self.check_type(c_char, "x") + self.check_type(c_char, "a") + + # disabled: would now (correctly) raise a RuntimeWarning about + # a memory leak. A callback function cannot return a non-integral + # C type without causing a memory leak. +## def test_char_p(self): +## self.check_type(c_char_p, "abc") +## self.check_type(c_char_p, "def") + + def test_unsupported_restype_1(self): + py.test.skip("I don't understand this limitation") + # Only "fundamental" result types are supported for callback + # functions, the type must have a non-NULL stgdict->setfunc. + # POINTER(c_double), for example, is not supported. + + prototype = self.functype.im_func(POINTER(c_double)) + # The type is checked when the prototype is called + raises(TypeError, prototype, lambda: None) + +try: + WINFUNCTYPE +except NameError: + pass +else: + class StdcallCallbacks(Callbacks): + functype = WINFUNCTYPE + +################################################################ + +class TestSampleCallbacks: + + def test_integrate(self): + # Derived from some then non-working code, posted by David Foster + import conftest + _ctypes_test = str(conftest.sofile) + dll = CDLL(_ctypes_test) + + # The function prototype called by 'integrate': double func(double); + CALLBACK = CFUNCTYPE(c_double, c_double) + + # The integrate function itself, exposed from the _ctypes_test dll + integrate = dll.integrate + integrate.argtypes = (c_double, c_double, CALLBACK, c_long) + integrate.restype = c_double + + def func(x): + return x**2 + + result = integrate(0.0, 1.0, CALLBACK(func), 10) + diff = abs(result - 1./3.) + + assert diff < 0.01, "%s not less than 0.01" % diff + +################################################################ + From fijal at codespeak.net Fri Jan 25 20:23:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 20:23:45 +0100 (CET) Subject: [pypy-svn] r51045 - pypy/dist/pypy/module/_rawffi Message-ID: <20080125192345.4C2341684DB@codespeak.net> Author: fijal Date: Fri Jan 25 20:23:43 2008 New Revision: 51045 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py Log: Make 'Z' pointer letter as well Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Fri Jan 25 20:23:43 2008 @@ -48,7 +48,7 @@ 'O' : ffi_type_pointer, 'Z' : ffi_type_pointer, } -TYPEMAP_PTR_LETTERS = "POsz" +TYPEMAP_PTR_LETTERS = "POszZ" UNPACKED_TYPECODES = dict([(code, (code, intmask(field_desc.c_size), @@ -72,6 +72,7 @@ 'd' : rffi.DOUBLE, 's' : rffi.CCHARP, 'z' : rffi.CCHARP, + 'Z' : rffi.CArrayPtr(lltype.UniChar), 'O' : rffi.VOIDP, 'P' : rffi.VOIDP, 'v' : lltype.Void, From fijal at codespeak.net Fri Jan 25 20:26:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 20:26:32 +0100 (CET) Subject: [pypy-svn] r51046 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080125192632.0DD321684DB@codespeak.net> Author: fijal Date: Fri Jan 25 20:26:31 2008 New Revision: 51046 Added: pypy/dist/pypy/lib/app_test/ctypes/test_cast.py (contents, props changed) Modified: pypy/dist/pypy/lib/_ctypes/pointer.py pypy/dist/pypy/lib/_ctypes/primitive.py Log: * Casting from integers * get/setvalue for c_wchar_p * allow setitem on pointers on further indices (cpython allows that) Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Fri Jan 25 20:26:31 2008 @@ -95,8 +95,6 @@ return self._type_._CData_output(self._subarray(index)) def __setitem__(self, index, value): - if index != 0: - raise IndexError self._subarray(index)[0] = self._type_._CData_input(value)[0] def __nonzero__(self): @@ -114,6 +112,10 @@ ptr._buffer = tp._ffiarray(1) ptr._buffer[0] = obj._buffer return ptr + if isinstance(obj, (int, long)): + result = tp() + result._buffer[0] = obj + return result if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): raise TypeError("cast() argument 1 must be a pointer, not %s" % (type(obj),)) Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Fri Jan 25 20:26:31 2008 @@ -76,6 +76,25 @@ value = 0 self._buffer[0] = value result.value = property(_getvalue, _setvalue) + elif tp == 'Z': + # c_wchar_p + from _ctypes import Array, _Pointer, _wstring_at_addr + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + else: + return _wstring_at_addr(addr) + + def _setvalue(self, value): + if isinstance(value, str): + array = _rawffi.Array('u')(len(value)+1, value) + value = array.buffer + # XXX free 'array' later + elif value is None: + value = 0 + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) elif tp == 'P': # c_void_p Added: pypy/dist/pypy/lib/app_test/ctypes/test_cast.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/ctypes/test_cast.py Fri Jan 25 20:26:31 2008 @@ -0,0 +1,75 @@ +from ctypes import * +import sys, py + +class TestCast: + + def test_array2pointer(self): + array = (c_int * 3)(42, 17, 2) + + # casting an array to a pointer works. + ptr = cast(array, POINTER(c_int)) + assert [ptr[i] for i in range(3)] == [42, 17, 2] + + if 2*sizeof(c_short) == sizeof(c_int): + ptr = cast(array, POINTER(c_short)) + if sys.byteorder == "little": + assert [ptr[i] for i in range(6)] == ( + [42, 0, 17, 0, 2, 0]) + else: + assert [ptr[i] for i in range(6)] == ( + [0, 42, 0, 17, 0, 2]) + + def test_address2pointer(self): + array = (c_int * 3)(42, 17, 2) + + address = addressof(array) + ptr = cast(c_void_p(address), POINTER(c_int)) + assert [ptr[i] for i in range(3)] == [42, 17, 2] + + ptr = cast(address, POINTER(c_int)) + assert [ptr[i] for i in range(3)] == [42, 17, 2] + + def test_p2a_objects(self): + py.test.skip("keepalive logic") + array = (c_char_p * 5)() + assert array._objects == None + array[0] = "foo bar" + assert array._objects == {'0': "foo bar"} + + p = cast(array, POINTER(c_char_p)) + # array and p share a common _objects attribute + assert p._objects is array._objects + assert array._objects == {'0': "foo bar", id(array): array} + p[0] = "spam spam" + assert p._objects == {'0': "spam spam", id(array): array} + assert array._objects is p._objects + p[1] = "foo bar" + assert p._objects == {'1': 'foo bar', '0': "spam spam", id(array): array} + assert array._objects is p._objects + + def test_other(self): + p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int)) + assert p[:4] == [1,2, 3, 4] + c_int() + assert p[:4] == [1, 2, 3, 4] + p[2] = 96 + assert p[:4] == [1, 2, 96, 4] + c_int() + assert p[:4] == [1, 2, 96, 4] + + def test_char_p(self): + # This didn't work: bad argument to internal function + s = c_char_p("hiho") + assert cast(cast(s, c_void_p), c_char_p).value == ( + "hiho") + + try: + c_wchar_p + except NameError: + pass + else: + def test_wchar_p(self): + py.test.skip("XXX reenable") + s = c_wchar_p("hiho") + assert cast(cast(s, c_void_p), c_wchar_p).value == ( + "hiho") From fijal at codespeak.net Fri Jan 25 21:23:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 21:23:54 +0100 (CET) Subject: [pypy-svn] r51047 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes Message-ID: <20080125202354.394781684DD@codespeak.net> Author: fijal Date: Fri Jan 25 21:23:52 2008 New Revision: 51047 Modified: pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/app_test/ctypes/test_cast.py Log: Unskip test and a fix. Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Fri Jan 25 21:23:52 2008 @@ -84,7 +84,7 @@ if addr == 0: return None else: - return _wstring_at_addr(addr) + return _wstring_at_addr(addr, -1) def _setvalue(self, value): if isinstance(value, str): Modified: pypy/dist/pypy/lib/app_test/ctypes/test_cast.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes/test_cast.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes/test_cast.py Fri Jan 25 21:23:52 2008 @@ -69,7 +69,6 @@ pass else: def test_wchar_p(self): - py.test.skip("XXX reenable") s = c_wchar_p("hiho") assert cast(cast(s, c_void_p), c_wchar_p).value == ( "hiho") From fijal at codespeak.net Fri Jan 25 23:03:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 25 Jan 2008 23:03:57 +0100 (CET) Subject: [pypy-svn] r51048 - pypy/extradoc/talk/rupy2008 Message-ID: <20080125220357.707011684F7@codespeak.net> Author: fijal Date: Fri Jan 25 23:03:55 2008 New Revision: 51048 Added: pypy/extradoc/talk/rupy2008/ pypy/extradoc/talk/rupy2008/abstract.txt (contents, props changed) Log: Brain dump for potential abstract. Added: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/rupy2008/abstract.txt Fri Jan 25 23:03:55 2008 @@ -0,0 +1,23 @@ +Speakers: Maciej Fijalkowski + +Title: PyPy, Python interpreter written in Python + +Abstract: XXX + +Why another python interpreter? + +CPython is cool, but has limitations. + +Writing in C is ugly and unefficient. + +Let's write high-level interpreter in high-level language! + +Our cool features (which you haven't seen yet): + +* sandboxing +* jit (python is too dynamic, let's compile it dynamically) +* stackless (?) +* frame pickling +* gc in action + +xxx \ No newline at end of file From exarkun at codespeak.net Sat Jan 26 00:47:12 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Sat, 26 Jan 2008 00:47:12 +0100 (CET) Subject: [pypy-svn] r51050 - pypy/build/buildbot Message-ID: <20080125234712.DA3F71684F0@codespeak.net> Author: exarkun Date: Sat Jan 26 00:47:10 2008 New Revision: 51050 Modified: pypy/build/buildbot/pypybuilders.py Log: Continue the build even if translation fails; Twisted tests will not be runnable, but PyPy tests will be Modified: pypy/build/buildbot/pypybuilders.py ============================================================================== --- pypy/build/buildbot/pypybuilders.py (original) +++ pypy/build/buildbot/pypybuilders.py Sat Jan 26 00:47:10 2008 @@ -15,7 +15,7 @@ command = ["python", "translate.py", "--batch"] translationTarget = "targetpypystandalone" - haltOnFailure = True + haltOnFailure = False def __init__(self, translationArgs, targetArgs, workdir="build/pypy-src/pypy/translator/goal", From tismer at codespeak.net Sat Jan 26 04:32:30 2008 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 26 Jan 2008 04:32:30 +0100 (CET) Subject: [pypy-svn] r51051 - pypy/dist/pypy/tool Message-ID: <20080126033230.21659168435@codespeak.net> Author: tismer Date: Sat Jan 26 04:32:30 2008 New Revision: 51051 Modified: pypy/dist/pypy/tool/sourcetools.py Log: small correction for correct error message. thanks to CarlosEDP who messed with a checkout and produced this :-) Modified: pypy/dist/pypy/tool/sourcetools.py ============================================================================== --- pypy/dist/pypy/tool/sourcetools.py (original) +++ pypy/dist/pypy/tool/sourcetools.py Sat Jan 26 04:32:30 2008 @@ -66,9 +66,9 @@ if self.srctext: try: p = self.srctext.index(src) - except ValueError, e: - e.args = "Source text not found in %s - use a raw string" % self.srcname - raise + except ValueError: + msg = "Source text not found in %s - use a raw string" % self.srcname + raise ValueError(msg) prelines = self.srctext[:p].count("\n") + 1 else: prelines = 0 From fijal at codespeak.net Sat Jan 26 13:12:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jan 2008 13:12:30 +0100 (CET) Subject: [pypy-svn] r51064 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126121230.800D31684DC@codespeak.net> Author: fijal Date: Sat Jan 26 13:12:30 2008 New Revision: 51064 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: First approach to abstract. Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 13:12:30 2008 @@ -2,22 +2,13 @@ Title: PyPy, Python interpreter written in Python -Abstract: XXX +Abstract: In this talk I would like to present the PyPy project, our motivation, +state of art and targets. PyPy is both an extremely flexible python interpreter +written in Python itself to avoid burden of writing in low-level languages +(like C) and compiler toolchain which compiles restricted python to a variety +of lower-level platforms (including C/POSIX, CLI, JVM...). I would like to +present some cool features, especially those created since the last rupy +conference in 2007. Also, I would like to showcase directions in which +the PyPy project is going, including even more agressive JIT compilation. -Why another python interpreter? - -CPython is cool, but has limitations. - -Writing in C is ugly and unefficient. - -Let's write high-level interpreter in high-level language! - -Our cool features (which you haven't seen yet): - -* sandboxing -* jit (python is too dynamic, let's compile it dynamically) -* stackless (?) -* frame pickling -* gc in action - -xxx \ No newline at end of file +Details about the PyPy project can be seen at http://codespeak.net/pypy/ \ No newline at end of file From pypy-svn at codespeak.net Sat Jan 26 13:31:25 2008 From: pypy-svn at codespeak.net (® Official Site) Date: Sat, 26 Jan 2008 13:31:25 +0100 (CET) Subject: [pypy-svn] January 74% OFF Message-ID: <20080126073117.9703.qmail@c953a14b.virtua.com.br> An HTML attachment was scrubbed... URL: From hpk at codespeak.net Sat Jan 26 13:54:40 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 26 Jan 2008 13:54:40 +0100 (CET) Subject: [pypy-svn] r51065 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126125440.ED7F71684D8@codespeak.net> Author: hpk Date: Sat Jan 26 13:54:39 2008 New Revision: 51065 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: reviewed and refactored Maciej's abstract Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 13:54:39 2008 @@ -1,14 +1,13 @@ Speakers: Maciej Fijalkowski -Title: PyPy, Python interpreter written in Python +Title: PyPy - status and next goals -Abstract: In this talk I would like to present the PyPy project, our motivation, -state of art and targets. PyPy is both an extremely flexible python interpreter -written in Python itself to avoid burden of writing in low-level languages -(like C) and compiler toolchain which compiles restricted python to a variety -of lower-level platforms (including C/POSIX, CLI, JVM...). I would like to -present some cool features, especially those created since the last rupy -conference in 2007. Also, I would like to showcase directions in which -the PyPy project is going, including even more agressive JIT compilation. +Abstract: I'd like to present the status and next goals of +the PyPy project: both a platform for implementing dynamic languages +and a complete Python Interpreter written in a high level language. +PyPy translates interpreters to C, .NET and the JVM. The talk will +focus on what is new since the last RUPY conference. I am going to +talk about speed and feature improvements, including the status +and future of PyPy's Just-In-Time compiler. -Details about the PyPy project can be seen at http://codespeak.net/pypy/ \ No newline at end of file +More about the PyPy project: http://codespeak.net/pypy/ From hpk at codespeak.net Sat Jan 26 14:00:48 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 26 Jan 2008 14:00:48 +0100 (CET) Subject: [pypy-svn] r51066 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126130048.CEE60168461@codespeak.net> Author: hpk Date: Sat Jan 26 14:00:47 2008 New Revision: 51066 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: not really only just a simple JIT ... Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 14:00:47 2008 @@ -8,6 +8,6 @@ PyPy translates interpreters to C, .NET and the JVM. The talk will focus on what is new since the last RUPY conference. I am going to talk about speed and feature improvements, including the status -and future of PyPy's Just-In-Time compiler. +and future of PyPy's Just-In-Time compiler generator. More about the PyPy project: http://codespeak.net/pypy/ From fijal at codespeak.net Sat Jan 26 14:15:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jan 2008 14:15:24 +0100 (CET) Subject: [pypy-svn] r51067 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126131524.83EE91683ED@codespeak.net> Author: fijal Date: Sat Jan 26 14:15:23 2008 New Revision: 51067 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: * affiliation * try to elaborate a bit on jit and gc Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 14:15:23 2008 @@ -1,4 +1,4 @@ -Speakers: Maciej Fijalkowski +Speakers: Maciej Fijalkowski, merlinux GmbH Title: PyPy - status and next goals @@ -7,7 +7,11 @@ and a complete Python Interpreter written in a high level language. PyPy translates interpreters to C, .NET and the JVM. The talk will focus on what is new since the last RUPY conference. I am going to -talk about speed and feature improvements, including the status -and future of PyPy's Just-In-Time compiler generator. +talk about speed and feature improvements, including our flexible +garbage collection framework and status and future of our Just-in-time +compiler generator. This generator is used to automatically turn +python interpreter into compiler directly emiting assembler code, +extending the idea of the Psyco project. + More about the PyPy project: http://codespeak.net/pypy/ From fijal at codespeak.net Sat Jan 26 14:17:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 26 Jan 2008 14:17:20 +0100 (CET) Subject: [pypy-svn] r51068 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126131720.0FCD91684D2@codespeak.net> Author: fijal Date: Sat Jan 26 14:17:20 2008 New Revision: 51068 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: capitalisation Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 14:17:20 2008 @@ -6,7 +6,7 @@ the PyPy project: both a platform for implementing dynamic languages and a complete Python Interpreter written in a high level language. PyPy translates interpreters to C, .NET and the JVM. The talk will -focus on what is new since the last RUPY conference. I am going to +focus on what is new since the last RuPy conference. I am going to talk about speed and feature improvements, including our flexible garbage collection framework and status and future of our Just-in-time compiler generator. This generator is used to automatically turn From hpk at codespeak.net Sat Jan 26 14:22:14 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 26 Jan 2008 14:22:14 +0100 (CET) Subject: [pypy-svn] r51069 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126132214.1B6161683EE@codespeak.net> Author: hpk Date: Sat Jan 26 14:22:13 2008 New Revision: 51069 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: * refined english a bit * strike Psyco reference (not too telling for Ruby people) Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 14:22:13 2008 @@ -7,11 +7,10 @@ and a complete Python Interpreter written in a high level language. PyPy translates interpreters to C, .NET and the JVM. The talk will focus on what is new since the last RuPy conference. I am going to -talk about speed and feature improvements, including our flexible -garbage collection framework and status and future of our Just-in-time -compiler generator. This generator is used to automatically turn -python interpreter into compiler directly emiting assembler code, -extending the idea of the Psyco project. +talk about speed and feature improvements, particularly our flexible +garbage collection framework and the Just-in-time compiler generator. +This generator is used to automatically turn our Python interpreter +into a compiler for directly emiting assembler code. More about the PyPy project: http://codespeak.net/pypy/ From cfbolz at codespeak.net Sat Jan 26 17:11:34 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 26 Jan 2008 17:11:34 +0100 (CET) Subject: [pypy-svn] r51070 - pypy/extradoc/talk/rupy2008 Message-ID: <20080126161134.983D81684E0@codespeak.net> Author: cfbolz Date: Sat Jan 26 17:11:32 2008 New Revision: 51070 Modified: pypy/extradoc/talk/rupy2008/abstract.txt Log: typo Modified: pypy/extradoc/talk/rupy2008/abstract.txt ============================================================================== --- pypy/extradoc/talk/rupy2008/abstract.txt (original) +++ pypy/extradoc/talk/rupy2008/abstract.txt Sat Jan 26 17:11:32 2008 @@ -10,7 +10,7 @@ talk about speed and feature improvements, particularly our flexible garbage collection framework and the Just-in-time compiler generator. This generator is used to automatically turn our Python interpreter -into a compiler for directly emiting assembler code. +into a compiler for directly emitting assembler code. More about the PyPy project: http://codespeak.net/pypy/ From fijal at codespeak.net Sun Jan 27 13:35:44 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 27 Jan 2008 13:35:44 +0100 (CET) Subject: [pypy-svn] r51078 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080127123544.20E3E1684ED@codespeak.net> Author: fijal Date: Sun Jan 27 13:35:43 2008 New Revision: 51078 Modified: pypy/dist/pypy/jit/codegen/i386/operation.py Log: * Add (non-working) float operation. * Resort from one magic to different (simpler). This will allow us to test while still being rpython. Modified: pypy/dist/pypy/jit/codegen/i386/operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/operation.py (original) +++ pypy/dist/pypy/jit/codegen/i386/operation.py Sun Jan 27 13:35:43 2008 @@ -18,10 +18,31 @@ else: CALL_ALIGN = 1 +class OperationType(type): + def __new__(self, name, bases, typedict): + res = type.__new__(self, name, bases, typedict) + if 'emit_opcode' in typedict: + # create emit method based on opcode + opcode_name = typedict['emit_opcode'] + argnum = res.argnum + if argnum == 1: + def emit(self, mc, dstop): + return getattr(mc, opcode_name)(dstop) + else: + assert argnum == 2 + def emit(self, mc, dstop, op1): + return getattr(mc, opcode_name)(dstop, op1) + res.emit = emit + return res class Operation(GenVar): clobbers_cc = True side_effects = True + width = WORD + __metaclass__ = OperationType + + def getwidth(self): + return self.getwidth() def mark_used_vars(self, allocator): raise NotImplementedError @@ -29,6 +50,7 @@ raise NotImplementedError class Op1(Operation): + argnum = 1 def __init__(self, x): self.x = x def mark_used_vars(self, allocator): @@ -51,12 +73,12 @@ class OpIntNeg(UnaryOp): opname = 'int_neg', 'int_neg_ovf' - emit = staticmethod(I386CodeBuilder.NEG) + emit_opcode = 'NEG' ccexcflag = Conditions['O'] class OpIntInvert(UnaryOp): opname = 'int_invert', 'uint_invert' - emit = staticmethod(I386CodeBuilder.NOT) + emit_opcode = 'NOT' class OpIntAbs(Op1): opname = 'int_abs', 'int_abs_ovf' @@ -148,6 +170,7 @@ allocator.create_in_cc(self, ccop) class Op2(Operation): + argnum = 2 def __init__(self, x, y): self.x = x self.y = y @@ -155,6 +178,30 @@ allocator.using(self.x) allocator.using(self.y) +class OpFloatAdd(Op2): + opname = 'float_add' + width = 2*8 + + def mark_used_vars(self, allocator): + allocator.using(self.y) + allocator.using(self.x) + + def generate(self, allocator): + x, y = self.x, self.y + op1 = allocator.get_float_operand(x) + assert not isinstance(op1, ST0) + #I386CodeBuilder.FLD(allocator.mc, op1) + #op2 = allocator.get_float_operand(y) + #if not isinstance(op2, ST0): + # I386CodeBuilder.FLD(allocator.mc, op2) + #I386CodeBuilder.FADD(allocator.mc) + allocator.release(x) + #allocator.release(y) + #I386CodeBuilder.FISTP(allocator.mc, op1) + #loc = allocator.create(self) + #loc2 = allocator.create(self) + allocator.create_exactly_at(self, op1) + class BinaryOp(Op2): side_effects = False commutative = False @@ -199,26 +246,26 @@ class OpIntAdd(BinaryOp): opname = 'int_add', 'uint_add', 'int_add_ovf', 'int_add_nonneg_ovf' - emit = staticmethod(I386CodeBuilder.ADD) + emit_opcode = 'ADD' commutative = True ccexcflag = Conditions['O'] class OpIntSub(BinaryOp): opname = 'int_sub', 'uint_sub', 'int_sub_ovf' - emit = staticmethod(I386CodeBuilder.SUB) + emit_opcode = 'SUB' ccexcflag = Conditions['O'] class OpIntAnd(BinaryOp): opname = 'int_and', 'uint_and' - emit = staticmethod(I386CodeBuilder.AND) + emit_opcode = 'AND' class OpIntOr(BinaryOp): opname = 'int_or', 'uint_or' - emit = staticmethod(I386CodeBuilder.OR) + emit_opcode = 'OR' class OpIntXor(BinaryOp): opname = 'int_xor', 'uint_xor' - emit = staticmethod(I386CodeBuilder.XOR) + emit_opcode = 'XOR' class OpIntMul(Op2): opname = 'int_mul', 'int_mul_ovf' @@ -493,15 +540,15 @@ class OpIntLShift(OpShift): opname = 'int_lshift', 'uint_lshift' - emit = staticmethod(I386CodeBuilder.SHL) + emit_opcode = 'SHL' class OpUIntRShift(OpShift): opname = 'uint_rshift' - emit = staticmethod(I386CodeBuilder.SHR) + emit_opcode = 'SHR' class OpIntRShift(OpShift): opname = 'int_rshift' - emit = staticmethod(I386CodeBuilder.SAR) + emit_opcode = 'SAR' countmax31 = True class OpCompare2(Op2): From fijal at codespeak.net Sun Jan 27 13:36:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 27 Jan 2008 13:36:45 +0100 (CET) Subject: [pypy-svn] r51079 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080127123645.5B4211684E7@codespeak.net> Author: fijal Date: Sun Jan 27 13:36:43 2008 New Revision: 51079 Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py Log: Change sigToken from only number of arguments into some kind of specification. Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/i386/rgenop.py Sun Jan 27 13:36:43 2008 @@ -641,13 +641,21 @@ graphctx.write_stack_adj(mc, initial=True) # ^^^ pushed 5 words including the retval ( == PROLOGUE_FIXED_WORDS) # ---------------- - numargs = sigtoken # for now + numargs = len(sigtoken) inputargs_gv = [] inputoperands = [] + relofs = 0 for i in range(numargs): + size = sigtoken[i] + 1 inputargs_gv.append(GenVar()) - ofs = WORD * (GraphCtx.PROLOGUE_FIXED_WORDS+i) - inputoperands.append(mem(ebp, ofs)) + ofs = WORD * (GraphCtx.PROLOGUE_FIXED_WORDS+relofs) + relofs += size + if size == 1: + inputoperands.append(mem(ebp, ofs)) + elif size == 2: + inputoperands.append(mem64(ebp, ofs)) + else: + raise Exception("Unknown size %d" % (size,)) builder = Builder(self, graphctx, inputargs_gv, inputoperands) # XXX this makes the code layout in memory a bit obscure: we have the # prologue of the new graph somewhere in the middle of its first @@ -727,18 +735,23 @@ @staticmethod @specialize.memo() def kindToken(T): - if T is lltype.Float: - py.test.skip("not implemented: floats in the i386 back-end") - return None # for now + # 32 bit stuff + if T is lltype.Signed or T is llmemory.Address or \ + isinstance(T, lltype.Ptr) or T is lltype.Bool or \ + T is lltype.Void: + # XXX should be else return 0? be on the safe side + return 0 + elif T is lltype.Float: + return 1 + else: + raise NotImplementedError(T) @staticmethod @specialize.memo() def sigToken(FUNCTYPE): - numargs = 0 - for ARG in FUNCTYPE.ARGS: - if ARG is not lltype.Void: - numargs += 1 - return numargs # for now + argtokens = [RI386GenOp.kindToken(i) for i in FUNCTYPE.ARGS + if i is not lltype.Void] + return argtokens @staticmethod def erasedType(T): From fijal at codespeak.net Sun Jan 27 13:37:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 27 Jan 2008 13:37:28 +0100 (CET) Subject: [pypy-svn] r51080 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080127123728.8393E1684E7@codespeak.net> Author: fijal Date: Sun Jan 27 13:37:28 2008 New Revision: 51080 Modified: pypy/dist/pypy/jit/codegen/i386/ri386.py Log: Forgotten checkin. 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 Jan 27 13:37:28 2008 @@ -247,6 +247,9 @@ def mem(basereg, offset=0): return memSIB(basereg, None, 0, offset) +def mem64(basereg, offset=0): + return memSIB64(basereg, None, 0, offset) + def memSIB(base, index, scaleshift, offset): return _SIBencode(MODRM, base, index, scaleshift, offset) From fijal at codespeak.net Sun Jan 27 13:38:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 27 Jan 2008 13:38:02 +0100 (CET) Subject: [pypy-svn] r51081 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080127123802.CB2C91684E7@codespeak.net> Author: fijal Date: Sun Jan 27 13:38:02 2008 New Revision: 51081 Added: pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py (contents, props changed) Log: Start real unittests for regalloc. Added: pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py Sun Jan 27 13:38:02 2008 @@ -0,0 +1,41 @@ + +from pypy.jit.codegen.i386.regalloc import RegAllocator +from pypy.jit.codegen.i386 import operation as op +from pypy.jit.codegen.i386.ri386 import mem, ebp, I386CodeBuilder +from pypy.jit.codegen.model import GenVar + +WORD = op.WORD + +class DummyMc(I386CodeBuilder): + def __init__(self): + self.ops = [] + + def __getattribute__(self, attr): + if attr == '__dict__' or attr == 'ops': + return object.__getattribute__(self, attr) + def append_to_ops(*args): + if attr == 'write': + return + self.ops.append((attr, args)) + return append_to_ops + + +class TestRegalloc: + def test_basics(self): + """ This tests a simple two-arg routine + """ + varx, vary = GenVar(), GenVar() + x = mem(ebp) + y = mem(ebp, WORD) + finalloc = mem(ebp, 2*WORD) + operations = [op.OpIntAdd(varx, vary)] + regalloc = RegAllocator(operations) + regalloc.set_final(operations, [finalloc]) + regalloc.compute_lifetimes() + regalloc.init_reg_alloc([varx, vary], [x, y]) + dummy_mc = DummyMc() + regalloc.generate_operations(dummy_mc) + regalloc.generate_final_moves(operations, [finalloc]) + names = (op for op, args in dummy_mc.ops) + assert list(names) == ['MOV', 'ADD', 'PUSH', 'POP'] + # XXX more asserts here From fijal at codespeak.net Sun Jan 27 13:39:28 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 27 Jan 2008 13:39:28 +0100 (CET) Subject: [pypy-svn] r51082 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080127123928.704361684ED@codespeak.net> Author: fijal Date: Sun Jan 27 13:39:27 2008 New Revision: 51082 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py Log: This works with less magic. Modified: pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_regalloc.py Sun Jan 27 13:39:27 2008 @@ -6,13 +6,11 @@ WORD = op.WORD -class DummyMc(I386CodeBuilder): +class DummyMc: def __init__(self): self.ops = [] - def __getattribute__(self, attr): - if attr == '__dict__' or attr == 'ops': - return object.__getattribute__(self, attr) + def __getattr__(self, attr): def append_to_ops(*args): if attr == 'write': return From cfbolz at codespeak.net Sun Jan 27 13:59:23 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 27 Jan 2008 13:59:23 +0100 (CET) Subject: [pypy-svn] r51083 - pypy/branch/jit-float-support Message-ID: <20080127125923.7F3921684EF@codespeak.net> Author: cfbolz Date: Sun Jan 27 13:59:21 2008 New Revision: 51083 Removed: pypy/branch/jit-float-support/ Log: kill branch From cfbolz at codespeak.net Sun Jan 27 14:00:22 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 27 Jan 2008 14:00:22 +0100 (CET) Subject: [pypy-svn] r51084 - pypy/branch/jit-float-support Message-ID: <20080127130022.4F5361684EF@codespeak.net> Author: cfbolz Date: Sun Jan 27 14:00:21 2008 New Revision: 51084 Added: pypy/branch/jit-float-support/ - copied from r51083, pypy/dist/ Log: branch dist again, the current dist contains the changes maciek wanted to do on the branch From cfbolz at codespeak.net Sun Jan 27 14:15:48 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 27 Jan 2008 14:15:48 +0100 (CET) Subject: [pypy-svn] r51085 - pypy/dist/pypy/jit Message-ID: <20080127131548.08EB61684E7@codespeak.net> Author: cfbolz Date: Sun Jan 27 14:15:48 2008 New Revision: 51085 Removed: pypy/dist/pypy/jit/ Log: kill the JIT dir to restore it to its old state From cfbolz at codespeak.net Sun Jan 27 14:17:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 27 Jan 2008 14:17:10 +0100 (CET) Subject: [pypy-svn] r51086 - pypy/dist/pypy/jit Message-ID: <20080127131710.7CC981684E7@codespeak.net> Author: cfbolz Date: Sun Jan 27 14:17:10 2008 New Revision: 51086 Added: pypy/dist/pypy/jit/ - copied from r51020, pypy/dist/pypy/jit/ Log: restore the jit dir to the state before Maciek's branch From pypy-svn at codespeak.net Mon Jan 28 23:56:45 2008 From: pypy-svn at codespeak.net (pypy-svn at codespeak.net) Date: Mon, 28 Jan 2008 23:56:45 +0100 (CET) Subject: [pypy-svn] Winter Sale -- For Adventure Lovers Message-ID: <20080128125631.9107.qmail@adsl196-168-110-217-196.adsl196-12.iam.net.ma> An HTML attachment was scrubbed... URL: From cfbolz at codespeak.net Tue Jan 29 14:37:00 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 29 Jan 2008 14:37:00 +0100 (CET) Subject: [pypy-svn] r51109 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20080129133700.B221E16840B@codespeak.net> Author: cfbolz Date: Tue Jan 29 14:36:59 2008 New Revision: 51109 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py Log: comment out float stuff, maciek is working on it on a branch Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386.py Tue Jan 29 14:36:59 2008 @@ -74,9 +74,9 @@ # call +17 yield check, '\xE8\x11\x00\x00\x00', 'CALL', rel32(22) # fld - yield check, '\xDD\x44\x24\x04', 'FLD', mem(esp, 4) + #yield check, '\xDD\x44\x24\x04', 'FLD', mem(esp, 4) # fadd - yield check, '\xDC\x44\x24\x08', 'FADD', mem(esp, 8) + #yield check, '\xDC\x44\x24\x08', 'FADD', mem(esp, 8) ##def test_conditional(): ## """Compare the encoding for the instructions JE, JAE, JC etc., From exarkun at codespeak.net Tue Jan 29 15:22:12 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Tue, 29 Jan 2008 15:22:12 +0100 (CET) Subject: [pypy-svn] r51110 - pypy/build/buildbot Message-ID: <20080129142212.0A661168413@codespeak.net> Author: exarkun Date: Tue Jan 29 15:22:12 2008 New Revision: 51110 Modified: pypy/build/buildbot/pypy_status.py Log: recentFailures is across all builders, so don't reset it every time through the builder loop Modified: pypy/build/buildbot/pypy_status.py ============================================================================== --- pypy/build/buildbot/pypy_status.py (original) +++ pypy/build/buildbot/pypy_status.py Tue Jan 29 15:22:12 2008 @@ -11,13 +11,13 @@ def body(self, request): status = self.getStatus(request) builderNames = status.getBuilderNames() + recentFailures = Set() failedTests = {} anyBuildResults = Set() buildNumbers = range(self.oldBuildCount - 1, -1, -1) for name in builderNames: - recentFailures = Set() builder = status.getBuilder(name) recentBuilds = builder.generateFinishedBuilds( branches=[None], num_builds=self.oldBuildCount) From cfbolz at codespeak.net Tue Jan 29 15:28:50 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 29 Jan 2008 15:28:50 +0100 (CET) Subject: [pypy-svn] r51111 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080129142850.7FCB2168413@codespeak.net> Author: cfbolz Date: Tue Jan 29 15:28:48 2008 New Revision: 51111 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: this __del__ is completely pointless: the KeepaliveKeeper objects are static in practice and never have their __del__ called. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Tue Jan 29 15:28:48 2008 @@ -226,13 +226,6 @@ def __init__(self): self.stuff_to_keepalive = [] self.free_positions = [] - - def __del__(self): - # checker - num = len([i for i in self.stuff_to_keepalive if i is not None]) - if num: - print "WARNING! %d elements kept alive for type %s" % \ - (num, tp_str) keeper = KeepaliveKeeper() _KEEPER_CACHE[TP] = keeper return keeper From cfbolz at codespeak.net Wed Jan 30 14:07:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 14:07:45 +0100 (CET) Subject: [pypy-svn] r51125 - pypy/branch/jit-refactoring Message-ID: <20080130130745.F1C3A1683FB@codespeak.net> Author: cfbolz Date: Wed Jan 30 14:07:44 2008 New Revision: 51125 Added: pypy/branch/jit-refactoring/ - copied from r51124, pypy/dist/ Log: a branch for the rainbow interpreter refactoring From cfbolz at codespeak.net Wed Jan 30 14:18:01 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 14:18:01 +0100 (CET) Subject: [pypy-svn] r51126 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test Message-ID: <20080130131801.7F66216843E@codespeak.net> Author: cfbolz Date: Wed Jan 30 14:18:00 2008 New Revision: 51126 Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/ pypy/branch/jit-refactoring/pypy/jit/rainbow/__init__.py (contents, props changed) pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (contents, props changed) pypy/branch/jit-refactoring/pypy/jit/rainbow/test/ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/__init__.py (contents, props changed) pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (contents, props changed) Log: start serializing graphs for the rainbow interpreter. all very sketchy at the moment. Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/__init__.py ============================================================================== Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- (empty file) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 14:18:00 2008 @@ -0,0 +1,303 @@ +from pypy.objspace.flow import model as flowmodel +from pypy.rpython.lltypesystem import lltype +from pypy.jit.hintannotator.model import originalconcretetype +from pypy.jit.timeshifter import rtimeshift, rvalue +from pypy.rlib.unroll import unrolling_iterable + +class JitCode(object): + """ + normal operations have the following format: + 2 byte - operation + n * 2 byte - arguments + + for nonvoid results the result is appended to the varlist + + red vars are just indexes + green vars are positive indexes + green consts are negative indexes + """ + + def __init__(self, code, constants): + self.code = code + self.constants = constants + + def _freeze_(self): + return True + +class JitInterpreter(object): + def __init__(self): + self.opcode_implementations = [] + self.opcode_descs = [] + self.opname_to_index = {} + self.jitstate = None + self.bytecode = None + self._add_implemented_opcodes() + + # construction-time interface + + def _add_implemented_opcodes(self): + for name in dir(self): + if not name.startswith("opimpl_"): + continue + opname = name[len("opimpl_"):] + self.opname_to_index[opname] = len(self.opcode_implementations) + self.opcode_implementations.append(getattr(self, name).im_func) + self.opcode_descs.append(None) + + + def find_opcode(self, name): + return self.opname_to_index.get(name, -1) + + def make_opcode_implementation(self, color, opdesc): + numargs = unrolling_iterable(range(opdesc.nb_args)) + if color == "green": + def implementation(self): + args = () + for i in numargs: + args.append(self.get_greenarg()) + result = opdesc.llop(*args) + self.green_result(result) + elif color == "red": + if opdesc.nb_args == 1: + impl = rtimeshift.ll_gen1 + elif opdesc.nb_args == 2: + impl = rtimeshift.ll_gen2 + else: + XXX + def implementation(self): + args = (self.jitstate, ) + for i in numargs: + args.append(self.get_redarg()) + result = impl(*args) + self.red_result(result) + else: + assert 0, "unknown color" + implementation.func_name = "opimpl_%s_%s" % (color, opdesc.opname) + opname = "%s_%s" % (color, opdesc.opname) + index = self.opname_to_index[opname] = len(self.opcode_implementations) + self.opcode_implementations.append(implementation) + self.opcode_descs.append(opdesc) + return index + + + # operation implemetations + def opimpl_make_redbox(self): + XXX + + def opimpl_goto(self): + XXX + + def opimpl_goto_green_iftrue(self): + XXX + + def opimpl_goto_red_iftrue(self): + XXX + + def opimpl_red_return(self): + XXX + + def opimpl_green_return(self): + XXX + + def opimpl_make_new_redvars(self): + # an opcode with a variable number of args + # num_args arg_old_1 arg_new_1 ... + XXX + + def opimpl_make_new_greenvars(self): + # an opcode with a variable number of args + # num_args arg_old_1 arg_new_1 ... + XXX + + +class BytecodeWriter(object): + def __init__(self, t, hintannotator, RGenOp): + self.translator = t + self.annotator = t.annotator + self.hannotator = hintannotator + self.interpreter = JitInterpreter() + self.RGenOp = RGenOp + + def make_bytecode(self, graph): + self.seen_blocks = {} + self.bytecode = [] + self.constants = [] + self.const_positions = {} + self.block_positions = {} + self.graph = graph + self.entrymap = flowmodel.mkentrymap(graph) + self.make_bytecode_block(graph.startblock) + self.patch_jumps() + return JitCode("".join(self.bytecode), self.constants) + + def make_bytecode_block(self, block, insert_goto=False): + if block in self.block_positions: + if insert_goto: + self.emit_2byte(self.interpreter.find_opcode("goto")) + self.emit_4byte(self.block_positions[block]) + return + # inserting a goto not necessary, falling through + self.current_block = block + self.redvar_positions = {} + self.greenvar_positions = {} + self.block_positions[block] = len(self.bytecode) + reds, greens = self.sort_by_color(block.inputargs) + # asign positions to the arguments + for arg in reds: + self.redvar_position(arg) + for arg in greens: + self.greenvar_positions(arg) + #self.insert_merges(block) + for op in block.operations: + self.serialize_op(op) + #self.insert_splits(block) + self.insert_exits(block) + + def insert_exits(self, block): + if block.exits == (): + returnvar, = block.inputargs + if self.hannotator.binding(returnvar).is_green(): + color = "green" + else: + color = "red" + self.emit_2byte(self.interpreter.find_opcode("%s_return" % color)) + self.emit_2byte(self.serialize_oparg(color, returnvar)) + elif len(block.exits) == 1: + link, = block.exits + self.insert_renaming(link.args) + self.make_bytecode_block(link.target, insert_goto=True) + else: + XXX + + def patch_jumps(self): + for i in range(len(self.bytecode)): + if isinstance(self.bytecode[i], str): + continue + assert 0 + # must be a block + index = self.block_positions[self.bytecode[i]] + self.bytecode[i + 0] = chr((index >> 24) & 0xff) + self.bytecode[i + 1] = chr((index >> 16) & 0xff) + self.bytecode[i + 2] = chr((index >> 8) & 0xff) + self.bytecode[i + 3] = chr(index & 0xff) + + + def insert_renaming(self, args): + reds, greens = self.sort_by_color(args) + for color, args in [("red", reds), ("green", greens)]: + result = [] + for v in args: + result.append(self.serialize_oparg(color, v)) + self.emit_2byte(self.interpreter.find_opcode( + "make_new_%svars" % (color, ))) + self.emit_2byte(len(args)) + for index in result: + self.emit_2byte(index) + + def serialize_op(self, op): + color = self.opcolor(op) + args = [] + for arg in op.args: + args.append(self.serialize_oparg(color, arg)) + self.serialize_opcode(color, op) + for index in args: + self.emit_2byte(index) + if self.hannotator.binding(op.result).is_green(): + self.green_position(op.result) + else: + self.redvar_position(op.result) + + + def serialize_opcode(self, color, op): + opname = op.opname + name = "%s_%s" % (color, opname) + index = self.interpreter.find_opcode(name) + if index == -1: + hop = PseudoHOP( + op, [self.hannotator.binding(arg) for arg in op.args], + self.hannotator.binding(op.result), self.RGenOp) + opdesc = rtimeshift.make_opdesc(hop) + index = self.interpreter.make_opcode_implementation(color, opdesc) + self.emit_2byte(index) + + def serialize_oparg(self, color, arg): + if color == "red": + if self.hannotator.binding(arg).is_green(): + return self.convert_to_red(arg) + return self.redvar_position(arg) + XXX + + def convert_to_red(self, arg): + if arg in self.redvar_positions: + # already converted + return self.redvar_positions[arg] + self.emit_2byte(self.interpreter.find_opcode("make_redbox")) + resultindex = self.redvar_positions[arg] = len(self.redvar_positions) + argindex = self.green_position(arg) + self.emit_2byte(resultindex) + self.emit_2byte(argindex) + return resultindex + + def opcolor(self, op): + for v in op.args: + if not self.hannotator.binding(v).is_green(): + return "red" + if not self.hannotator.binding(op.result).is_green(): + return "red" + return "green" + + def redvar_position(self, arg): + return self.redvar_positions.setdefault( + arg, len(self.redvar_positions)) + + def green_position(self, arg): + if isinstance(arg, flowmodel.Variable): + return self.greenvar_positions.setdefault( + arg, len(self.greenvar_positions)) + return -self.const_positions(arg) + + def const_position(self, const): + if const in self.const_position: + return self.const_position[const] + XXX + + def emit_2byte(self, index): + assert not index & 0xffff0000 + self.bytecode.append(chr((index >> 8) & 0xff)) + self.bytecode.append(chr(index & 0xff)) + + def emit_4byte(self, index): + self.bytecode.append(chr((index >> 24) & 0xff)) + self.bytecode.append(chr((index >> 16) & 0xff)) + self.bytecode.append(chr((index >> 8) & 0xff)) + self.bytecode.append(chr(index & 0xff)) + + def emit_jumptarget(self, block): + self.bytecode.extend((block, None, None, None)) + + def sort_by_color(self, vars, by_color_of_vars=None): + reds = [] + greens = [] + if by_color_of_vars is None: + by_color_of_vars = vars + for v, bcv in zip(vars, by_color_of_vars): + if v.concretetype is lltype.Void: + continue + if self.hannotator.binding(bcv).is_green(): + greens.append(v) + else: + reds.append(v) + return reds, greens + +# XXX too lazy to fix the interface of make_opdesc +class PseudoHOP(object): + def __init__(self, op, args_s, s_result, RGenOp): + self.spaceop = op + self.args_s = args_s + self.s_result = s_result + self.rtyper = PseudoHRTyper(RGenOp) + +class PseudoHRTyper(object): + def __init__(self, RGenOp): + self.RGenOp = RGenOp + Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/__init__.py ============================================================================== Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- (empty file) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 14:18:00 2008 @@ -0,0 +1,85 @@ +from pypy.translator.translator import TranslationContext, graphof +from pypy.jit.hintannotator.annotator import HintAnnotator +from pypy.jit.hintannotator.policy import StopAtXPolicy, HintAnnotatorPolicy +from pypy.jit.hintannotator.model import SomeLLAbstractConstant, OriginFlags +from pypy.jit.rainbow.bytecode import BytecodeWriter +from pypy.jit.codegen.llgraph.rgenop import RGenOp +from pypy import conftest + + +P_DEFAULT = HintAnnotatorPolicy(entrypoint_returns_red=False) +P_OOPSPEC = HintAnnotatorPolicy(oopspec=True, + entrypoint_returns_red=False) +P_OOPSPEC_NOVIRTUAL = HintAnnotatorPolicy(oopspec=True, + novirtualcontainer=True, + entrypoint_returns_red=False) +P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True, + entrypoint_returns_red=False) + +class AbstractSerializationTest: + type_system = None + + def serialize(self, func, argtypes, policy=P_DEFAULT, inline=None, + backendoptimize=False): + # build the normal ll graphs for ll_function + t = TranslationContext() + a = t.buildannotator() + a.build_types(func, argtypes) + rtyper = t.buildrtyper(type_system = self.type_system) + rtyper.specialize() + if inline: + auto_inlining(t, threshold=inline) + if backendoptimize: + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(t) + graph1 = graphof(t, func) + + # build hint annotator types + policy = self.fixpolicy(policy) + 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() + graph2 = graphof(t, func) + writer = BytecodeWriter(t, hannotator, RGenOp) + jitcode = writer.make_bytecode(graph2) + return writer, jitcode + + def fixpolicy(self, policy): + return policy + + def test_simple(self): + def f(x, y): + return x + y + writer, jitcode = self.serialize(f, [int, int]) + assert jitcode.code == code(writer.interpreter, + "red_int_add", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + "red_return", 0) + + + + +def code(interpreter, *args): + result = [] + def emit_2byte(index): + result.append(chr((index >> 8) & 0xff)) + result.append(chr(index & 0xff)) + for arg in args: + if isinstance(arg, str): + emit_2byte(interpreter.find_opcode(arg)) + elif isinstance(arg, int): + emit_2byte(arg) + else: + XXX + return "".join(result) + + + +class TestLLType(AbstractSerializationTest): + type_system = "lltype" From exarkun at codespeak.net Wed Jan 30 14:37:58 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Wed, 30 Jan 2008 14:37:58 +0100 (CET) Subject: [pypy-svn] r51127 - pypy/build/buildbot Message-ID: <20080130133758.60F961683CF@codespeak.net> Author: exarkun Date: Wed Jan 30 14:37:57 2008 New Revision: 51127 Modified: pypy/build/buildbot/master.cfg Log: disable tests on linux64 and win32 for the time being on each platform, the tests exhaust all available resources and force the machines so hard into swap that they must be power cycled Modified: pypy/build/buildbot/master.cfg ============================================================================== --- pypy/build/buildbot/master.cfg (original) +++ pypy/build/buildbot/master.cfg Wed Jan 30 14:37:57 2008 @@ -55,7 +55,7 @@ {"name": "pypy-c-allworkingmodules-faassen-64", "slavenames": ["linux-dvs0"], "builddir": "pypy-c-allworkingmodules-faassen-64", - "factory": PyPyBuildFactory(["--boxed"], + "factory": PyPyBuildFactory(None, [], ["--allworkingmodules", "--faassen"])}, @@ -63,7 +63,7 @@ {"name": "pypy-c-allworkingmodules-faassen-winxp32", "slavenames": ["winxp32-py2.5"], "builddir": "pypy-c-allworkingmodules-faassen-winxp32", - "factory": PyPyBuildFactory([], + "factory": PyPyBuildFactory(None, [], ["--allworkingmodules"])}, ], From cfbolz at codespeak.net Wed Jan 30 15:15:27 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 15:15:27 +0100 (CET) Subject: [pypy-svn] r51128 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test Message-ID: <20080130141527.3BE36168422@codespeak.net> Author: cfbolz Date: Wed Jan 30 15:15:26 2008 New Revision: 51128 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Log: adding switches Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 15:15:26 2008 @@ -87,10 +87,10 @@ def opimpl_goto(self): XXX - def opimpl_goto_green_iftrue(self): + def opimpl_green_goto_iftrue(self): XXX - def opimpl_goto_red_iftrue(self): + def opimpl_red_goto_iftrue(self): XXX def opimpl_red_return(self): @@ -124,6 +124,7 @@ self.constants = [] self.const_positions = {} self.block_positions = {} + self.additional_positions = {} self.graph = graph self.entrymap = flowmodel.mkentrymap(graph) self.make_bytecode_block(graph.startblock) @@ -156,26 +157,41 @@ def insert_exits(self, block): if block.exits == (): returnvar, = block.inputargs - if self.hannotator.binding(returnvar).is_green(): - color = "green" - else: - color = "red" + color = self.varcolor(returnvar) + index = self.serialize_oparg(color, returnvar) self.emit_2byte(self.interpreter.find_opcode("%s_return" % color)) - self.emit_2byte(self.serialize_oparg(color, returnvar)) + self.emit_2byte(index) elif len(block.exits) == 1: link, = block.exits self.insert_renaming(link.args) self.make_bytecode_block(link.target, insert_goto=True) + elif len(block.exits) == 2: + linkfalse, linktrue = block.exits + if linkfalse.llexitcase == True: + linkfalse, linktrue = linktrue, linkfalse + color = self.varcolor(block.exitswitch) + index = self.serialize_oparg(color, block.exitswitch) + self.emit_2byte(self.interpreter.find_opcode("%s_goto_iftrue" % color)) + self.emit_2byte(index) + self.emit_jumptarget(linktrue) + self.insert_renaming(linkfalse.args) + self.make_bytecode_block(linkfalse.target, insert_goto=True) + self.additional_positions[linktrue] = len(self.bytecode) + self.insert_renaming(linktrue.args) + self.emit_2byte(self.interpreter.find_opcode("goto")) + self.emit_jumptarget(linktrue.target) else: XXX def patch_jumps(self): for i in range(len(self.bytecode)): + byte = self.bytecode[i] if isinstance(self.bytecode[i], str): continue - assert 0 - # must be a block - index = self.block_positions[self.bytecode[i]] + if byte in self.block_positions: + index = self.block_positions[byte] + else: + index = self.additional_positions[byte] self.bytecode[i + 0] = chr((index >> 24) & 0xff) self.bytecode[i + 1] = chr((index >> 16) & 0xff) self.bytecode[i + 2] = chr((index >> 8) & 0xff) @@ -245,6 +261,13 @@ if not self.hannotator.binding(op.result).is_green(): return "red" return "green" + + def varcolor(self, var): + if self.hannotator.binding(var).is_green(): + color = "green" + else: + color = "red" + return color def redvar_position(self, arg): return self.redvar_positions.setdefault( Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 15:15:26 2008 @@ -62,11 +62,39 @@ "make_new_greenvars", 0, "red_return", 0) - - + def test_switch(self): + def f(x, y, z): + if x: + return y + else: + return z + writer, jitcode = self.serialize(f, [int, int, int]) + expected = code(writer.interpreter, + "red_int_is_true", 0, + "red_goto_iftrue", 3, tlabel("true"), + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + label("return"), + "red_return", 0, + label("true"), + "make_new_redvars", 1, 1, + "make_new_greenvars", 0, + "goto", tlabel("return"), + ) + assert jitcode.code == expected + + +class label(object): + def __init__(self, name): + self.name = name + +class tlabel(object): + def __init__(self, name): + self.name = name def code(interpreter, *args): result = [] + labelpos = {} def emit_2byte(index): result.append(chr((index >> 8) & 0xff)) result.append(chr(index & 0xff)) @@ -75,8 +103,20 @@ emit_2byte(interpreter.find_opcode(arg)) elif isinstance(arg, int): emit_2byte(arg) + elif isinstance(arg, label): + labelpos[arg.name] = len(result) + elif isinstance(arg, tlabel): + result.extend((arg, None, None, None)) else: XXX + for i in range(len(result)): + b = result[i] + if isinstance(b, tlabel): + index = labelpos[b.name] + result[i + 0] = chr((index >> 24) & 0xff) + result[i + 1] = chr((index >> 16) & 0xff) + result[i + 2] = chr((index >> 8) & 0xff) + result[i + 3] = chr(index & 0xff) return "".join(result) From cfbolz at codespeak.net Wed Jan 30 16:17:38 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 16:17:38 +0100 (CET) Subject: [pypy-svn] r51131 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test Message-ID: <20080130151738.3E08F16842C@codespeak.net> Author: cfbolz Date: Wed Jan 30 16:17:37 2008 New Revision: 51131 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Log: more complex switch test + fix Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 16:17:37 2008 @@ -178,8 +178,7 @@ self.make_bytecode_block(linkfalse.target, insert_goto=True) self.additional_positions[linktrue] = len(self.bytecode) self.insert_renaming(linktrue.args) - self.emit_2byte(self.interpreter.find_opcode("goto")) - self.emit_jumptarget(linktrue.target) + self.make_bytecode_block(linktrue.target, insert_goto=True) else: XXX Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 16:17:37 2008 @@ -4,6 +4,7 @@ from pypy.jit.hintannotator.model import SomeLLAbstractConstant, OriginFlags from pypy.jit.rainbow.bytecode import BytecodeWriter from pypy.jit.codegen.llgraph.rgenop import RGenOp +from pypy.rlib.jit import hint from pypy import conftest @@ -83,6 +84,36 @@ ) assert jitcode.code == expected + def test_switch2(self): + def f(x, y, z): + if x: + return y + z + else: + return y - z + writer, jitcode = self.serialize(f, [int, int, int]) + expected = code(writer.interpreter, + "red_int_is_true", 0, + "red_goto_iftrue", 3, tlabel("true"), + "make_new_redvars", 2, 1, 2, + "make_new_greenvars", 0, + label("sub"), + "red_int_sub", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + label("return"), + "red_return", 0, + label("true"), + "make_new_redvars", 2, 1, 2, + "make_new_greenvars", 0, + label("add"), + "red_int_add", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + "goto", tlabel("return"), + ) + assert jitcode.code == expected + + class label(object): def __init__(self, name): From cfbolz at codespeak.net Wed Jan 30 16:42:50 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 16:42:50 +0100 (CET) Subject: [pypy-svn] r51133 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test Message-ID: <20080130154250.CF39F16841D@codespeak.net> Author: cfbolz Date: Wed Jan 30 16:42:49 2008 New Revision: 51133 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Log: use the nice assembler I wrote for tests for the real bytecode serialization too Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 16:42:49 2008 @@ -120,28 +120,28 @@ def make_bytecode(self, graph): self.seen_blocks = {} - self.bytecode = [] + self.assembler = [] self.constants = [] self.const_positions = {} - self.block_positions = {} + self.seen_blocks = {} self.additional_positions = {} self.graph = graph self.entrymap = flowmodel.mkentrymap(graph) self.make_bytecode_block(graph.startblock) - self.patch_jumps() - return JitCode("".join(self.bytecode), self.constants) + return JitCode(assemble(self.interpreter, *self.assembler), self.constants) def make_bytecode_block(self, block, insert_goto=False): - if block in self.block_positions: + if block in self.seen_blocks: if insert_goto: - self.emit_2byte(self.interpreter.find_opcode("goto")) - self.emit_4byte(self.block_positions[block]) + self.emit("goto") + self.emit(tlabel(block)) return # inserting a goto not necessary, falling through + self.seen_blocks[block] = True self.current_block = block self.redvar_positions = {} self.greenvar_positions = {} - self.block_positions[block] = len(self.bytecode) + self.emit(label(block)) reds, greens = self.sort_by_color(block.inputargs) # asign positions to the arguments for arg in reds: @@ -159,8 +159,8 @@ returnvar, = block.inputargs color = self.varcolor(returnvar) index = self.serialize_oparg(color, returnvar) - self.emit_2byte(self.interpreter.find_opcode("%s_return" % color)) - self.emit_2byte(index) + self.emit("%s_return" % color) + self.emit(index) elif len(block.exits) == 1: link, = block.exits self.insert_renaming(link.args) @@ -171,43 +171,27 @@ linkfalse, linktrue = linktrue, linkfalse color = self.varcolor(block.exitswitch) index = self.serialize_oparg(color, block.exitswitch) - self.emit_2byte(self.interpreter.find_opcode("%s_goto_iftrue" % color)) - self.emit_2byte(index) - self.emit_jumptarget(linktrue) + self.emit("%s_goto_iftrue" % color) + self.emit(index) + self.emit(tlabel(linktrue)) self.insert_renaming(linkfalse.args) self.make_bytecode_block(linkfalse.target, insert_goto=True) - self.additional_positions[linktrue] = len(self.bytecode) + self.emit(label(linktrue)) self.insert_renaming(linktrue.args) self.make_bytecode_block(linktrue.target, insert_goto=True) else: XXX - def patch_jumps(self): - for i in range(len(self.bytecode)): - byte = self.bytecode[i] - if isinstance(self.bytecode[i], str): - continue - if byte in self.block_positions: - index = self.block_positions[byte] - else: - index = self.additional_positions[byte] - self.bytecode[i + 0] = chr((index >> 24) & 0xff) - self.bytecode[i + 1] = chr((index >> 16) & 0xff) - self.bytecode[i + 2] = chr((index >> 8) & 0xff) - self.bytecode[i + 3] = chr(index & 0xff) - - def insert_renaming(self, args): reds, greens = self.sort_by_color(args) for color, args in [("red", reds), ("green", greens)]: result = [] for v in args: result.append(self.serialize_oparg(color, v)) - self.emit_2byte(self.interpreter.find_opcode( - "make_new_%svars" % (color, ))) - self.emit_2byte(len(args)) + self.emit("make_new_%svars" % (color, )) + self.emit(len(args)) for index in result: - self.emit_2byte(index) + self.emit(index) def serialize_op(self, op): color = self.opcolor(op) @@ -216,7 +200,7 @@ args.append(self.serialize_oparg(color, arg)) self.serialize_opcode(color, op) for index in args: - self.emit_2byte(index) + self.emit(index) if self.hannotator.binding(op.result).is_green(): self.green_position(op.result) else: @@ -233,7 +217,7 @@ self.hannotator.binding(op.result), self.RGenOp) opdesc = rtimeshift.make_opdesc(hop) index = self.interpreter.make_opcode_implementation(color, opdesc) - self.emit_2byte(index) + self.emit(name) def serialize_oparg(self, color, arg): if color == "red": @@ -246,11 +230,11 @@ if arg in self.redvar_positions: # already converted return self.redvar_positions[arg] - self.emit_2byte(self.interpreter.find_opcode("make_redbox")) + self.emit("make_redbox") resultindex = self.redvar_positions[arg] = len(self.redvar_positions) argindex = self.green_position(arg) - self.emit_2byte(resultindex) - self.emit_2byte(argindex) + self.emit(resultindex) + self.emit(argindex) return resultindex def opcolor(self, op): @@ -283,19 +267,8 @@ return self.const_position[const] XXX - def emit_2byte(self, index): - assert not index & 0xffff0000 - self.bytecode.append(chr((index >> 8) & 0xff)) - self.bytecode.append(chr(index & 0xff)) - - def emit_4byte(self, index): - self.bytecode.append(chr((index >> 24) & 0xff)) - self.bytecode.append(chr((index >> 16) & 0xff)) - self.bytecode.append(chr((index >> 8) & 0xff)) - self.bytecode.append(chr(index & 0xff)) - - def emit_jumptarget(self, block): - self.bytecode.extend((block, None, None, None)) + def emit(self, stuff): + self.assembler.append(stuff) def sort_by_color(self, vars, by_color_of_vars=None): reds = [] @@ -311,6 +284,45 @@ reds.append(v) return reds, greens + + +class label(object): + def __init__(self, name): + self.name = name + +class tlabel(object): + def __init__(self, name): + self.name = name + +def assemble(interpreter, *args): + result = [] + labelpos = {} + def emit_2byte(index): + result.append(chr((index >> 8) & 0xff)) + result.append(chr(index & 0xff)) + for arg in args: + if isinstance(arg, str): + emit_2byte(interpreter.find_opcode(arg)) + elif isinstance(arg, int): + emit_2byte(arg) + elif isinstance(arg, label): + labelpos[arg.name] = len(result) + elif isinstance(arg, tlabel): + result.extend((arg, None, None, None)) + else: + XXX + for i in range(len(result)): + b = result[i] + if isinstance(b, tlabel): + index = labelpos[b.name] + result[i + 0] = chr((index >> 24) & 0xff) + result[i + 1] = chr((index >> 16) & 0xff) + result[i + 2] = chr((index >> 8) & 0xff) + result[i + 3] = chr(index & 0xff) + return "".join(result) + + + # XXX too lazy to fix the interface of make_opdesc class PseudoHOP(object): def __init__(self, op, args_s, s_result, RGenOp): Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 16:42:49 2008 @@ -2,7 +2,7 @@ from pypy.jit.hintannotator.annotator import HintAnnotator from pypy.jit.hintannotator.policy import StopAtXPolicy, HintAnnotatorPolicy from pypy.jit.hintannotator.model import SomeLLAbstractConstant, OriginFlags -from pypy.jit.rainbow.bytecode import BytecodeWriter +from pypy.jit.rainbow.bytecode import BytecodeWriter, label, tlabel, assemble from pypy.jit.codegen.llgraph.rgenop import RGenOp from pypy.rlib.jit import hint from pypy import conftest @@ -57,12 +57,12 @@ def f(x, y): return x + y writer, jitcode = self.serialize(f, [int, int]) - assert jitcode.code == code(writer.interpreter, - "red_int_add", 0, 1, - "make_new_redvars", 1, 2, - "make_new_greenvars", 0, - "red_return", 0) - + assert jitcode.code == assemble(writer.interpreter, + "red_int_add", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + "red_return", 0) + def test_switch(self): def f(x, y, z): if x: @@ -70,18 +70,18 @@ else: return z writer, jitcode = self.serialize(f, [int, int, int]) - expected = code(writer.interpreter, - "red_int_is_true", 0, - "red_goto_iftrue", 3, tlabel("true"), - "make_new_redvars", 1, 2, - "make_new_greenvars", 0, - label("return"), - "red_return", 0, - label("true"), - "make_new_redvars", 1, 1, - "make_new_greenvars", 0, - "goto", tlabel("return"), - ) + expected = assemble(writer.interpreter, + "red_int_is_true", 0, + "red_goto_iftrue", 3, tlabel("true"), + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + label("return"), + "red_return", 0, + label("true"), + "make_new_redvars", 1, 1, + "make_new_greenvars", 0, + "goto", tlabel("return"), + ) assert jitcode.code == expected def test_switch2(self): @@ -91,66 +91,29 @@ else: return y - z writer, jitcode = self.serialize(f, [int, int, int]) - expected = code(writer.interpreter, - "red_int_is_true", 0, - "red_goto_iftrue", 3, tlabel("true"), - "make_new_redvars", 2, 1, 2, - "make_new_greenvars", 0, - label("sub"), - "red_int_sub", 0, 1, - "make_new_redvars", 1, 2, - "make_new_greenvars", 0, - label("return"), - "red_return", 0, - label("true"), - "make_new_redvars", 2, 1, 2, - "make_new_greenvars", 0, - label("add"), - "red_int_add", 0, 1, - "make_new_redvars", 1, 2, - "make_new_greenvars", 0, - "goto", tlabel("return"), - ) + expected = assemble(writer.interpreter, + "red_int_is_true", 0, + "red_goto_iftrue", 3, tlabel("true"), + "make_new_redvars", 2, 1, 2, + "make_new_greenvars", 0, + label("sub"), + "red_int_sub", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + label("return"), + "red_return", 0, + label("true"), + "make_new_redvars", 2, 1, 2, + "make_new_greenvars", 0, + label("add"), + "red_int_add", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + "goto", tlabel("return"), + ) assert jitcode.code == expected -class label(object): - def __init__(self, name): - self.name = name - -class tlabel(object): - def __init__(self, name): - self.name = name - -def code(interpreter, *args): - result = [] - labelpos = {} - def emit_2byte(index): - result.append(chr((index >> 8) & 0xff)) - result.append(chr(index & 0xff)) - for arg in args: - if isinstance(arg, str): - emit_2byte(interpreter.find_opcode(arg)) - elif isinstance(arg, int): - emit_2byte(arg) - elif isinstance(arg, label): - labelpos[arg.name] = len(result) - elif isinstance(arg, tlabel): - result.extend((arg, None, None, None)) - else: - XXX - for i in range(len(result)): - b = result[i] - if isinstance(b, tlabel): - index = labelpos[b.name] - result[i + 0] = chr((index >> 24) & 0xff) - result[i + 1] = chr((index >> 16) & 0xff) - result[i + 2] = chr((index >> 8) & 0xff) - result[i + 3] = chr(index & 0xff) - return "".join(result) - - - class TestLLType(AbstractSerializationTest): type_system = "lltype" From cfbolz at codespeak.net Wed Jan 30 22:53:20 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 22:53:20 +0100 (CET) Subject: [pypy-svn] r51146 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test Message-ID: <20080130215320.EECEF1683F0@codespeak.net> Author: cfbolz Date: Wed Jan 30 22:53:18 2008 New Revision: 51146 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Log: rewrite that test to use a green switch, since a red switch would need a proper split operation Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 22:53:18 2008 @@ -117,6 +117,7 @@ self.hannotator = hintannotator self.interpreter = JitInterpreter() self.RGenOp = RGenOp + self.current_block = None def make_bytecode(self, graph): self.seen_blocks = {} @@ -125,9 +126,14 @@ self.const_positions = {} self.seen_blocks = {} self.additional_positions = {} + self.redvar_positions = {} + self.free_red = {} + self.greenvar_positions = {} + self.free_green = {} self.graph = graph self.entrymap = flowmodel.mkentrymap(graph) self.make_bytecode_block(graph.startblock) + assert self.current_block is None return JitCode(assemble(self.interpreter, *self.assembler), self.constants) def make_bytecode_block(self, block, insert_goto=False): @@ -138,21 +144,22 @@ return # inserting a goto not necessary, falling through self.seen_blocks[block] = True + oldblock = self.current_block + self.free_green[block] = 0 + self.free_red[block] = 0 self.current_block = block - self.redvar_positions = {} - self.greenvar_positions = {} self.emit(label(block)) reds, greens = self.sort_by_color(block.inputargs) - # asign positions to the arguments for arg in reds: - self.redvar_position(arg) + self.register_redvar(arg) for arg in greens: - self.greenvar_positions(arg) + self.register_greenvar(arg) #self.insert_merges(block) for op in block.operations: self.serialize_op(op) #self.insert_splits(block) self.insert_exits(block) + self.current_block = oldblock def insert_exits(self, block): if block.exits == (): @@ -194,6 +201,9 @@ self.emit(index) def serialize_op(self, op): + specialcase = getattr(self, "serialize_op_%s" % (op.opname, ), None) + if specialcase is not None: + return specialcase(op) color = self.opcolor(op) args = [] for arg in op.args: @@ -202,9 +212,9 @@ for index in args: self.emit(index) if self.hannotator.binding(op.result).is_green(): - self.green_position(op.result) + self.register_greenvar(op.result) else: - self.redvar_position(op.result) + self.register_redvar(op.result) def serialize_opcode(self, color, op): @@ -221,17 +231,19 @@ def serialize_oparg(self, color, arg): if color == "red": - if self.hannotator.binding(arg).is_green(): + if self.varcolor(arg) == "green": return self.convert_to_red(arg) return self.redvar_position(arg) - XXX + elif color == "green": + return self.green_position(arg) + assert 0, "unknown color" def convert_to_red(self, arg): if arg in self.redvar_positions: # already converted return self.redvar_positions[arg] self.emit("make_redbox") - resultindex = self.redvar_positions[arg] = len(self.redvar_positions) + resultindex = self.register_redvar((arg, block)) argindex = self.green_position(arg) self.emit(resultindex) self.emit(argindex) @@ -252,14 +264,26 @@ color = "red" return color + def register_redvar(self, arg): + print "register_redvar", arg + assert arg not in self.redvar_positions + self.redvar_positions[arg] = result = self.free_red[self.current_block] + self.free_red[self.current_block] += 1 + def redvar_position(self, arg): - return self.redvar_positions.setdefault( - arg, len(self.redvar_positions)) - + return self.redvar_positions[arg] + + def register_greenvar(self, arg, where=-1): + assert isinstance(arg, flowmodel.Variable) + if where == -1: + where = self.free_green[self.current_block] + self.free_green[self.current_block] += 1 + self.greenvar_positions[arg] = where + return where + def green_position(self, arg): if isinstance(arg, flowmodel.Variable): - return self.greenvar_positions.setdefault( - arg, len(self.greenvar_positions)) + return self.greenvar_positions[arg] return -self.const_positions(arg) def const_position(self, const): @@ -284,16 +308,34 @@ reds.append(v) return reds, greens + # operation special cases + + def serialize_op_hint(self, op): + hints = op.args[1].value + arg = op.args[0] + result = op.result + if "concrete" in hints: + assert self.hannotator.binding(arg).is_green() + assert self.hannotator.binding(result).is_green() + self.register_greenvar(result, self.green_position(arg)) + return + XXX class label(object): def __init__(self, name): self.name = name + def __repr__(self): + return "label(%r)" % (self.name, ) + class tlabel(object): def __init__(self, name): self.name = name + def __repr__(self): + return "tlabel(%r)" % (self.name, ) + def assemble(interpreter, *args): result = [] labelpos = {} Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 22:53:18 2008 @@ -63,22 +63,23 @@ "make_new_greenvars", 0, "red_return", 0) - def test_switch(self): + def test_green_switch(self): def f(x, y, z): + x = hint(x, concrete=True) if x: return y else: return z writer, jitcode = self.serialize(f, [int, int, int]) expected = assemble(writer.interpreter, - "red_int_is_true", 0, - "red_goto_iftrue", 3, tlabel("true"), - "make_new_redvars", 1, 2, + "green_int_is_true", 0, + "green_goto_iftrue", 1, tlabel("true"), + "make_new_redvars", 1, 1, "make_new_greenvars", 0, label("return"), "red_return", 0, label("true"), - "make_new_redvars", 1, 1, + "make_new_redvars", 1, 0, "make_new_greenvars", 0, "goto", tlabel("return"), ) From cfbolz at codespeak.net Wed Jan 30 22:55:23 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 22:55:23 +0100 (CET) Subject: [pypy-svn] r51147 - pypy/branch/jit-refactoring/pypy/jit/rainbow/test Message-ID: <20080130215523.0D5821683FC@codespeak.net> Author: cfbolz Date: Wed Jan 30 22:55:22 2008 New Revision: 51147 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Log: rewrite that test too Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 22:55:22 2008 @@ -85,17 +85,18 @@ ) assert jitcode.code == expected - def test_switch2(self): + def test_green_switch2(self): def f(x, y, z): + x = hint(x, concrete=True) if x: return y + z else: return y - z writer, jitcode = self.serialize(f, [int, int, int]) expected = assemble(writer.interpreter, - "red_int_is_true", 0, - "red_goto_iftrue", 3, tlabel("true"), - "make_new_redvars", 2, 1, 2, + "green_int_is_true", 0, + "green_goto_iftrue", 1, tlabel("true"), + "make_new_redvars", 2, 0, 1, "make_new_greenvars", 0, label("sub"), "red_int_sub", 0, 1, @@ -104,7 +105,7 @@ label("return"), "red_return", 0, label("true"), - "make_new_redvars", 2, 1, 2, + "make_new_redvars", 2, 0, 1, "make_new_greenvars", 0, label("add"), "red_int_add", 0, 1, From cfbolz at codespeak.net Wed Jan 30 23:06:32 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 30 Jan 2008 23:06:32 +0100 (CET) Subject: [pypy-svn] r51148 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test Message-ID: <20080130220632.9D928168423@codespeak.net> Author: cfbolz Date: Wed Jan 30 23:06:31 2008 New Revision: 51148 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Log: write a test involving a constant and fix the bugs Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 23:06:31 2008 @@ -239,13 +239,13 @@ assert 0, "unknown color" def convert_to_red(self, arg): - if arg in self.redvar_positions: + block = self.current_block + if (arg, block) in self.redvar_positions: # already converted return self.redvar_positions[arg] self.emit("make_redbox") resultindex = self.register_redvar((arg, block)) argindex = self.green_position(arg) - self.emit(resultindex) self.emit(argindex) return resultindex @@ -269,6 +269,7 @@ assert arg not in self.redvar_positions self.redvar_positions[arg] = result = self.free_red[self.current_block] self.free_red[self.current_block] += 1 + return result def redvar_position(self, arg): return self.redvar_positions[arg] @@ -284,14 +285,19 @@ def green_position(self, arg): if isinstance(arg, flowmodel.Variable): return self.greenvar_positions[arg] - return -self.const_positions(arg) + return -self.const_position(arg) - 1 def const_position(self, const): - if const in self.const_position: - return self.const_position[const] - XXX + if const in self.const_positions: + return self.const_positions[const] + const = self.RGenOp.constPrebuiltGlobal(const.value) + result = len(self.constants) + self.constants.append(const) + self.const_positions[const] = result + return result def emit(self, stuff): + assert stuff is not None self.assembler.append(stuff) def sort_by_color(self, vars, by_color_of_vars=None): Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 23:06:31 2008 @@ -62,6 +62,19 @@ "make_new_redvars", 1, 2, "make_new_greenvars", 0, "red_return", 0) + assert len(jitcode.constants) == 0 + + def test_constant(self): + def f(x): + return x + 1 + writer, jitcode = self.serialize(f, [int]) + assert jitcode.code == assemble(writer.interpreter, + "make_redbox", -1, + "red_int_add", 0, 1, + "make_new_redvars", 1, 2, + "make_new_greenvars", 0, + "red_return", 0) + assert len(jitcode.constants) == 1 def test_green_switch(self): def f(x, y, z): @@ -84,6 +97,7 @@ "goto", tlabel("return"), ) assert jitcode.code == expected + assert len(jitcode.constants) == 0 def test_green_switch2(self): def f(x, y, z): @@ -114,6 +128,7 @@ "goto", tlabel("return"), ) assert jitcode.code == expected + assert len(jitcode.constants) == 0 From cfbolz at codespeak.net Thu Jan 31 11:13:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 31 Jan 2008 11:13:10 +0100 (CET) Subject: [pypy-svn] r51151 - pypy/branch/jit-refactoring/pypy/jit/rainbow Message-ID: <20080131101310.88313168423@codespeak.net> Author: cfbolz Date: Thu Jan 31 11:13:10 2008 New Revision: 51151 Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Log: an XXX so that I don't forget: the implementation of green operations is wrong Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py ============================================================================== --- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (original) +++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Thu Jan 31 11:13:10 2008 @@ -65,6 +65,9 @@ else: XXX def implementation(self): + XXX + # the following is nonsense: the green arguments are + # GenConsts, so there are revealconsts missing args = (self.jitstate, ) for i in numargs: args.append(self.get_redarg()) From antocuni at codespeak.net Thu Jan 31 18:02:22 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 31 Jan 2008 18:02:22 +0100 (CET) Subject: [pypy-svn] r51160 - pypy/dist/pypy/jit/codegen/test Message-ID: <20080131170222.40A7A16846A@codespeak.net> Author: antocuni Date: Thu Jan 31 18:02:21 2008 New Revision: 51160 Modified: pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Log: refactor rgenop tests to easily switch to ootype Modified: pypy/dist/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/dist/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Thu Jan 31 18:02:21 2008 @@ -10,15 +10,22 @@ rtyper = None GENOP_POLICY = MixLevelAnnotatorPolicy(PseudoAnnhelper()) -FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) -FUNC2 = lltype.FuncType([lltype.Signed]*2, lltype.Signed) -FUNC3 = lltype.FuncType([lltype.Signed]*3, lltype.Signed) -FUNC5 = lltype.FuncType([lltype.Signed]*5, lltype.Signed) -FUNC27= lltype.FuncType([lltype.Signed]*27, lltype.Signed) +class LLType(object): + FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) + FUNC2 = lltype.FuncType([lltype.Signed]*2, lltype.Signed) + FUNC3 = lltype.FuncType([lltype.Signed]*3, lltype.Signed) + FUNC5 = lltype.FuncType([lltype.Signed]*5, lltype.Signed) + FUNC27= lltype.FuncType([lltype.Signed]*27, lltype.Signed) + FUNC100 = lltype.FuncType([lltype.Signed]*100, lltype.Signed) + + @staticmethod + def Ptr(FUNC): + return lltype.Ptr(FUNC) + -def make_adder(rgenop, n): +def make_adder(T, rgenop, n): # 'return x+n' - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_add_one, [gv_x] = rgenop.newgraph(sigtoken, "adder") builder.start_writing() gv_result = builder.genop2("int_add", gv_x, rgenop.genconst(n)) @@ -26,20 +33,20 @@ builder.end() return gv_add_one -def get_adder_runner(RGenOp): +def get_adder_runner(T, RGenOp): def runner(x, y): rgenop = RGenOp() - gv_add_x = make_adder(rgenop, x) - add_x = gv_add_x.revealconst(lltype.Ptr(FUNC)) + gv_add_x = make_adder(T, rgenop, x) + add_x = gv_add_x.revealconst(T.Ptr(T.FUNC)) res = add_x(y) keepalive_until_here(rgenop) # to keep the code blocks alive return res return runner -def make_dummy(rgenop): +def make_dummy(T, rgenop): # 'return x - (y - (x-1))' signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(T.FUNC2) builder, gv_dummyfn, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "dummy") builder.start_writing() gv_z = builder.genop2("int_sub", gv_x, rgenop.genconst(1)) @@ -55,18 +62,16 @@ builder.end() return gv_dummyfn -def get_dummy_runner(RGenOp): +def get_dummy_runner(T, RGenOp): def dummy_runner(x, y): rgenop = RGenOp() - gv_dummyfn = make_dummy(rgenop) - dummyfn = gv_dummyfn.revealconst(lltype.Ptr(FUNC2)) + gv_dummyfn = make_dummy(T, rgenop) + dummyfn = gv_dummyfn.revealconst(T.Ptr(T.FUNC2)) res = dummyfn(x, y) keepalive_until_here(rgenop) # to keep the code blocks alive return res return dummy_runner -FUNC100 = lltype.FuncType([lltype.Signed]*100, lltype.Signed) - def largedummy_example(): args = [random.randrange(-10, 50) for i in range(100)] total = 0 @@ -74,10 +79,10 @@ total += args[i] - args[i+1] return args, total -def make_largedummy(rgenop): +def make_largedummy(T, rgenop): # 'return v0-v1+v2-v3+v4-v5...+v98-v99' signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC100) + sigtoken = rgenop.sigToken(T.FUNC100) builder, gv_largedummyfn, gvs = rgenop.newgraph(sigtoken, "largedummy") builder.start_writing() @@ -94,7 +99,7 @@ builder.end() return gv_largedummyfn -def get_largedummy_runner(RGenOp): +def get_largedummy_runner(T, RGenOp): def largedummy_runner(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, @@ -106,8 +111,8 @@ v80, v81, v82, v83, v84, v85, v86, v87, v88, v89, v90, v91, v92, v93, v94, v95, v96, v97, v98, v99): rgenop = RGenOp() - gv_largedummyfn = make_largedummy(rgenop) - largedummyfn = gv_largedummyfn.revealconst(lltype.Ptr(FUNC100)) + gv_largedummyfn = make_largedummy(T, rgenop) + largedummyfn = gv_largedummyfn.revealconst(T.Ptr(T.FUNC100)) res = largedummyfn(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, @@ -122,11 +127,11 @@ return res return largedummy_runner -def make_branching(rgenop): +def make_branching(T, rgenop): # 'if x > 5: return x-1 # else: return y' signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(T.FUNC2) builder, gv_branchingfn, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "branching") builder.start_writing() @@ -149,11 +154,11 @@ builder.end() return gv_branchingfn -def get_branching_runner(RGenOp): +def get_branching_runner(T, RGenOp): def branching_runner(x, y): rgenop = RGenOp() - gv_branchingfn = make_branching(rgenop) - branchingfn = gv_branchingfn.revealconst(lltype.Ptr(FUNC2)) + gv_branchingfn = make_branching(T, rgenop) + branchingfn = gv_branchingfn.revealconst(T.Ptr(T.FUNC2)) res = branchingfn(x, y) keepalive_until_here(rgenop) # to keep the code blocks alive return res @@ -187,7 +192,7 @@ gv_x2 = bodybuilder.genop2("int_sub", gv_x, rgenop.genconst(1)) bodybuilder.finish_and_goto([gv_x2, gv_y2, gv_z2], loopblock) -def make_goto(rgenop): +def make_goto(T, rgenop): # z = 1 # while x > 0: # z = x * z @@ -196,7 +201,7 @@ # y += z # return y signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(T.FUNC2) builder, gv_gotofn, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "goto") builder.start_writing() @@ -211,23 +216,23 @@ builder.end() return gv_gotofn -def get_goto_runner(RGenOp): +def get_goto_runner(T, RGenOp): def goto_runner(x, y): rgenop = RGenOp() - gv_gotofn = make_goto(rgenop) - gotofn = gv_gotofn.revealconst(lltype.Ptr(FUNC2)) + gv_gotofn = make_goto(T, rgenop) + gotofn = gv_gotofn.revealconst(T.Ptr(T.FUNC2)) res = gotofn(x, y) keepalive_until_here(rgenop) # to keep the code blocks alive return res return goto_runner -def make_if(rgenop): +def make_if(T, rgenop): # a = x # if x > 5: # x //= 2 # return x + a signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(T.FUNC2) builder, gv_gotofn, [gv_x1, gv_unused] = rgenop.newgraph(sigtoken, "if") builder.start_writing() @@ -257,17 +262,17 @@ builder.end() return gv_gotofn -def get_if_runner(RGenOp): +def get_if_runner(T, RGenOp): def if_runner(x, y): rgenop = RGenOp() - gv_iffn = make_if(rgenop) - iffn = gv_iffn.revealconst(lltype.Ptr(FUNC2)) + gv_iffn = make_if(T, rgenop) + iffn = gv_iffn.revealconst(T.Ptr(T.FUNC2)) res = iffn(x, y) keepalive_until_here(rgenop) # to keep the code blocks alive return res return if_runner -def make_switch(rgenop): +def make_switch(T, rgenop): """ def f(v0, v1): if v0 == 0: # switch @@ -278,7 +283,7 @@ return v1 """ signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(T.FUNC2) builder, gv_switch, [gv0, gv1] = rgenop.newgraph(sigtoken, "switch") builder.start_writing() @@ -301,17 +306,17 @@ builder.end() return gv_switch -def get_switch_runner(RGenOp): +def get_switch_runner(T, RGenOp): def switch_runner(x, y): rgenop = RGenOp() - gv_switchfn = make_switch(rgenop) - switchfn = gv_switchfn.revealconst(lltype.Ptr(FUNC2)) + gv_switchfn = make_switch(T, rgenop) + switchfn = gv_switchfn.revealconst(T.Ptr(T.FUNC2)) res = switchfn(x, y) keepalive_until_here(rgenop) # to keep the code blocks alive return res return switch_runner -def make_large_switch(rgenop): +def make_large_switch(T, rgenop): """ def f(v0, v1): if v0 == 0: # switch @@ -327,7 +332,7 @@ return v1 """ signed_tok = rgenop.kindToken(lltype.Signed) - f2_token = rgenop.sigToken(FUNC2) + f2_token = rgenop.sigToken(T.FUNC2) builder, gv_switch, (gv0, gv1) = rgenop.newgraph(f2_token, "large_switch") builder.start_writing() @@ -352,17 +357,17 @@ builder.end() return gv_switch -def get_large_switch_runner(RGenOp): +def get_large_switch_runner(T, RGenOp): def large_switch_runner(x, y): rgenop = RGenOp() - gv_large_switchfn = make_large_switch(rgenop) - largeswitchfn = gv_large_switchfn.revealconst(lltype.Ptr(FUNC2)) + gv_large_switchfn = make_large_switch(T, rgenop) + largeswitchfn = gv_large_switchfn.revealconst(T.Ptr(T.FUNC2)) res = largeswitchfn(x, y) keepalive_until_here(rgenop) # to keep the code blocks alive return res return large_switch_runner -def make_fact(rgenop): +def make_fact(T, rgenop): # def fact(x): # if x: # y = x-1 @@ -371,7 +376,7 @@ # return w # return 1 signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_fact, [gv_x] = rgenop.newgraph(sigtoken, "fact") builder.start_writing() @@ -391,24 +396,24 @@ builder.end() return gv_fact -def get_fact_runner(RGenOp): +def get_fact_runner(T, RGenOp): def fact_runner(x): rgenop = RGenOp() - gv_large_switchfn = make_fact(rgenop) - largeswitchfn = gv_large_switchfn.revealconst(lltype.Ptr(FUNC)) + gv_large_switchfn = make_fact(T, rgenop) + largeswitchfn = gv_large_switchfn.revealconst(T.Ptr(T.FUNC)) res = largeswitchfn(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res return fact_runner -def make_func_calling_pause(rgenop): +def make_func_calling_pause(T, rgenop): # def f(x): # if x > 0: # return x # else: # return -x signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "abs") builder.start_writing() @@ -429,17 +434,17 @@ builder.end() return gv_f -def get_func_calling_pause_runner(RGenOp): +def get_func_calling_pause_runner(T, RGenOp): def runner(x): rgenop = RGenOp() - gv_abs = make_func_calling_pause(rgenop) - myabs = gv_abs.revealconst(lltype.Ptr(FUNC)) + gv_abs = make_func_calling_pause(T, rgenop) + myabs = gv_abs.revealconst(T.Ptr(T.FUNC)) res = myabs(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res return runner -def make_longwinded_and(rgenop): +def make_longwinded_and(T, rgenop): # def f(y): return 2 <= y <= 4 # but more like this: # def f(y) @@ -452,7 +457,7 @@ # return 0 bool_kind = rgenop.kindToken(lltype.Bool) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_f, [gv_y] = rgenop.newgraph(sigtoken, "abs") builder.start_writing() @@ -479,10 +484,10 @@ builder.end() return gv_f -def make_condition_result_cross_link(rgenop): +def make_condition_result_cross_link(T, rgenop): signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_f, [gv_y] = rgenop.newgraph(sigtoken, "foo") builder.start_writing() @@ -503,7 +508,7 @@ builder.end() return gv_f -def make_pause_and_resume(rgenop): +def make_pause_and_resume(T, rgenop): # def f(x): # y = x + 1 # # pause/resume here @@ -511,7 +516,7 @@ # w = y*z # return w signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_callable, [gv_x] = rgenop.newgraph(sigtoken, "f") builder.start_writing() @@ -531,17 +536,17 @@ return gv_callable -def get_pause_and_resume_runner(RGenOp): +def get_pause_and_resume_runner(T, RGenOp): def runner(x): rgenop = RGenOp() - gv_f = make_pause_and_resume(rgenop) - f = gv_f.revealconst(lltype.Ptr(FUNC)) + gv_f = make_pause_and_resume(T, rgenop) + f = gv_f.revealconst(T.Ptr(T.FUNC)) res = f(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res return runner -def make_something_a_bit_like_residual_red_call_with_exc(rgenop): +def make_something_a_bit_like_residual_red_call_with_exc(T, rgenop): # def f(x, y): # if x: # z = 1 @@ -561,9 +566,9 @@ # u = add1(z2) # v = u * z # return add1(u) - gv_add1 = make_adder(rgenop, 1) + gv_add1 = make_adder(T, rgenop, 1) signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(T.FUNC2) builder, gv_f, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "f") builder.start_writing() @@ -571,7 +576,7 @@ true_builder = builder.jump_if_true(gv_c, []) - gv_y2 = builder.genop_call(rgenop.sigToken(FUNC), gv_add1, [gv_y]) + gv_y2 = builder.genop_call(rgenop.sigToken(T.FUNC), gv_add1, [gv_y]) args_gv = [gv_y2, gv_y] label = builder.enter_next_block([signed_kind, signed_kind], args_gv) @@ -582,11 +587,11 @@ gv_z2 = builder.genop2("int_mul", gv_z, gv_w) - gv_u = builder.genop_call(rgenop.sigToken(FUNC), gv_add1, [gv_z2]) + gv_u = builder.genop_call(rgenop.sigToken(T.FUNC), gv_add1, [gv_z2]) gv_v = builder.genop2("int_mul", gv_u, gv_z) - gv_result = builder.genop_call(rgenop.sigToken(FUNC), gv_add1, [gv_u]) + gv_result = builder.genop_call(rgenop.sigToken(T.FUNC), gv_add1, [gv_u]) builder.finish_and_return(sigtoken, gv_result) @@ -596,7 +601,7 @@ builder.end() return gv_f -def make_call_functions_with_different_signatures(rgenop): +def make_call_functions_with_different_signatures(T, rgenop): # this also tests calling functions with enormous numbers of # parameters, something not tested yet. # def f(x, y): @@ -604,12 +609,12 @@ # w = add1(x) # return z+w - gv_largedummy = make_largedummy(rgenop) - gv_add1 = make_adder(rgenop, 1) + gv_largedummy = make_largedummy(T, rgenop) + gv_add1 = make_adder(T, rgenop, 1) - sig2token = rgenop.sigToken(FUNC2) - sig1token = rgenop.sigToken(FUNC) - sig100token = rgenop.sigToken(FUNC100) + sig2token = rgenop.sigToken(T.FUNC2) + sig1token = rgenop.sigToken(T.FUNC) + sig100token = rgenop.sigToken(T.FUNC100) builder, gv_callable, [gv_x, gv_y] = rgenop.newgraph(sig2token, "f") builder.start_writing() @@ -632,9 +637,9 @@ self.frameinfo = info return llhelper(self.FUNC, self.reader) -def make_read_frame_var(rgenop, get_reader): +def make_read_frame_var(T, rgenop, get_reader): signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) readertoken = rgenop.sigToken(FrameVarReader.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") @@ -654,13 +659,13 @@ return gv_f -def get_read_frame_var_runner(RGenOp): +def get_read_frame_var_runner(T, RGenOp): fvr = FrameVarReader(RGenOp) def read_frame_var_runner(x): rgenop = RGenOp() - gv_f = make_read_frame_var(rgenop, fvr.get_reader) - fn = gv_f.revealconst(lltype.Ptr(FUNC)) + gv_f = make_read_frame_var(T, rgenop, fvr.get_reader) + fn = gv_f.revealconst(T.Ptr(T.FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res @@ -682,9 +687,9 @@ self.place2 = place2 return llhelper(self.FUNC, self.writer) -def make_write_frame_place(rgenop, get_writer): +def make_write_frame_place(T, rgenop, get_writer): signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) writertoken = rgenop.sigToken(FramePlaceWriter.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") @@ -704,13 +709,13 @@ return gv_f -def get_write_frame_place_runner(RGenOp): +def get_write_frame_place_runner(T, RGenOp): fvw = FramePlaceWriter(RGenOp) def write_frame_place_runner(x): rgenop = RGenOp() - gv_f = make_write_frame_place(rgenop, fvw.get_writer) - fn = gv_f.revealconst(lltype.Ptr(FUNC)) + gv_f = make_write_frame_place(T, rgenop, fvw.get_writer) + fn = gv_f.revealconst(T.Ptr(T.FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res @@ -733,9 +738,9 @@ self.places = places return llhelper(self.FUNC, self.writer) -def make_write_lots_of_frame_places(rgenop, get_writer): +def make_write_lots_of_frame_places(T, rgenop, get_writer): signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) writertoken = rgenop.sigToken(FramePlaceWriter.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") @@ -755,13 +760,13 @@ return gv_f -def get_write_lots_of_frame_places_runner(RGenOp): +def get_write_lots_of_frame_places_runner(T, RGenOp): fvw = ManyFramePlaceWriter(RGenOp) def write_lots_of_frame_places_runner(x): rgenop = RGenOp() - gv_f = make_write_lots_of_frame_places(rgenop, fvw.get_writer) - fn = gv_f.revealconst(lltype.Ptr(FUNC)) + gv_f = make_write_lots_of_frame_places(T, rgenop, fvw.get_writer) + fn = gv_f.revealconst(T.Ptr(T.FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res @@ -779,9 +784,9 @@ self.place = place return llhelper(self.FUNC, self.reader) -def make_read_frame_place(rgenop, get_reader): +def make_read_frame_place(T, rgenop, get_reader): signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(T.FUNC) readertoken = rgenop.sigToken(FramePlaceReader.FUNC.TO) builder, gv_f, [gv_x] = rgenop.newgraph(sigtoken, "f") @@ -798,20 +803,20 @@ return gv_f -def get_read_frame_place_runner(RGenOp): +def get_read_frame_place_runner(T, RGenOp): fpr = FramePlaceReader(RGenOp) def read_frame_place_runner(x): rgenop = RGenOp() - gv_f = make_read_frame_place(rgenop, fpr.get_reader) - fn = gv_f.revealconst(lltype.Ptr(FUNC)) + gv_f = make_read_frame_place(T, rgenop, fpr.get_reader) + fn = gv_f.revealconst(T.Ptr(T.FUNC)) res = fn(x) keepalive_until_here(rgenop) # to keep the code blocks alive return res return read_frame_place_runner -def make_ovfcheck_adder(rgenop, n): - sigtoken = rgenop.sigToken(FUNC) +def make_ovfcheck_adder(T, rgenop, n): + sigtoken = rgenop.sigToken(T.FUNC) builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "ovfcheck_adder") builder.start_writing() gv_result, gv_flag = builder.genraisingop2("int_add_ovf", gv_x, @@ -823,11 +828,11 @@ builder.end() return gv_fn -def get_ovfcheck_adder_runner(RGenOp): +def get_ovfcheck_adder_runner(T, RGenOp): def runner(x, y): rgenop = RGenOp() - gv_add_x = make_ovfcheck_adder(rgenop, x) - add_x = gv_add_x.revealconst(lltype.Ptr(FUNC)) + gv_add_x = make_ovfcheck_adder(T, rgenop, x) + add_x = gv_add_x.revealconst(T.Ptr(T.FUNC)) res = add_x(y) keepalive_until_here(rgenop) # to keep the code blocks alive return res @@ -837,6 +842,7 @@ class AbstractRGenOpTests(test_boehm.AbstractGCTestClass): RGenOp = None RGenOpPacked = None + T = LLType def compile(self, runner, argtypes): return self.getcompiled(runner, argtypes, @@ -860,15 +866,16 @@ # def callable(x, y): # return f(x) + x + y rgenop = self.RGenOp() + T = self.T def f(x): return x + 1 - gv_f = rgenop.genconst(self.directtesthelper(lltype.Ptr(FUNC), f)) + gv_f = rgenop.genconst(self.directtesthelper(T.Ptr(T.FUNC), f)) signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken1 = rgenop.sigToken(FUNC) - sigtoken2 = rgenop.sigToken(FUNC2) + sigtoken1 = rgenop.sigToken(T.FUNC) + sigtoken2 = rgenop.sigToken(T.FUNC2) builder, gv_callable, [gv_x, gv_y] = rgenop.newgraph(sigtoken2, "callable") builder.start_writing() @@ -885,25 +892,25 @@ def test_adder_direct(self): rgenop = self.RGenOp() - gv_add_5 = make_adder(rgenop, 5) + gv_add_5 = make_adder(self.T, rgenop, 5) fnptr = self.cast(gv_add_5, 1) res = fnptr(37) assert res == 42 def test_adder_compile(self): - fn = self.compile(get_adder_runner(self.RGenOp), [int, int]) + fn = self.compile(get_adder_runner(self.T, self.RGenOp), [int, int]) res = fn(9080983, -9080941) assert res == 42 def test_dummy_direct(self): rgenop = self.RGenOp() - gv_dummyfn = make_dummy(rgenop) + gv_dummyfn = make_dummy(self.T, rgenop) fnptr = self.cast(gv_dummyfn, 2) res = fnptr(30, 17) assert res == 42 def test_dummy_compile(self): - fn = self.compile(get_dummy_runner(self.RGenOp), [int, int]) + fn = self.compile(get_dummy_runner(self.T, self.RGenOp), [int, int]) res = fn(40, 37) assert res == 42 @@ -924,7 +931,7 @@ def test_hide_and_reveal_p(self): RGenOp = self.RGenOp S = lltype.GcStruct('s', ('x', lltype.Signed)) - S_PTR = lltype.Ptr(S) + S_PTR = self.T.Ptr(S) s1 = lltype.malloc(S) s1.x = 8111 s2 = lltype.malloc(S) @@ -951,21 +958,21 @@ def test_largedummy_direct(self): rgenop = self.RGenOp() - gv_largedummyfn = make_largedummy(rgenop) + gv_largedummyfn = make_largedummy(self.T, rgenop) fnptr = self.cast(gv_largedummyfn, 100) args, expected = largedummy_example() res = fnptr(*args) assert res == expected def test_largedummy_compile(self): - fn = self.compile(get_largedummy_runner(self.RGenOp), [int] * 100) + fn = self.compile(get_largedummy_runner(self.T, self.RGenOp), [int] * 100) args, expected = largedummy_example() res = fn(*args) assert res == expected def test_branching_direct(self): rgenop = self.RGenOp() - gv_branchingfn = make_branching(rgenop) + gv_branchingfn = make_branching(self.T, rgenop) fnptr = self.cast(gv_branchingfn, 2) res = fnptr(30, 17) assert res == 29 @@ -973,7 +980,7 @@ assert res == 17 def test_branching_compile(self): - fn = self.compile(get_branching_runner(self.RGenOp), [int, int]) + fn = self.compile(get_branching_runner(self.T, self.RGenOp), [int, int]) res = fn(30, 17) assert res == 29 res = fn(3, 17) @@ -981,7 +988,7 @@ def test_goto_direct(self): rgenop = self.RGenOp() - gv_gotofn = make_goto(rgenop) + gv_gotofn = make_goto(self.T, rgenop) fnptr = self.cast(gv_gotofn, 2) res = fnptr(10, 17) # <== the segfault is here assert res == 3628872 @@ -989,7 +996,7 @@ assert res == 29 def test_goto_compile(self): - fn = self.compile(get_goto_runner(self.RGenOp), [int, int]) + fn = self.compile(get_goto_runner(self.T, self.RGenOp), [int, int]) res = fn(10, 17) assert res == 3628872 res = fn(3, 17) @@ -997,7 +1004,7 @@ def test_if_direct(self): rgenop = self.RGenOp() - gv_iffn = make_if(rgenop) + gv_iffn = make_if(self.T, rgenop) fnptr = self.cast(gv_iffn, 2) res = fnptr(30, 0) assert res == 45 @@ -1005,7 +1012,7 @@ assert res == 6 def test_if_compile(self): - fn = self.compile(get_if_runner(self.RGenOp), [int, int]) + fn = self.compile(get_if_runner(self.T, self.RGenOp), [int, int]) res = fn(30, 0) assert res == 45 res = fn(3, 0) @@ -1013,7 +1020,7 @@ def test_switch_direct(self): rgenop = self.RGenOp() - gv_switchfn = make_switch(rgenop) + gv_switchfn = make_switch(self.T, rgenop) fnptr = self.cast(gv_switchfn, 2) res = fnptr(0, 2) assert res == 42 @@ -1023,7 +1030,7 @@ assert res == 16 def test_switch_compile(self): - fn = self.compile(get_switch_runner(self.RGenOp), [int, int]) + fn = self.compile(get_switch_runner(self.T, self.RGenOp), [int, int]) res = fn(0, 2) assert res == 42 res = fn(1, 17) @@ -1033,7 +1040,7 @@ def test_large_switch_direct(self): rgenop = self.RGenOp() - gv_switchfn = make_large_switch(rgenop) + gv_switchfn = make_large_switch(self.T, rgenop) fnptr = self.cast(gv_switchfn, 2) res = fnptr(0, 2) assert res == 42 @@ -1044,7 +1051,7 @@ assert res == 16 def test_large_switch_compile(self): - fn = self.compile(get_large_switch_runner(self.RGenOp), [int, int]) + fn = self.compile(get_large_switch_runner(self.T, self.RGenOp), [int, int]) res = fn(0, 2) assert res == 42 for x in range(1,11): @@ -1055,7 +1062,7 @@ def test_fact_direct(self): rgenop = self.RGenOp() - gv_fact = make_fact(rgenop) + gv_fact = make_fact(self.T, rgenop) fnptr = self.cast(gv_fact, 1) res = fnptr(2) assert res == 2 @@ -1063,7 +1070,7 @@ assert res == 3628800 def test_fact_compile(self): - fn = self.compile(get_fact_runner(self.RGenOp), [int]) + fn = self.compile(get_fact_runner(self.T, self.RGenOp), [int]) res = fn(2) assert res == 2 res = fn(11) @@ -1071,7 +1078,7 @@ def test_calling_pause_direct(self): rgenop = self.RGenOp() - gv_abs = make_func_calling_pause(rgenop) + gv_abs = make_func_calling_pause(self.T, rgenop) fnptr = self.cast(gv_abs, 1) res = fnptr(2) assert res == 2 @@ -1079,7 +1086,7 @@ assert res == 42 def test_calling_pause_compile(self): - fn = self.compile(get_func_calling_pause_runner(self.RGenOp), [int]) + fn = self.compile(get_func_calling_pause_runner(self.T, self.RGenOp), [int]) res = fn(2) assert res == 2 res = fn(-72) @@ -1087,7 +1094,7 @@ def test_longwinded_and_direct(self): rgenop = self.RGenOp() - gv_fn = make_longwinded_and(rgenop) + gv_fn = make_longwinded_and(self.T, rgenop) fnptr = self.cast(gv_fn, 1) res = fnptr(1) @@ -1107,7 +1114,7 @@ def test_condition_result_cross_link_direct(self): rgenop = self.RGenOp() - gv_fn = make_condition_result_cross_link(rgenop) + gv_fn = make_condition_result_cross_link(self.T, rgenop) fnptr = self.cast(gv_fn, 1) res = fnptr(-1) @@ -1124,7 +1131,7 @@ # return x>y + 10*x=y + 10000*x==y + 100000*x!=y rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(self.T.FUNC2) builder, gv_callable, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "multicmp") builder.start_writing() @@ -1176,7 +1183,7 @@ # 1>x + 10*(1=x) + 1000*(1<=x) + 10000*(1==x) + 100000*(1!=x) rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_callable, [gv_x] = rgenop.newgraph(sigtoken, "multicmp") builder.start_writing() @@ -1231,7 +1238,7 @@ # return x rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_callable, [gv_x] = rgenop.newgraph(sigtoken, "tightloop") builder.start_writing() @@ -1258,7 +1265,7 @@ def test_jump_to_block_with_many_vars(self): rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_verysmall_callable, [gv_x] = rgenop.newgraph(sigtoken, "verysmall") builder.start_writing() @@ -1300,7 +1307,7 @@ def test_same_as(self): rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_callable, [gv_x] = rgenop.newgraph(sigtoken, "sameas") builder.start_writing() gv_nineteen = builder.genop_same_as(signed_kind, rgenop.genconst(19)) @@ -1315,7 +1322,7 @@ def test_pause_and_resume_direct(self): rgenop = self.RGenOp() - gv_callable = make_pause_and_resume(rgenop) + gv_callable = make_pause_and_resume(self.T, rgenop) fnptr = self.cast(gv_callable, 1) res = fnptr(1) @@ -1328,7 +1335,7 @@ assert res == 8 def test_pause_and_resume_compile(self): - fn = self.compile(get_pause_and_resume_runner(self.RGenOp), [int]) + fn = self.compile(get_pause_and_resume_runner(self.T, self.RGenOp), [int]) res = fn(1) assert res == 0 @@ -1341,7 +1348,7 @@ def test_like_residual_red_call_with_exc_direct(self): rgenop = self.RGenOp() - gv_callable = make_something_a_bit_like_residual_red_call_with_exc(rgenop) + gv_callable = make_something_a_bit_like_residual_red_call_with_exc(self.T, rgenop) fnptr = self.cast(gv_callable, 2) res = fnptr(1, 3) @@ -1352,7 +1359,7 @@ def test_call_functions_with_different_signatures_direct(self): rgenop = self.RGenOp() - gv_callable = make_call_functions_with_different_signatures(rgenop) + gv_callable = make_call_functions_with_different_signatures(self.T, rgenop) fnptr = self.cast(gv_callable, 2) res = fnptr(1, 3) @@ -1364,7 +1371,7 @@ def test_defaultonly_switch(self): rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_callable, [gv_x] = rgenop.newgraph(sigtoken, "defaultonly") builder.start_writing() flexswitch, default_builder = builder.flexswitch(gv_x, [gv_x]) @@ -1380,7 +1387,7 @@ rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) bool_kind = rgenop.kindToken(lltype.Bool) - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_callable, [gv_x] = rgenop.newgraph(sigtoken, "bool_not") builder.start_writing() gv_cond = builder.genop2("int_lt", gv_x, rgenop.genconst(10)) @@ -1407,13 +1414,13 @@ return reader_ptr rgenop = self.RGenOp() - gv_callable = make_read_frame_var(rgenop, get_reader) + gv_callable = make_read_frame_var(self.T, rgenop, get_reader) fnptr = self.cast(gv_callable, 1) res = fnptr(20) assert res == 40 def test_read_frame_var_compile(self): - fn = self.compile(get_read_frame_var_runner(self.RGenOp), [int]) + fn = self.compile(get_read_frame_var_runner(self.T, self.RGenOp), [int]) res = fn(30) assert res == 60 @@ -1426,7 +1433,7 @@ return writer_ptr rgenop = self.RGenOp() - gv_callable = make_write_frame_place(rgenop, get_writer) + gv_callable = make_write_frame_place(self.T, rgenop, get_writer) fnptr = self.cast(gv_callable, 1) res = fnptr(3) assert res == -100 - 30 @@ -1434,7 +1441,7 @@ assert res == 42 - 60 def test_write_frame_place_compile(self): - fn = self.compile(get_write_frame_place_runner(self.RGenOp), [int]) + fn = self.compile(get_write_frame_place_runner(self.T, self.RGenOp), [int]) res = fn(-42) assert res == -100 - (-420) res = fn(606) @@ -1448,7 +1455,7 @@ return writer_ptr rgenop = self.RGenOp() - gv_callable = make_write_lots_of_frame_places(rgenop, get_writer) + gv_callable = make_write_lots_of_frame_places(self.T, rgenop, get_writer) fnptr = self.cast(gv_callable, 1) res = fnptr(3) assert res == sum(range(3, 103)) @@ -1463,19 +1470,19 @@ return reader_ptr rgenop = self.RGenOp() - gv_callable = make_read_frame_place(rgenop, get_reader) + gv_callable = make_read_frame_place(self.T, rgenop, get_reader) fnptr = self.cast(gv_callable, 1) res = fnptr(-1) assert res == 42 def test_read_frame_place_compile(self): - fn = self.compile(get_read_frame_place_runner(self.RGenOp), [int]) + fn = self.compile(get_read_frame_place_runner(self.T, self.RGenOp), [int]) res = fn(-1) assert res == 42 def test_frame_vars_like_the_frontend_direct(self): rgenop = self.RGenOp() - sigtoken = rgenop.sigToken(FUNC3) + sigtoken = rgenop.sigToken(self.T.FUNC3) signed_kind = rgenop.kindToken(lltype.Signed) # ------------------------------------------ builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph(sigtoken, @@ -1518,7 +1525,7 @@ rgenop = self.RGenOp() signed_kind = rgenop.kindToken(lltype.Signed) - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(self.T.FUNC2) builder, gv_callable, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "f") builder.start_writing() @@ -1565,7 +1572,7 @@ signed_kind = rgenop.kindToken(lltype.Signed) bool_kind = rgenop.kindToken(lltype.Bool) - builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph(rgenop.sigToken(FUNC3), 'compiled_dummyfn') + builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph(rgenop.sigToken(self.T.FUNC3), 'compiled_dummyfn') builder0.start_writing() args_gv = [v0, v1] @@ -1597,7 +1604,7 @@ v17 = builder3.genop1('cast_bool_to_int', v14) v18 = builder3.genop2('int_mul', v17, rgenop.genconst(-340864157)) v19 = builder3.genop2('int_add', v16, v18) - builder3.finish_and_return(rgenop.sigToken(FUNC3), v19) + builder3.finish_and_return(rgenop.sigToken(self.T.FUNC3), v19) builder1.start_writing() builder1.finish_and_goto([v3, v4, rgenop.genconst(False)], label1) @@ -1624,7 +1631,7 @@ signed_kind = rgenop.kindToken(lltype.Signed) bool_kind = rgenop.kindToken(lltype.Bool) - builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph(rgenop.sigToken(FUNC3), 'compiled_dummyfn') + builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph(rgenop.sigToken(self.T.FUNC3), 'compiled_dummyfn') builder0.start_writing() v3 = builder0.genop1('int_is_true', v1) @@ -1653,7 +1660,7 @@ builder3.finish_and_goto([v14, v6, v7, v4], label1) builder2.start_writing() - builder2.finish_and_return(rgenop.sigToken(FUNC3), v5) + builder2.finish_and_return(rgenop.sigToken(self.T.FUNC3), v5) builder2.end() fnptr = self.cast(gv_callable, 3) @@ -1679,11 +1686,11 @@ signed_kind = rgenop.kindToken(lltype.Signed) bool_kind = rgenop.kindToken(lltype.Bool) - builder0, gv_callable, [v0, v1, v2, v3, v4] = rgenop.newgraph(rgenop.sigToken(FUNC5), 'compiled_dummyfn') + builder0, gv_callable, [v0, v1, v2, v3, v4] = rgenop.newgraph(rgenop.sigToken(self.T.FUNC5), 'compiled_dummyfn') builder0.start_writing() v5 = builder0.genop1('int_is_true', v0) builder1 = builder0.jump_if_true(v5, [v0, v1, v3, v2]) - builder0.finish_and_return(rgenop.sigToken(FUNC5), rgenop.genconst(0)) + builder0.finish_and_return(rgenop.sigToken(self.T.FUNC5), rgenop.genconst(0)) builder1.start_writing() @@ -1734,7 +1741,7 @@ v32 = builder5.genop1('cast_bool_to_int', v26) v33 = builder5.genop2('int_mul', rgenop.genconst(2), v32) v34 = builder5.genop2('int_add', v31, v33) - builder5.finish_and_return(rgenop.sigToken(FUNC5), v34) + builder5.finish_and_return(rgenop.sigToken(self.T.FUNC5), v34) builder5.end() fnptr = self.cast(gv_callable, 5) @@ -1748,7 +1755,7 @@ bool_kind = rgenop.kindToken(lltype.Bool) builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph( - rgenop.sigToken(FUNC3), 'compiled_dummyfn') + rgenop.sigToken(self.T.FUNC3), 'compiled_dummyfn') builder0.start_writing() @@ -1778,7 +1785,7 @@ label4 = builder1.enter_next_block([signed_kind, signed_kind, signed_kind], args_gv) [v26, v27, v28] = args_gv - builder1.finish_and_return(rgenop.sigToken(FUNC3), v27) + builder1.finish_and_return(rgenop.sigToken(self.T.FUNC3), v27) builder2.start_writing() v33 = builder2.genop2('int_sub', v8, rgenop.genconst(1)) @@ -1828,7 +1835,7 @@ signed_kind = rgenop.kindToken(lltype.Signed) bool_kind = rgenop.kindToken(lltype.Bool) - builder0, gv_callable, [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26] = rgenop.newgraph(rgenop.sigToken(FUNC27), 'compiled_dummyfn') + builder0, gv_callable, [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26] = rgenop.newgraph(rgenop.sigToken(self.T.FUNC27), 'compiled_dummyfn') builder0.start_writing() args_gv = [v0, v1, v2, v3, v6, v8, v9, v10, v11, v12, v13, v14, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26] label0 = builder0.enter_next_block([signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind, signed_kind], args_gv) @@ -1916,7 +1923,7 @@ v235 = builder0.genop2('int_add', v233, v234) v236 = builder0.genop2('int_mul', v181, rgenop.genconst(-1563822213)) v237 = builder0.genop2('int_add', v235, v236) - builder0.finish_and_return(rgenop.sigToken(FUNC27), v237) + builder0.finish_and_return(rgenop.sigToken(self.T.FUNC27), v237) builder2.start_writing() builder2.finish_and_goto([v51, v52, v53, v54, v55, v58, v56, v57, v58, v59, v60, v61, v62, v63, v64, v65, v66, v67, v68, v69, v70, v71, v72, v73], label2) builder4.start_writing() @@ -1941,13 +1948,13 @@ RGenOp = self.RGenOp gv = RGenOp.genzeroconst(RGenOp.kindToken(lltype.Signed)) assert gv.revealconst(lltype.Signed) == 0 - P = lltype.Ptr(lltype.Struct('S')) + P = self.T.Ptr(lltype.Struct('S')) gv = RGenOp.genzeroconst(RGenOp.kindToken(P)) assert gv.revealconst(llmemory.Address) == llmemory.NULL def test_ovfcheck_adder_direct(self): rgenop = self.RGenOp() - gv_add_5 = make_ovfcheck_adder(rgenop, 5) + gv_add_5 = make_ovfcheck_adder(self.T, rgenop, 5) fnptr = self.cast(gv_add_5, 1) res = fnptr(37) assert res == (42 << 1) | 0 @@ -1955,7 +1962,7 @@ assert (res & 1) == 1 def test_ovfcheck_adder_compile(self): - fn = self.compile(get_ovfcheck_adder_runner(self.RGenOp), [int, int]) + fn = self.compile(get_ovfcheck_adder_runner(self.T, self.RGenOp), [int, int]) res = fn(9080983, -9080941) assert res == (42 << 1) | 0 res = fn(-sys.maxint, -10) @@ -1975,7 +1982,7 @@ def ovfcheck1_direct(self, opname, testcases): rgenop = self.RGenOp() - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "ovfcheck1") builder.start_writing() gv_result, gv_flag = builder.genraisingop1(opname, gv_x) @@ -2022,7 +2029,7 @@ def ovfcheck2_direct(self, opname, testcases): rgenop = self.RGenOp() - sigtoken = rgenop.sigToken(FUNC2) + sigtoken = rgenop.sigToken(self.T.FUNC2) builder, gv_fn, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "ovfcheck2") builder.start_writing() gv_result, gv_flag = builder.genraisingop2(opname, gv_x, gv_y) @@ -2055,13 +2062,13 @@ def cast_direct(self, operations, expected, max=r_uint(-1)): need_odd_integer = False rgenop = self.RGenOp() - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "cast") builder.start_writing() for opname in operations: if opname == "cast_int_to_ptr": S = lltype.GcStruct('s', ('x', lltype.Signed)) - ptrkind = rgenop.kindToken(lltype.Ptr(S)) + ptrkind = rgenop.kindToken(self.T.Ptr(S)) gv_x = builder.genop_cast_int_to_ptr(ptrkind, gv_x) need_odd_integer = True else: @@ -2082,13 +2089,12 @@ py.test.skip("requires RGenOpPacked") rgenop = self.RGenOpPacked() A = lltype.GcArray(lltype.Signed) - FUNC3 = lltype.FuncType([lltype.Signed]*3, lltype.Signed) varsizealloctoken = rgenop.varsizeAllocToken(A) arraytoken = rgenop.arrayToken(A) signed_kind = rgenop.kindToken(lltype.Signed) # ------------------------------------------------------------ builder0, gv_callable, [v0, v1, v2] = rgenop.newgraph( - rgenop.sigToken(FUNC3), 'generated') + rgenop.sigToken(self.T.FUNC3), 'generated') builder0.start_writing() v3 = builder0.genop_malloc_varsize(varsizealloctoken, rgenop.genconst(2)) @@ -2113,7 +2119,7 @@ args_gv = [v8] label1 = builder4.enter_next_block([signed_kind], args_gv) [v9] = args_gv - builder4.finish_and_return(rgenop.sigToken(FUNC3), v9) + builder4.finish_and_return(rgenop.sigToken(self.T.FUNC3), v9) builder0.end() fnptr = self.cast(gv_callable, 3) @@ -2128,11 +2134,11 @@ # lloperation in the llgraphs. if self.RGenOpPacked is None: py.test.skip("requires RGenOpPacked") - T = lltype.Struct('T', ('x', lltype.Signed)) - A = lltype.Array(T) + X = lltype.Struct('X', ('x', lltype.Signed)) + A = lltype.Array(X) S = lltype.GcStruct('S', ('a', A)) rgenop = self.RGenOpPacked() - sigtoken = rgenop.sigToken(FUNC) + sigtoken = rgenop.sigToken(self.T.FUNC) builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "interior_access") builder.start_writing() gv_s = builder.genop_malloc_varsize(rgenop.varsizeAllocToken(S), @@ -2141,12 +2147,12 @@ gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s) gv_t1 = builder.genop_getarraysubstruct(rgenop.arrayToken(A), gv_a1, rgenop.genconst(3)) - builder.genop_setfield(rgenop.fieldToken(T, 'x'), gv_t1, gv_x) + builder.genop_setfield(rgenop.fieldToken(X, 'x'), gv_t1, gv_x) # generate an expanded 'getinteriorfield' gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s) gv_t1 = builder.genop_getarraysubstruct(rgenop.arrayToken(A), gv_a1, rgenop.genconst(3)) - gv_y = builder.genop_getfield(rgenop.fieldToken(T, 'x'), gv_t1) + gv_y = builder.genop_getfield(rgenop.fieldToken(X, 'x'), gv_t1) # generate an expanded 'getinteriorarraysize' gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s) gv_z = builder.genop_getarraysize(rgenop.arrayToken(A), gv_a1)